Merge "Part of fix for bug 4997380: Some error types unknown to SslError"
diff --git a/Android.mk b/Android.mk
index 335fb73..5cb4d30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -93,6 +93,7 @@
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
 	core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
+	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
 	core/java/android/content/IClipboard.aidl \
 	core/java/android/content/IContentService.aidl \
 	core/java/android/content/IIntentReceiver.aidl \
@@ -158,6 +159,11 @@
 	core/java/com/android/internal/os/IResultReceiver.aidl \
 	core/java/com/android/internal/statusbar/IStatusBar.aidl \
 	core/java/com/android/internal/statusbar/IStatusBarService.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
+	core/java/com/android/internal/textservice/ITextServicesManager.aidl \
+	core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
 	core/java/com/android/internal/view/IInputContext.aidl \
 	core/java/com/android/internal/view/IInputContextCallback.aidl \
 	core/java/com/android/internal/view/IInputMethod.aidl \
@@ -190,6 +196,7 @@
 	telephony/java/com/android/internal/telephony/ISms.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
+	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \
 	voip/java/android/net/sip/ISipSession.aidl \
 	voip/java/android/net/sip/ISipSessionListener.aidl \
@@ -266,6 +273,11 @@
 	frameworks/base/core/java/android/view/Surface.aidl \
 	frameworks/base/core/java/android/view/WindowManager.aidl \
 	frameworks/base/core/java/android/widget/RemoteViews.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ITextServicesManager.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputContext.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputMethod.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputMethodCallback.aidl \
@@ -457,7 +469,7 @@
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=3.1
+framework_docs_SDK_VERSION:=3.2
   # release version (ie "Release x")  (full releases only)
 framework_docs_SDK_REL_ID:=1
 
diff --git a/api/14.txt b/api/14.txt
index ad8e1c5..895c44d 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -19820,8 +19820,8 @@
     field public static final java.util.regex.Pattern IP_ADDRESS;
     field public static final java.util.regex.Pattern PHONE;
     field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN;
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)|y[et]|z[amw])";
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)|y[et]|z[amw]))";
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
     field public static final java.util.regex.Pattern WEB_URL;
   }
 
diff --git a/api/current.txt b/api/current.txt
index 2e1ad7f..4135b5d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
@@ -82,6 +83,7 @@
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
+    field public static final java.lang.String READ_WRITE_OWN_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
     field public static final java.lang.String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
@@ -115,6 +117,7 @@
     field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
     field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
     field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
+    field public static final java.lang.String VPN = "android.permission.VPN";
     field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK";
     field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
     field public static final java.lang.String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
@@ -183,14 +186,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 = 16843649; // 0x1010381
-    field public static final int accessibilityFeedbackType = 16843651; // 0x1010383
-    field public static final int accessibilityFlags = 16843653; // 0x1010385
+    field public static final int accessibilityEventTypes = 16843646; // 0x101037e
+    field public static final int accessibilityFeedbackType = 16843648; // 0x1010380
+    field public static final int accessibilityFlags = 16843650; // 0x1010382
     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 actionBarSplitStyle = 16843668; // 0x1010394
     field public static final int actionBarStyle = 16843470; // 0x10102ce
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -206,9 +209,10 @@
     field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
     field public static final int actionModeCutDrawable = 16843537; // 0x1010311
     field public static final int actionModePasteDrawable = 16843539; // 0x1010313
-    field public static final int actionModeSelectAllDrawable = 16843647; // 0x101037f
+    field public static final int actionModeSelectAllDrawable = 16843644; // 0x101037c
+    field public static final int actionModeStyle = 16843680; // 0x10103a0
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
-    field public static final int actionProviderClass = 16843677; // 0x101039d
+    field public static final int actionProviderClass = 16843669; // 0x1010395
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -220,7 +224,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 = 16843641; // 0x1010379
+    field public static final int alignmentMode = 16843638; // 0x1010376
     field public static final int allContactsName = 16843468; // 0x10102cc
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -254,8 +258,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 backgroundSplit = 16843671; // 0x1010397
+    field public static final int backgroundStacked = 16843670; // 0x1010396
     field public static final int backupAgent = 16843391; // 0x101027f
     field public static final int baseline = 16843548; // 0x101031c
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -264,7 +268,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 = 16843660; // 0x101038c
+    field public static final int bottomChevronDrawable = 16843657; // 0x1010389
     field public static final int bottomDark = 16842953; // 0x10100c9
     field public static final int bottomLeftRadius = 16843179; // 0x10101ab
     field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -283,7 +287,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 = 16843654; // 0x1010386
+    field public static final int canRetrieveWindowContent = 16843651; // 0x1010383
     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
@@ -312,18 +316,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 colorActivatedHighlight = 16843676; // 0x101039c
     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 colorFocusedHighlight = 16843675; // 0x101039b
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
-    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 colorLongPressedHighlight = 16843674; // 0x101039a
+    field public static final int colorMultiSelectHighlight = 16843677; // 0x101039d
+    field public static final int colorPressedHighlight = 16843673; // 0x1010399
+    field public static final int columnCount = 16843635; // 0x1010373
     field public static final int columnDelay = 16843215; // 0x10101cf
-    field public static final int columnOrderPreserved = 16843639; // 0x1010377
+    field public static final int columnOrderPreserved = 16843636; // 0x1010374
     field public static final int columnWidth = 16843031; // 0x1010117
     field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
     field public static final int completionHint = 16843122; // 0x1010172
@@ -377,11 +381,11 @@
     field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
     field public static final int drawable = 16843161; // 0x1010199
     field public static final int drawableBottom = 16843118; // 0x101016e
-    field public static final int drawableEnd = 16843687; // 0x10103a7
+    field public static final int drawableEnd = 16843679; // 0x101039f
     field public static final int drawableLeft = 16843119; // 0x101016f
     field public static final int drawablePadding = 16843121; // 0x1010171
     field public static final int drawableRight = 16843120; // 0x1010170
-    field public static final int drawableStart = 16843686; // 0x10103a6
+    field public static final int drawableStart = 16843678; // 0x101039e
     field public static final int drawableTop = 16843117; // 0x101016d
     field public static final int drawingCacheQuality = 16842984; // 0x10100e8
     field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -438,7 +442,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 = 16843666; // 0x1010392
+    field public static final int feedbackCount = 16843663; // 0x101038f
     field public static final int fillAfter = 16843197; // 0x10101bd
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillEnabled = 16843343; // 0x101024f
@@ -491,7 +495,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 = 16843656; // 0x1010388
+    field public static final int handleDrawable = 16843653; // 0x1010385
     field public static final int handleProfiling = 16842786; // 0x1010022
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -500,12 +504,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 = 16843663; // 0x101038f
+    field public static final int hitRadius = 16843660; // 0x101038c
     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 = 16843668; // 0x1010394
+    field public static final int horizontalOffset = 16843665; // 0x1010391
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
@@ -551,7 +555,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 = 16843648; // 0x1010380
+    field public static final int isAuxiliary = 16843645; // 0x101037d
     field public static final int isDefault = 16843297; // 0x1010221
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
@@ -588,7 +592,6 @@
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
-    field public static final int layoutDirection = 16843634; // 0x1010372
     field public static final int layout_above = 16843140; // 0x1010184
     field public static final int layout_alignBaseline = 16843142; // 0x1010186
     field public static final int layout_alignBottom = 16843146; // 0x101018a
@@ -605,20 +608,18 @@
     field public static final int layout_centerInParent = 16843151; // 0x101018f
     field public static final int layout_centerVertical = 16843153; // 0x1010191
     field public static final int layout_column = 16843084; // 0x101014c
-    field public static final int layout_columnFlexibility = 16843646; // 0x101037e
-    field public static final int layout_columnSpan = 16843645; // 0x101037d
+    field public static final deprecated int layout_columnFlexibility = 16843643; // 0x101037b
+    field public static final int layout_columnSpan = 16843642; // 0x101037a
     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 = 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_row = 16843639; // 0x1010377
+    field public static final deprecated int layout_rowFlexibility = 16843641; // 0x1010379
+    field public static final int layout_rowSpan = 16843640; // 0x1010378
     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
@@ -628,7 +629,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
-    field public static final int leftChevronDrawable = 16843657; // 0x1010389
+    field public static final int leftChevronDrawable = 16843654; // 0x1010386
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -640,8 +641,8 @@
     field public static final int listDividerAlertDialog = 16843525; // 0x1010305
     field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
-    field public static final int listPreferredItemHeightLarge = 16843669; // 0x1010395
-    field public static final int listPreferredItemHeightSmall = 16843670; // 0x1010396
+    field public static final int listPreferredItemHeightLarge = 16843666; // 0x1010392
+    field public static final int listPreferredItemHeightSmall = 16843667; // 0x1010393
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -672,6 +673,8 @@
     field public static final int minHeight = 16843072; // 0x1010140
     field public static final int minLevel = 16843185; // 0x10101b1
     field public static final int minLines = 16843094; // 0x1010156
+    field public static final int minResizeHeight = 16843682; // 0x10103a2
+    field public static final int minResizeWidth = 16843681; // 0x10103a1
     field public static final int minSdkVersion = 16843276; // 0x101020c
     field public static final int minWidth = 16843071; // 0x101013f
     field public static final int mode = 16843134; // 0x101017e
@@ -687,7 +690,7 @@
     field public static final int nextFocusUp = 16842979; // 0x10100e3
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
-    field public static final int notificationTimeout = 16843652; // 0x1010384
+    field public static final int notificationTimeout = 16843649; // 0x1010381
     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
@@ -701,17 +704,15 @@
     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 = 16843662; // 0x101038e
+    field public static final int outerRadius = 16843659; // 0x101038b
     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 = 16843650; // 0x1010382
+    field public static final int packageNames = 16843647; // 0x101037f
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
-    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 = 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
@@ -792,17 +793,17 @@
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int right = 16843183; // 0x10101af
-    field public static final int rightChevronDrawable = 16843658; // 0x101038a
+    field public static final int rightChevronDrawable = 16843655; // 0x1010387
     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 = 16843636; // 0x1010374
+    field public static final int rowCount = 16843633; // 0x1010371
     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 = 16843637; // 0x1010375
+    field public static final int rowOrderPreserved = 16843634; // 0x1010372
     field public static final int saveEnabled = 16842983; // 0x10100e7
     field public static final int scaleGravity = 16843262; // 0x10101fe
     field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -868,7 +869,7 @@
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
-    field public static final int snapMargin = 16843665; // 0x1010391
+    field public static final int snapMargin = 16843662; // 0x101038e
     field public static final int soundEffectsEnabled = 16843285; // 0x1010215
     field public static final int spacing = 16843027; // 0x1010113
     field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -916,7 +917,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 = 16843635; // 0x1010373
+    field public static final int suggestionsEnabled = 16843632; // 0x1010370
     field public static final int summary = 16843241; // 0x10101e9
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
@@ -933,7 +934,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 = 16843655; // 0x1010387
+    field public static final int targetDrawables = 16843652; // 0x1010384
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
@@ -948,7 +949,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 textAllCaps = 16843672; // 0x1010398
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
     field public static final int textAppearanceInverse = 16842805; // 0x1010035
@@ -985,14 +986,11 @@
     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
     field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
-    field public static final int textEditSuggestionItemLayout = 16843633; // 0x1010371
-    field public static final int textEditSuggestionsBottomWindowLayout = 16843631; // 0x101036f
-    field public static final int textEditSuggestionsTopWindowLayout = 16843632; // 0x1010370
+    field public static final int textEditSuggestionItemLayout = 16843631; // 0x101036f
     field public static final int textFilterEnabled = 16843007; // 0x10100ff
     field public static final int textIsSelectable = 16843542; // 0x1010316
     field public static final int textOff = 16843045; // 0x1010125
@@ -1025,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 = 16843659; // 0x101038b
+    field public static final int topChevronDrawable = 16843656; // 0x1010388
     field public static final int topDark = 16842951; // 0x10100c7
     field public static final int topLeftRadius = 16843177; // 0x10101a9
     field public static final int topOffset = 16843352; // 0x1010258
@@ -1041,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 = 16843640; // 0x1010378
+    field public static final int useDefaultMargins = 16843637; // 0x1010375
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -1055,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 = 16843667; // 0x1010393
+    field public static final int verticalOffset = 16843664; // 0x1010390
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int vibrationDuration = 16843664; // 0x1010390
+    field public static final int vibrationDuration = 16843661; // 0x101038d
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1075,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 = 16843661; // 0x101038d
+    field public static final int waveDrawable = 16843658; // 0x101038a
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -1823,12 +1821,14 @@
     method public static java.lang.String feedbackTypeToString(int);
     method public static java.lang.String flagToString(int);
     method public boolean getCanRetrieveWindowContent();
+    method public java.lang.String getDescription();
     method public java.lang.String getId();
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int DEFAULT = 1; // 0x1
+    field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
     field public static final int FEEDBACK_AUDIBLE = 4; // 0x4
     field public static final int FEEDBACK_GENERIC = 16; // 0x10
     field public static final int FEEDBACK_HAPTIC = 2; // 0x2
@@ -2256,7 +2256,6 @@
     method public abstract void setCustomView(android.view.View);
     method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
     method public abstract void setCustomView(int);
-    method public abstract void setDisplayDisableHomeEnabled(boolean);
     method public abstract void setDisplayHomeAsUpEnabled(boolean);
     method public abstract void setDisplayOptions(int);
     method public abstract void setDisplayOptions(int, int);
@@ -2264,6 +2263,7 @@
     method public abstract void setDisplayShowHomeEnabled(boolean);
     method public abstract void setDisplayShowTitleEnabled(boolean);
     method public abstract void setDisplayUseLogoEnabled(boolean);
+    method public abstract void setHomeButtonEnabled(boolean);
     method public abstract void setIcon(int);
     method public abstract void setIcon(android.graphics.drawable.Drawable);
     method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
@@ -2276,7 +2276,6 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitle(int);
     method public abstract void show();
-    field public static final int DISPLAY_DISABLE_HOME = 32; // 0x20
     field public static final int DISPLAY_HOME_AS_UP = 4; // 0x4
     field public static final int DISPLAY_SHOW_CUSTOM = 16; // 0x10
     field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
@@ -3928,6 +3927,8 @@
     field public int initialLayout;
     field public java.lang.String label;
     field public int minHeight;
+    field public int minResizeHeight;
+    field public int minResizeWidth;
     field public int minWidth;
     field public int previewImage;
     field public android.content.ComponentName provider;
@@ -4784,6 +4785,7 @@
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
+    field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
     field public static final java.lang.String UI_MODE_SERVICE = "uimode";
     field public static final java.lang.String USB_SERVICE = "usb";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
@@ -8904,6 +8906,8 @@
     method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
     method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
     method public final void unlock();
+    field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+    field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
     field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
   }
@@ -8938,6 +8942,8 @@
     method public java.lang.String flatten();
     method public java.lang.String get(java.lang.String);
     method public java.lang.String getAntibanding();
+    method public boolean getAutoExposureLock();
+    method public boolean getAutoWhiteBalanceLock();
     method public java.lang.String getColorEffect();
     method public int getExposureCompensation();
     method public float getExposureCompensationStep();
@@ -8983,6 +8989,8 @@
     method public java.lang.String getWhiteBalance();
     method public int getZoom();
     method public java.util.List<java.lang.Integer> getZoomRatios();
+    method public boolean isAutoExposureLockSupported();
+    method public boolean isAutoWhiteBalanceLockSupported();
     method public boolean isSmoothZoomSupported();
     method public boolean isZoomSupported();
     method public void remove(java.lang.String);
@@ -8990,6 +8998,8 @@
     method public void set(java.lang.String, java.lang.String);
     method public void set(java.lang.String, int);
     method public void setAntibanding(java.lang.String);
+    method public void setAutoExposureLock(boolean);
+    method public void setAutoWhiteBalanceLock(boolean);
     method public void setColorEffect(java.lang.String);
     method public void setExposureCompensation(int);
     method public void setFlashMode(java.lang.String);
@@ -10397,8 +10407,8 @@
     method public void setAudioEncodingBitRate(int);
     method public void setAudioSamplingRate(int);
     method public void setAudioSource(int) throws java.lang.IllegalStateException;
-    method public void setAuxiliaryOutputFile(java.io.FileDescriptor);
-    method public void setAuxiliaryOutputFile(java.lang.String);
+    method public deprecated void setAuxiliaryOutputFile(java.io.FileDescriptor);
+    method public deprecated void setAuxiliaryOutputFile(java.lang.String);
     method public void setCamera(android.hardware.Camera);
     method public void setCaptureRate(double);
     method public void setLocation(float, float);
@@ -11278,6 +11288,7 @@
     method public static long getMobileRxPackets();
     method public static long getMobileTxBytes();
     method public static long getMobileTxPackets();
+    method public static int getThreadStatsTag();
     method public static long getTotalRxBytes();
     method public static long getTotalRxPackets();
     method public static long getTotalTxBytes();
@@ -11435,6 +11446,26 @@
     method public abstract java.lang.String sanitize(java.lang.String);
   }
 
+  public class VpnBuilder {
+    ctor public VpnBuilder();
+    method public android.net.VpnBuilder addAddress(java.lang.String, int);
+    method public android.net.VpnBuilder addAddress(java.net.InetAddress, int);
+    method public android.net.VpnBuilder addDnsServer(java.lang.String);
+    method public android.net.VpnBuilder addDnsServer(java.net.InetAddress);
+    method public android.net.VpnBuilder addRoute(java.lang.String, int);
+    method public android.net.VpnBuilder addRoute(java.net.InetAddress, int);
+    method public android.net.VpnBuilder addSearchDomain(java.lang.String);
+    method public android.os.ParcelFileDescriptor establish();
+    method public static android.content.Intent prepare(android.content.Context);
+    method public static boolean protect(int);
+    method public static boolean protect(java.net.Socket);
+    method public static boolean protect(java.net.DatagramSocket);
+    method public android.net.VpnBuilder setConfigureIntent(android.app.PendingIntent);
+    method public android.net.VpnBuilder setMtu(int);
+    method public android.net.VpnBuilder setSession(java.lang.String);
+    field public static final java.lang.String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
+  }
+
 }
 
 package android.net.http {
@@ -11905,6 +11936,7 @@
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
     field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -11960,6 +11992,8 @@
   public final class NdefRecord implements android.os.Parcelable {
     ctor public NdefRecord(short, byte[], byte[], byte[]);
     ctor public NdefRecord(byte[]) throws android.nfc.FormatException;
+    method public static android.nfc.NdefRecord createUri(android.net.Uri);
+    method public static android.nfc.NdefRecord createUri(java.lang.String);
     method public int describeContents();
     method public byte[] getId();
     method public byte[] getPayload();
@@ -13922,6 +13956,10 @@
   public static class Debug.MemoryInfo implements android.os.Parcelable {
     ctor public Debug.MemoryInfo();
     method public int describeContents();
+    method public static java.lang.String getOtherLabel(int);
+    method public int getOtherPrivateDirty(int);
+    method public int getOtherPss(int);
+    method public int getOtherSharedDirty(int);
     method public int getTotalPrivateDirty();
     method public int getTotalPss();
     method public int getTotalSharedDirty();
@@ -14030,6 +14068,7 @@
     method public void dispatchMessage(android.os.Message);
     method public final void dump(android.util.Printer, java.lang.String);
     method public final android.os.Looper getLooper();
+    method public java.lang.String getMessageName(android.os.Message);
     method public void handleMessage(android.os.Message);
     method public final boolean hasMessages(int);
     method public final boolean hasMessages(int, java.lang.Object);
@@ -14099,13 +14138,13 @@
 
   public class Looper {
     method public void dump(android.util.Printer, java.lang.String);
-    method public static final synchronized android.os.Looper getMainLooper();
+    method public static synchronized android.os.Looper getMainLooper();
     method public java.lang.Thread getThread();
-    method public static final void loop();
-    method public static final android.os.Looper myLooper();
-    method public static final android.os.MessageQueue myQueue();
-    method public static final void prepare();
-    method public static final void prepareMainLooper();
+    method public static void loop();
+    method public static android.os.Looper myLooper();
+    method public static android.os.MessageQueue myQueue();
+    method public static void prepare();
+    method public static void prepareMainLooper();
     method public void quit();
     method public void setMessageLogging(android.util.Printer);
   }
@@ -14420,6 +14459,7 @@
   public class RecoverySystem {
     ctor public RecoverySystem();
     method public static void installPackage(android.content.Context, java.io.File) throws java.io.IOException;
+    method public static void rebootWipeCache(android.content.Context) throws java.io.IOException;
     method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
     method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
   }
@@ -15289,6 +15329,7 @@
     field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
     field public static final java.lang.String DURATION = "duration";
     field public static final int INCOMING_TYPE = 1; // 0x1
+    field public static final java.lang.String IS_READ = "is_read";
     field public static final int MISSED_TYPE = 3; // 0x3
     field public static final java.lang.String NEW = "new";
     field public static final java.lang.String NUMBER = "number";
@@ -15752,6 +15793,7 @@
   public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
     field public static final java.lang.String PHOTO = "data15";
+    field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
 
   public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
@@ -15862,6 +15904,7 @@
     method public static android.net.Uri getLookupUri(long, java.lang.String);
     method public static android.net.Uri lookupContact(android.content.ContentResolver, android.net.Uri);
     method public static void markAsContacted(android.content.ContentResolver, long);
+    method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final android.net.Uri CONTENT_GROUP_URI;
@@ -15891,7 +15934,9 @@
 
   public static final class ContactsContract.Contacts.Photo implements android.provider.BaseColumns android.provider.ContactsContract.DataColumnsWithJoins {
     field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final java.lang.String DISPLAY_PHOTO = "display_photo";
     field public static final java.lang.String PHOTO = "data15";
+    field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
 
   public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
@@ -15904,6 +15949,7 @@
     field public static final java.lang.String IN_VISIBLE_GROUP = "in_visible_group";
     field public static final java.lang.String IS_USER_PROFILE = "is_user_profile";
     field public static final java.lang.String LOOKUP_KEY = "lookup";
+    field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
     field public static final java.lang.String PHOTO_ID = "photo_id";
     field public static final java.lang.String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
     field public static final java.lang.String PHOTO_URI = "photo_uri";
@@ -15992,6 +16038,13 @@
     field public static final int UNDEFINED = 0; // 0x0
   }
 
+  public static final class ContactsContract.DisplayPhoto {
+    field public static final android.net.Uri CONTENT_MAX_DIMENSIONS_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DISPLAY_MAX_DIM = "display_max_dim";
+    field public static final java.lang.String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+  }
+
   public static abstract interface ContactsContract.FullNameStyle {
     field public static final int CHINESE = 3; // 0x3
     field public static final int CJK = 2; // 0x2
@@ -16010,6 +16063,8 @@
   }
 
   protected static abstract interface ContactsContract.GroupsColumns {
+    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 AUTO_ADD = "auto_add";
     field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String DELETED = "deleted";
@@ -16029,6 +16084,7 @@
     field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
     field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
     field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
+    field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
     field public static final java.lang.String SEARCH_SUGGESTION_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
     field public static final java.lang.String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
     field public static final java.lang.String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
@@ -16127,6 +16183,10 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "data";
   }
 
+  public static final class ContactsContract.RawContacts.DisplayPhoto {
+    field public static final java.lang.String CONTENT_DIRECTORY = "display_photo";
+  }
+
   public static final class ContactsContract.RawContacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
     field public static final java.lang.String CONTENT_DIRECTORY = "entity";
     field public static final java.lang.String DATA_ID = "data_id";
@@ -16197,12 +16257,14 @@
   }
 
   public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String PHOTO = "photo";
   }
 
   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 PHOTO_FILE_ID = "photo_file_id";
+    field public static final java.lang.String PHOTO_URI = "photo_uri";
     field public static final java.lang.String SORT_INDEX = "sort_index";
     field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
   }
@@ -16212,7 +16274,6 @@
     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 {
@@ -16674,6 +16735,7 @@
     field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
     field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
     field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
+    field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
     field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
     field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
     field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
@@ -16690,18 +16752,18 @@
     field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
     field public static final java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
     field public static final java.lang.String WIFI_ON = "wifi_on";
-    field public static final java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
-    field public static final java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
-    field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
-    field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled";
-    field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms";
-    field public static final java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count";
-    field public static final java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
     field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
-    field public static final java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
-    field public static final java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
-    field public static final java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
-    field public static final java.lang.String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
   }
 
   public static class Settings.SettingNotFoundException extends android.util.AndroidException {
@@ -16883,6 +16945,49 @@
     field public static final java.lang.String _ID = "_id";
   }
 
+  public class VoicemailContract {
+    field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+    field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+    field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
+    field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
+  }
+
+  public static final class VoicemailContract.Status implements android.provider.BaseColumns {
+    method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
+    field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+    field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
+    field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+    field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
+    field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
+    field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+    field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
+    field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String SETTINGS_URI = "settings_uri";
+    field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+    field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
+  }
+
+  public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns {
+    method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String HAS_CONTENT = "has_content";
+    field public static final java.lang.String IS_READ = "is_read";
+    field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
+    field public static final java.lang.String MIME_TYPE = "mime_type";
+    field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String SOURCE_DATA = "source_data";
+    field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+  }
+
 }
 
 package android.renderscript {
@@ -16964,6 +17069,7 @@
 
   public class BaseObj {
     method public synchronized void destroy();
+    method public java.lang.String getName();
     method public void setName(java.lang.String);
   }
 
@@ -17616,6 +17722,21 @@
     method public void surfaceDestroyed(android.view.SurfaceHolder);
   }
 
+  public class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
+    ctor public RSTextureView(android.content.Context);
+    ctor public RSTextureView(android.content.Context, android.util.AttributeSet);
+    method public android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
+    method public void destroyRenderScriptGL();
+    method public android.renderscript.RenderScriptGL getRenderScriptGL();
+    method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
+    method public void onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
+    method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+    method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+    method public void pause();
+    method public void resume();
+    method public void setRenderScriptGL(android.renderscript.RenderScriptGL);
+  }
+
   public class RenderScript {
     method public void contextDump();
     method public static android.renderscript.RenderScript create(android.content.Context);
@@ -17663,6 +17784,7 @@
     method public void pause();
     method public void resume();
     method public void setSurface(android.view.SurfaceHolder, int, int);
+    method public void setSurfaceTexture(android.graphics.SurfaceTexture, int, int);
   }
 
   public static class RenderScriptGL.SurfaceConfig {
@@ -17706,6 +17828,7 @@
 
   public class Script extends android.renderscript.BaseObj {
     method public void bindAllocation(android.renderscript.Allocation, int);
+    method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
     method protected void invoke(int);
     method protected void invoke(int, android.renderscript.FieldPacker);
     method public void setTimeZone(java.lang.String);
@@ -17863,6 +17986,31 @@
 
 }
 
+package android.service.textservice {
+
+  public abstract class SpellCheckerService extends android.app.Service {
+    ctor public SpellCheckerService();
+    method public void cancel();
+    method public abstract android.view.textservice.SuggestionsInfo getSuggestions(android.view.textservice.TextInfo, int, java.lang.String);
+    method public android.view.textservice.SuggestionsInfo[] getSuggestionsMultiple(android.view.textservice.TextInfo[], java.lang.String, int, boolean);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
+  }
+
+  public class SpellCheckerSession {
+    method public void close();
+    method public android.view.textservice.SpellCheckerInfo getSpellChecker();
+    method public void getSuggestions(android.view.textservice.TextInfo, int);
+    method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
+    method public boolean isSessionDisconnected();
+  }
+
+  public static abstract interface SpellCheckerSession.SpellCheckerSessionListener {
+    method public abstract void onGetSuggestions(android.view.textservice.SuggestionsInfo[]);
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -18002,7 +18150,6 @@
 
   public abstract interface SynthesisCallback {
     method public abstract int audioAvailable(byte[], int, int);
-    method public abstract int completeAudioAvailable(int, int, int, byte[], int, int);
     method public abstract int done();
     method public abstract void error();
     method public abstract int getMaxBufferSize();
@@ -20465,6 +20612,14 @@
     ctor public Base64OutputStream(java.io.OutputStream, int);
   }
 
+  public final deprecated class Config {
+    field public static final deprecated boolean DEBUG = false;
+    field public static final deprecated boolean LOGD = true;
+    field public static final deprecated boolean LOGV = false;
+    field public static final deprecated boolean PROFILE = false;
+    field public static final deprecated boolean RELEASE = true;
+  }
+
   public class DebugUtils {
     method public static boolean isObjectSelected(java.lang.Object);
   }
@@ -20675,8 +20830,8 @@
     field public static final java.util.regex.Pattern IP_ADDRESS;
     field public static final java.util.regex.Pattern PHONE;
     field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN;
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)|y[et]|z[amw])";
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)|y[et]|z[amw]))";
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
     field public static final java.util.regex.Pattern WEB_URL;
   }
 
@@ -20704,11 +20859,12 @@
     method public void set(T, V);
   }
 
-  public class SparseArray {
+  public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
     method public void append(int, E);
     method public void clear();
+    method public android.util.SparseArray<E> clone();
     method public void delete(int);
     method public E get(int);
     method public E get(int, E);
@@ -20723,11 +20879,12 @@
     method public E valueAt(int);
   }
 
-  public class SparseBooleanArray {
+  public class SparseBooleanArray implements java.lang.Cloneable {
     ctor public SparseBooleanArray();
     ctor public SparseBooleanArray(int);
     method public void append(int, boolean);
     method public void clear();
+    method public android.util.SparseBooleanArray clone();
     method public void delete(int);
     method public boolean get(int);
     method public boolean get(int, boolean);
@@ -20739,11 +20896,12 @@
     method public boolean valueAt(int);
   }
 
-  public class SparseIntArray {
+  public class SparseIntArray implements java.lang.Cloneable {
     ctor public SparseIntArray();
     ctor public SparseIntArray(int);
     method public void append(int, int);
     method public void clear();
+    method public android.util.SparseIntArray clone();
     method public void delete(int);
     method public int get(int);
     method public int get(int, int);
@@ -20890,11 +21048,13 @@
     method public abstract android.view.Menu getMenu();
     method public abstract android.view.MenuInflater getMenuInflater();
     method public abstract java.lang.CharSequence getSubtitle();
+    method public java.lang.Object getTag();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract void invalidate();
     method public abstract void setCustomView(android.view.View);
     method public abstract void setSubtitle(java.lang.CharSequence);
     method public abstract void setSubtitle(int);
+    method public void setTag(java.lang.Object);
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitle(int);
   }
@@ -20914,6 +21074,11 @@
     method public void onPrepareSubMenu(android.view.SubMenu);
   }
 
+  public abstract interface CollapsibleActionView {
+    method public abstract void onActionViewCollapsed();
+    method public abstract void onActionViewExpanded();
+  }
+
   public abstract interface ContextMenu implements android.view.Menu {
     method public abstract void clearHeader();
     method public abstract android.view.ContextMenu setHeaderIcon(int);
@@ -21796,9 +21961,8 @@
     field public static final int EDGE_TOP = 1; // 0x1
     field public static final int FLAG_WINDOW_IS_OBSCURED = 1; // 0x1
     field public static final int INVALID_POINTER_ID = -1; // 0xffffffff
+    field public static final int TOOL_TYPE_ERASER = 4; // 0x4
     field public static final int TOOL_TYPE_FINGER = 1; // 0x1
-    field public static final int TOOL_TYPE_INDIRECT_FINGER = 4; // 0x4
-    field public static final int TOOL_TYPE_INDIRECT_STYLUS = 5; // 0x5
     field public static final int TOOL_TYPE_MOUSE = 3; // 0x3
     field public static final int TOOL_TYPE_STYLUS = 2; // 0x2
     field public static final int TOOL_TYPE_UNKNOWN = 0; // 0x0
@@ -22007,9 +22171,12 @@
     method public android.graphics.SurfaceTexture getSurfaceTexture();
     method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
     method public boolean isAvailable();
+    method public android.graphics.Canvas lockCanvas();
+    method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
     method protected final void onDraw(android.graphics.Canvas);
     method public void setOpaque(boolean);
     method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
+    method public void unlockCanvasAndPost(android.graphics.Canvas);
   }
 
   public static abstract interface TextureView.SurfaceTextureListener {
@@ -22058,6 +22225,7 @@
     method public void buildDrawingCache();
     method public void buildDrawingCache(boolean);
     method public void buildLayer();
+    method protected boolean canResolveLayoutDirection();
     method public boolean canScrollHorizontally(int);
     method public boolean canScrollVertically(int);
     method public void cancelLongPress();
@@ -22106,6 +22274,7 @@
     method public final android.view.View findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence);
     method protected boolean fitSystemWindows(android.graphics.Rect);
+    method public boolean fitsSystemWindows();
     method public android.view.View focusSearch(int);
     method public void forceLayout();
     method public float getAlpha();
@@ -22347,6 +22516,7 @@
     method public void setEnabled(boolean);
     method public void setFadingEdgeLength(int);
     method public void setFilterTouchesWhenObscured(boolean);
+    method public void setFitsSystemWindows(boolean);
     method public void setFocusable(boolean);
     method public void setFocusableInTouchMode(boolean);
     method public void setHapticFeedbackEnabled(boolean);
@@ -23235,6 +23405,7 @@
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
     method public void interrupt();
     method public boolean isEnabled();
+    method public boolean isTouchExplorationEnabled();
     method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
   }
@@ -23271,6 +23442,7 @@
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain();
+    method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
     method public boolean performAction(int);
     method public void recycle();
     method public void setBoundsInParent(android.graphics.Rect);
@@ -23857,7 +24029,7 @@
     method public boolean isWatchingCursor(android.view.View);
     method public void restartInput(android.view.View);
     method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
-    method public boolean setAdditionalInputMethodSubtypes(android.os.IBinder, android.view.inputmethod.InputMethodSubtype[]);
+    method public boolean setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
     method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
     method public void setInputMethod(android.os.IBinder, java.lang.String);
     method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
@@ -23920,6 +24092,54 @@
 
 }
 
+package android.view.textservice {
+
+  public final class SpellCheckerInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public java.lang.String getPackageName();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class SuggestionsInfo implements android.os.Parcelable {
+    ctor public SuggestionsInfo(int, java.lang.String[]);
+    ctor public SuggestionsInfo(int, java.lang.String[], int, int);
+    ctor public SuggestionsInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getSuggestionAt(int);
+    method public int getSuggestionsAttributes();
+    method public int getSuggestionsCount();
+    method public void setCookieAndSequence(int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
+    field public static final int RESULT_ATTR_LOOKS_TYPO = 2; // 0x2
+  }
+
+  public final class TextInfo implements android.os.Parcelable {
+    ctor public TextInfo(java.lang.String);
+    ctor public TextInfo(java.lang.String, int, int);
+    ctor public TextInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class TextServicesManager {
+    method public android.service.textservice.SpellCheckerSession newSpellCheckerSession(java.util.Locale, android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean);
+  }
+
+}
+
 package android.webkit {
 
   public final deprecated class CacheManager {
@@ -25259,11 +25479,14 @@
     method public void setRowCount(int);
     method public void setRowOrderPreserved(boolean);
     method public void setUseDefaultMargins(boolean);
+    method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment);
+    method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment);
+    method public static android.widget.GridLayout.Spec spec(int, int);
+    method public static android.widget.GridLayout.Spec spec(int);
     field public static final int ALIGN_BOUNDS = 0; // 0x0
     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
@@ -25277,23 +25500,19 @@
   public static abstract class GridLayout.Alignment {
   }
 
-  public static class GridLayout.Group {
-    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 {
-    ctor public GridLayout.LayoutParams(android.widget.GridLayout.Group, android.widget.GridLayout.Group);
+    ctor public GridLayout.LayoutParams(android.widget.GridLayout.Spec, android.widget.GridLayout.Spec);
     ctor public GridLayout.LayoutParams();
     ctor public GridLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
     ctor public GridLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
     ctor public GridLayout.LayoutParams(android.widget.GridLayout.LayoutParams);
     ctor public GridLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
     method public void setGravity(int);
-    field public android.widget.GridLayout.Group columnGroup;
-    field public android.widget.GridLayout.Group rowGroup;
+    field public android.widget.GridLayout.Spec columnSpec;
+    field public android.widget.GridLayout.Spec rowSpec;
+  }
+
+  public static class GridLayout.Spec {
   }
 
   public class GridView extends android.widget.AbsListView {
@@ -26022,7 +26241,7 @@
     method public int timePassed();
   }
 
-  public class SearchView extends android.widget.LinearLayout {
+  public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView {
     ctor public SearchView(android.content.Context);
     ctor public SearchView(android.content.Context, android.util.AttributeSet);
     method public java.lang.CharSequence getQuery();
@@ -26031,6 +26250,8 @@
     method public boolean isIconified();
     method public boolean isQueryRefinementEnabled();
     method public boolean isSubmitButtonEnabled();
+    method public void onActionViewCollapsed();
+    method public void onActionViewExpanded();
     method public void setIconified(boolean);
     method public void setIconifiedByDefault(boolean);
     method public void setMaxWidth(int);
@@ -26084,7 +26305,7 @@
     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);
+    method public void setShareIntent(android.content.Intent);
     field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
   }
 
@@ -29691,7 +29912,7 @@
     ctor public ReferenceQueue();
     method public synchronized java.lang.ref.Reference<? extends T> poll();
     method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException;
-    method public synchronized java.lang.ref.Reference<? extends T> remove(long) throws java.lang.IllegalArgumentException, java.lang.InterruptedException;
+    method public synchronized java.lang.ref.Reference<? extends T> remove(long) throws java.lang.InterruptedException;
   }
 
   public class SoftReference extends java.lang.ref.Reference {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3fb1736..6dfa12b 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -468,10 +468,16 @@
         String profileFile = null;
         boolean start = false;
         boolean wall = false;
+        int profileType = 0;
         
         String process = null;
         
         String cmd = nextArgRequired();
+        if ("looper".equals(cmd)) {
+            cmd = nextArgRequired();
+            profileType = 1;
+        }
+
         if ("start".equals(cmd)) {
             start = true;
             wall = "--wall".equals(nextOption());
@@ -516,7 +522,7 @@
             } else if (start) {
                 //removeWallOption();
             }
-            if (!mAm.profileControl(process, start, profileFile, fd)) {
+            if (!mAm.profileControl(process, start, profileFile, fd, profileType)) {
                 wall = false;
                 throw new AndroidException("PROFILE FAILED on process " + process);
             }
@@ -1076,8 +1082,8 @@
                 "       am broadcast <INTENT>\n" +
                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" +
                 "               [--no-window-animation] <COMPONENT>\n" +
-                "       am profile start <PROCESS> <FILE>\n" +
-                "       am profile stop <PROCESS>\n" +
+                "       am profile [looper] start <PROCESS> <FILE>\n" +
+                "       am profile [looper] stop <PROCESS>\n" +
                 "       am dumpheap [flags] <PROCESS> <FILE>\n" +
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 56f1324..d602500 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -11,4 +11,9 @@
 
 LOCAL_SHARED_LIBRARIES := libcutils
 
+ifdef BOARD_LIB_DUMPSTATE
+LOCAL_STATIC_LIBRARIES := $(BOARD_LIB_DUMPSTATE)
+LOCAL_CFLAGS += -DBOARD_HAS_DUMPSTATE
+endif
+
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 42c35af..52b2d91 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -113,8 +113,8 @@
     dump_file("NETWORK ROUTES", "/proc/net/route");
     dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
     dump_file("ARP CACHE", "/proc/net/arp");
-    run_command("IPTABLES", 10, "su", "root", "iptables", "-L", NULL);
-    run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", NULL);
+    run_command("IPTABLES", 10, "su", "root", "iptables", "-L", "-n", NULL);
+    run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", "-n", NULL);
 
     run_command("WIFI NETWORKS", 20,
             "su", "root", "wpa_cli", "list_networks", NULL);
@@ -197,6 +197,15 @@
     dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
     printf("\n");
 
+#ifdef BOARD_HAS_DUMPSTATE
+    printf("========================================================\n");
+    printf("== Board\n");
+    printf("========================================================\n");
+
+    dumpstate_board();
+    printf("\n");
+#endif
+
     printf("========================================================\n");
     printf("== Android Framework Services\n");
     printf("========================================================\n");
@@ -218,6 +227,9 @@
 
     run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
 
+    printf("========================================================\n");
+    printf("== dumpstate: done\n");
+    printf("========================================================\n");
 }
 
 static void usage() {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 83b1d11..597ab1f 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -19,6 +19,7 @@
 
 #include <time.h>
 #include <unistd.h>
+#include <stdio.h>
 
 /* prints the contents of a file */
 int dump_file(const char *title, const char* path);
@@ -47,4 +48,7 @@
 /* Play a sound via Stagefright */
 void play_sound(const char* path);
 
+/* Implemented by libdumpstate_board to dump board-specific info */
+void dumpstate_board();
+
 #endif /* _DUMPSTATE_H_ */
diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c
index bbf6b14e..e9ee95d 100644
--- a/cmds/ip-up-vpn/ip-up-vpn.c
+++ b/cmds/ip-up-vpn/ip-up-vpn.c
@@ -17,19 +17,135 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
-#include <cutils/properties.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/route.h>
 
+#define LOG_TAG "ip-up-vpn"
+#include <cutils/log.h>
+
+#define DIR "/data/misc/vpn/"
+
+static const char *env(const char *name) {
+    const char *value = getenv(name);
+    return value ? value : "";
+}
+
+static int set_address(struct sockaddr *sa, const char *address) {
+    sa->sa_family = AF_INET;
+    return inet_pton(AF_INET, address, &((struct sockaddr_in *)sa)->sin_addr);
+}
+
+/*
+ * The primary goal is to create a file with VPN parameters. Currently they
+ * are interface, addresses, routes, DNS servers, and search domains. Each
+ * parameter occupies one line in the file, and it can be an empty string or
+ * space-separated values. The order and the format must be consistent with
+ * com.android.server.connectivity.Vpn. Here is an example.
+ *
+ *   ppp0
+ *   192.168.1.100/24
+ *   0.0.0.0/0
+ *   192.168.1.1 192.168.1.2
+ *   example.org
+ *
+ * The secondary goal is to unify the outcome of VPN. The current baseline
+ * is to have an interface configured with the given address and netmask
+ * and maybe add a host route to protect the tunnel. PPP-based VPN already
+ * does this, but others might not. Routes, DNS servers, and search domains
+ * are handled by the framework since they can be overridden by the users.
+ */
 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");
+    FILE *state = fopen(DIR ".tmp", "wb");
+    if (!state) {
+        LOGE("Cannot create state: %s", strerror(errno));
+        return 1;
+    }
 
-        snprintf(dns, sizeof(dns), "%s %s", dns1 ? dns1 : "", dns2 ? dns2 : "");
-        property_set("vpn.dns", dns);
-        property_set("vpn.via", argv[1]);
+    if (argc >= 6) {
+        /* Invoked by pppd. */
+        fprintf(state, "%s\n", argv[1]);
+        fprintf(state, "%s/32\n", argv[4]);
+        fprintf(state, "0.0.0.0/0\n");
+        fprintf(state, "%s %s\n", env("DNS1"), env("DNS2"));
+        fprintf(state, "\n");
+    } else if (argc == 2) {
+        /* Invoked by racoon. */
+        const char *interface = env("INTERFACE");
+        const char *address = env("INTERNAL_ADDR4");
+        const char *routes = env("SPLIT_INCLUDE_CIDR");
+
+        int s = socket(AF_INET, SOCK_DGRAM, 0);
+        struct rtentry rt;
+        struct ifreq ifr;
+
+        memset(&rt, 0, sizeof(rt));
+        memset(&ifr, 0, sizeof(ifr));
+
+        /* Remove the old host route. There could be more than one. */
+        rt.rt_flags |= RTF_UP | RTF_HOST;
+        if (set_address(&rt.rt_dst, env("REMOTE_ADDR"))) {
+            while (!ioctl(s, SIOCDELRT, &rt));
+        }
+        if (errno != ESRCH) {
+            LOGE("Cannot remove host route: %s", strerror(errno));
+            return 1;
+        }
+
+        /* Create a new host route. */
+        rt.rt_flags |= RTF_GATEWAY;
+        if (!set_address(&rt.rt_gateway, argv[1]) ||
+                (ioctl(s, SIOCADDRT, &rt) && errno != EEXIST)) {
+            LOGE("Cannot create host route: %s", strerror(errno));
+            return 1;
+        }
+
+        /* Bring up the interface. */
+        ifr.ifr_flags = IFF_UP;
+        strncpy(ifr.ifr_name, interface, IFNAMSIZ);
+        if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
+            LOGE("Cannot bring up %s: %s", interface, strerror(errno));
+            return 1;
+        }
+
+        /* Set the address. */
+        if (!set_address(&ifr.ifr_addr, address) ||
+                ioctl(s, SIOCSIFADDR, &ifr)) {
+            LOGE("Cannot set address: %s", strerror(errno));
+            return 1;
+        }
+
+        /* Set the netmask. */
+        if (!set_address(&ifr.ifr_netmask, env("INTERNAL_NETMASK4")) ||
+                ioctl(s, SIOCSIFNETMASK, &ifr)) {
+            LOGE("Cannot set netmask: %s", strerror(errno));
+            return 1;
+        }
+
+        /* TODO: Send few packets to trigger phase 2? */
+
+        fprintf(state, "%s\n", interface);
+        fprintf(state, "%s/%s\n", address, env("INTERNAL_CIDR4"));
+        fprintf(state, "%s\n", routes[0] ? routes : "0.0.0.0/0");
+        fprintf(state, "%s\n", env("INTERNAL_DNS4_LIST"));
+        fprintf(state, "%s\n", env("DEFAULT_DOMAIN"));
+    } else {
+        LOGE("Cannot parse parameters");
+        return 1;
+    }
+
+    fclose(state);
+    if (chmod(DIR ".tmp", 0444) || rename(DIR ".tmp", DIR "state")) {
+        LOGE("Cannot write state: %s", strerror(errno));
+        return 1;
     }
     return 0;
 }
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 1a5b7f3..34f0a64 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -793,7 +793,9 @@
             MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
             MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
             MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
-            MEDIA_MIMETYPE_AUDIO_MPEG
+            MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+            MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
+            MEDIA_MIMETYPE_VIDEO_VPX
         };
 
         for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
@@ -801,6 +803,7 @@
             printf("type '%s':\n", kMimeTypes[k]);
 
             Vector<CodecCapabilities> results;
+            // will retrieve hardware and software codecs
             CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
                                  true, // queryDecoders
                                  &results), (status_t)OK);
@@ -842,7 +845,12 @@
 
         for (List<IOMX::ComponentInfo>::iterator it = list.begin();
              it != list.end(); ++it) {
-            printf("%s\n", (*it).mName.string());
+            printf("%s\t Roles: ", (*it).mName.string());
+            for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
+                    itRoles != (*it).mRoles.end() ; ++itRoles) {
+                printf("%s\t", (*itRoles).string());
+            }
+            printf("\n");
         }
     }
 
diff --git a/cmds/system_server/system_main.cpp b/cmds/system_server/system_main.cpp
index 543f650..d67329d 100644
--- a/cmds/system_server/system_main.cpp
+++ b/cmds/system_server/system_main.cpp
@@ -52,10 +52,5 @@
     LOGW("*** Current priority: %d\n", getpriority(PRIO_PROCESS, 0));
     setpriority(PRIO_PROCESS, 0, -1);
 
-    #if HAVE_ANDROID_OS
-    //setgid(GID_SYSTEM);
-    //setuid(UID_SYSTEM);
-    #endif
-
     system_init();    
 }
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 68c9926..1e238f0 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -130,20 +130,11 @@
  * 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_WINDOW_STATE_CHANGED},
  * {@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.
+ * In other words, the last window that was shown or the last window that the user has touched
+ * during touch exploration.
  * </p>
  * <p>
  * The entry point for retrieving window content is through calling
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index ef4adca..41a3eaca 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -75,6 +75,17 @@
     public static final int FEEDBACK_GENERIC = 0x0000010;
 
     /**
+     * Mask for all feedback types.
+     *
+     * @see #FEEDBACK_SPOKEN
+     * @see #FEEDBACK_HAPTIC
+     * @see #FEEDBACK_AUDIBLE
+     * @see #FEEDBACK_VISUAL
+     * @see #FEEDBACK_GENERIC
+     */
+    public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
+
+    /**
      * If an {@link AccessibilityService} is the default for a given type.
      * Default service is invoked only if no package specific one exists. In case of
      * more than one package specific service only the earlier registered is notified.
@@ -171,6 +182,11 @@
     private boolean mCanRetrieveWindowContent;
 
     /**
+     * Description of the accessibility service.
+     */
+    private String mDescription;
+
+    /**
      * Creates a new instance.
      */
     public AccessibilityServiceInfo() {
@@ -193,8 +209,6 @@
         mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString();
         mResolveInfo = resolveInfo;
 
-        String settingsActivityName = null;
-        boolean retrieveScreenContent = false;
         XmlResourceParser parser = null;
 
         try {
@@ -242,6 +256,8 @@
             mCanRetrieveWindowContent = asAttributes.getBoolean(
                     com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
                     false);
+            mDescription = asAttributes.getString(
+                    com.android.internal.R.styleable.AccessibilityService_description);
             asAttributes.recycle();
         } catch (NameNotFoundException e) {
             throw new XmlPullParserException( "Unable to create context for: "
@@ -315,6 +331,18 @@
     }
 
     /**
+     * Description of the accessibility service.
+     * <p>
+     *    <strong>Statically set from
+     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+     * </p>
+     * @return The description.
+     */
+    public String getDescription() {
+        return mDescription;
+    }
+
+    /**
      * {@inheritDoc}
      */
     public int describeContents() {
@@ -331,6 +359,7 @@
         parcel.writeParcelable(mResolveInfo, 0);
         parcel.writeString(mSettingsActivityName);
         parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0);
+        parcel.writeString(mDescription);
     }
 
     private void initFromParcel(Parcel parcel) {
@@ -343,6 +372,7 @@
         mResolveInfo = parcel.readParcelable(null);
         mSettingsActivityName = parcel.readString();
         mCanRetrieveWindowContent = (parcel.readInt() == 1);
+        mDescription = parcel.readString();
     }
 
     @Override
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index d25de97..06d18ec 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -25,6 +25,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 
 /**
@@ -178,14 +179,17 @@
      * the transition. The reason for this is that a further layout event should cause
      * existing animations to stop where they are prior to starting new animations. So
      * we cache all of the current animations in this map for possible cancellation on
-     * another layout event.
+     * another layout event. LinkedHashMaps are used to preserve the order in which animations
+     * are inserted, so that we process events (such as setting up start values) in the same order.
      */
-    private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>();
-    private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
-    private final HashMap<View, Animator> currentAppearingAnimations =
+    private final HashMap<View, Animator> pendingAnimations =
             new HashMap<View, Animator>();
-    private final HashMap<View, Animator> currentDisappearingAnimations =
-            new HashMap<View, Animator>();
+    private final LinkedHashMap<View, Animator> currentChangingAnimations =
+            new LinkedHashMap<View, Animator>();
+    private final LinkedHashMap<View, Animator> currentAppearingAnimations =
+            new LinkedHashMap<View, Animator>();
+    private final LinkedHashMap<View, Animator> currentDisappearingAnimations =
+            new LinkedHashMap<View, Animator>();
 
     /**
      * This hashmap is used to track the listeners that have been added to the children of
@@ -235,7 +239,7 @@
             PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1);
             PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1);
             PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1);
-            defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder(this,
+            defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder((Object)null,
                     pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY);
             defaultChangeIn.setDuration(DEFAULT_DURATION);
             defaultChangeIn.setStartDelay(mChangingAppearingDelay);
@@ -244,11 +248,11 @@
             defaultChangeOut.setStartDelay(mChangingDisappearingDelay);
             defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator);
 
-            defaultFadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f);
+            defaultFadeIn = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f);
             defaultFadeIn.setDuration(DEFAULT_DURATION);
             defaultFadeIn.setStartDelay(mAppearingDelay);
             defaultFadeIn.setInterpolator(mAppearingInterpolator);
-            defaultFadeOut = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f);
+            defaultFadeOut = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
             defaultFadeOut.setDuration(DEFAULT_DURATION);
             defaultFadeOut.setStartDelay(mDisappearingDelay);
             defaultFadeOut.setInterpolator(mDisappearingInterpolator);
@@ -547,7 +551,7 @@
     }
 
     /**
-     * This function sets up runs animations on all of the views that change during layout.
+     * This function sets up animations on all of the views that change during layout.
      * For every child in the parent, we create a change animation of the appropriate
      * type (appearing or disappearing) and ask it to populate its start values from its
      * target view. We add layout listeners to all child views and listen for changes. For
@@ -821,24 +825,24 @@
      */
     public void cancel() {
         if (currentChangingAnimations.size() > 0) {
-            HashMap<View, Animator> currentAnimCopy =
-                    (HashMap<View, Animator>) currentChangingAnimations.clone();
+            LinkedHashMap<View, Animator> currentAnimCopy =
+                    (LinkedHashMap<View, Animator>) currentChangingAnimations.clone();
             for (Animator anim : currentAnimCopy.values()) {
                 anim.cancel();
             }
             currentChangingAnimations.clear();
         }
         if (currentAppearingAnimations.size() > 0) {
-            HashMap<View, Animator> currentAnimCopy =
-                    (HashMap<View, Animator>) currentAppearingAnimations.clone();
+            LinkedHashMap<View, Animator> currentAnimCopy =
+                    (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone();
             for (Animator anim : currentAnimCopy.values()) {
                 anim.end();
             }
             currentAppearingAnimations.clear();
         }
         if (currentDisappearingAnimations.size() > 0) {
-            HashMap<View, Animator> currentAnimCopy =
-                    (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+            LinkedHashMap<View, Animator> currentAnimCopy =
+                    (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone();
             for (Animator anim : currentAnimCopy.values()) {
                 anim.end();
             }
@@ -859,8 +863,8 @@
             case CHANGE_APPEARING:
             case CHANGE_DISAPPEARING:
                 if (currentChangingAnimations.size() > 0) {
-                    HashMap<View, Animator> currentAnimCopy =
-                            (HashMap<View, Animator>) currentChangingAnimations.clone();
+                    LinkedHashMap<View, Animator> currentAnimCopy =
+                            (LinkedHashMap<View, Animator>) currentChangingAnimations.clone();
                     for (Animator anim : currentAnimCopy.values()) {
                         anim.cancel();
                     }
@@ -869,8 +873,8 @@
                 break;
             case APPEARING:
                 if (currentAppearingAnimations.size() > 0) {
-                    HashMap<View, Animator> currentAnimCopy =
-                            (HashMap<View, Animator>) currentAppearingAnimations.clone();
+                    LinkedHashMap<View, Animator> currentAnimCopy =
+                            (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone();
                     for (Animator anim : currentAnimCopy.values()) {
                         anim.end();
                     }
@@ -879,8 +883,8 @@
                 break;
             case DISAPPEARING:
                 if (currentDisappearingAnimations.size() > 0) {
-                    HashMap<View, Animator> currentAnimCopy =
-                            (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+                    LinkedHashMap<View, Animator> currentAnimCopy =
+                            (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone();
                     for (Animator anim : currentAnimCopy.values()) {
                         anim.end();
                     }
@@ -1113,4 +1117,4 @@
                 View view, int transitionType);
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 3ec5edb..a217867 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -29,10 +29,16 @@
 import android.widget.SpinnerAdapter;
 
 /**
- * This is the public interface to the contextual ActionBar.
- * The ActionBar acts as a replacement for the title bar in Activities.
- * It provides facilities for creating toolbar actions as well as
- * methods of navigating around an application. 
+ * Acts as a replacement for the title bar in Activities.
+ * The action bar provides facilities for creating toolbar actions as well as
+ * methods of navigating the application.
+ * <p>By default, the action bar appears at the top of every activity, with the application icon on
+ * the left, followed by the activity title. Items from the activity's options menu are also
+ * accessible from the action bar.</p>
+ * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
+ * android.app.Activity#getActionBar getActionBar()}.</p>
+ * <p>For more information, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
+ * Bar</a> developer guide.</p>
  */
 public abstract class ActionBar {
     /**
@@ -81,6 +87,9 @@
      * Set this flag if selecting the 'home' button in the action bar to return
      * up by a single level in your UI rather than back to the top level or front page.
      *
+     * <p>Setting this option will implicitly enable interaction with the home/up
+     * button. See {@link #setHomeButtonEnabled(boolean)}.
+     *
      * @see #setDisplayOptions(int)
      * @see #setDisplayOptions(int, int)
      */
@@ -107,18 +116,6 @@
     public static final int DISPLAY_SHOW_CUSTOM = 0x10;
 
     /**
-     * Disable the 'home' element. This may be combined with
-     * {@link #DISPLAY_SHOW_HOME} to create a non-focusable/non-clickable
-     * 'home' element. Useful for a level of your app's navigation hierarchy
-     * where clicking 'home' doesn't do anything.
-     *
-     * @see #setDisplayOptions(int)
-     * @see #setDisplayOptions(int, int)
-     * @see #setDisplayDisableHomeEnabled(boolean)
-     */
-    public static final int DISPLAY_DISABLE_HOME = 0x20;
-
-    /**
      * Set the action bar into custom navigation mode, supplying a view
      * for custom navigation.
      *
@@ -405,21 +402,6 @@
     public abstract void setDisplayShowCustomEnabled(boolean showCustom);
 
     /**
-     * Set whether the 'home' affordance on the action bar should be disabled.
-     * If set, the 'home' element will not be focusable or clickable, useful if
-     * the user is at the top level of the app's navigation hierarchy.
-     *
-     * <p>To set several display options at once, see the setDisplayOptions methods.
-     *
-     * @param disableHome true to disable the 'home' element.
-     *
-     * @see #setDisplayOptions(int)
-     * @see #setDisplayOptions(int, int)
-     * @see #DISPLAY_DISABLE_HOME
-     */
-    public abstract void setDisplayDisableHomeEnabled(boolean disableHome);
-
-    /**
      * Set the ActionBar's background.
      * 
      * @param d Background drawable
@@ -632,6 +614,22 @@
     public abstract void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener);
 
     /**
+     * Enable or disable the "home" button in the corner of the action bar. (Note that this
+     * is the application home/up affordance on the action bar, not the systemwide home
+     * button.)
+     *
+     * <p>This defaults to true for packages targeting &lt; API 14. For packages targeting
+     * API 14 or greater, the application should call this method to enable interaction
+     * with the home/up affordance.
+     *
+     * <p>Setting the {@link #DISPLAY_HOME_AS_UP} display option will automatically enable
+     * the home button.
+     *
+     * @param enabled true to enable the home button, false to disable the home button.
+     */
+    public abstract void setHomeButtonEnabled(boolean enabled);
+
+    /**
      * Listener interface for ActionBar navigation events.
      */
     public interface OnNavigationListener {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aeb16f4..8d03ac7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1593,10 +1593,10 @@
         //Log.v(TAG, "invalidateFragmentIndex: index=" + index);
         if (mAllLoaderManagers != null) {
             LoaderManagerImpl lm = mAllLoaderManagers.get(index);
-            if (lm != null) {
+            if (lm != null && !lm.mRetaining) {
                 lm.doDestroy();
+                mAllLoaderManagers.remove(index);
             }
-            mAllLoaderManagers.remove(index);
         }
     }
     
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index fdf4a3a..b7cd829 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1104,10 +1104,11 @@
             data.enforceInterface(IActivityManager.descriptor);
             String process = data.readString();
             boolean start = data.readInt() != 0;
+            int profileType = data.readInt();
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            boolean res = profileControl(process, start, path, fd);
+            boolean res = profileControl(process, start, path, fd, profileType);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -1514,6 +1515,14 @@
             return true;
         }
 
+        case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            Configuration config = Configuration.CREATOR.createFromParcel(data);
+            updatePersistentConfiguration(config);
+            reply.writeNoException();
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -2880,13 +2889,14 @@
     }
     
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(process);
         data.writeInt(start ? 1 : 0);
+        data.writeInt(profileType);
         data.writeString(path);
         if (fd != null) {
             data.writeInt(1);
@@ -3410,5 +3420,17 @@
         return res;
     }
 
+    public void updatePersistentConfiguration(Configuration values) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        values.writeToParcel(data, 0);
+        mRemote.transact(UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ee04729..1e93f88 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -70,7 +70,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewManager;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -123,7 +123,6 @@
     /** @hide */
     public static final String TAG = "ActivityThread";
     private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
-    private static final boolean DEBUG = false;
     static final boolean localLOGV = false;
     static final boolean DEBUG_MESSAGES = false;
     /** @hide */
@@ -163,7 +162,7 @@
             = new ArrayList<Application>();
     // set of instantiated backup agents, keyed by package name
     final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
-    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal();
+    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
     Instrumentation mInstrumentation;
     String mInstrumentationAppDir = null;
     String mInstrumentationAppPackage = null;
@@ -410,13 +409,13 @@
         CompatibilityInfo info;
     }
     
-    native private void dumpGraphicsInfo(FileDescriptor fd);
+    private native void dumpGraphicsInfo(FileDescriptor fd);
 
-    private final class ApplicationThread extends ApplicationThreadNative {
-        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
-        private static final String ONE_COUNT_COLUMN = "%17s %8d";
-        private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
-        private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
+    private class ApplicationThread extends ApplicationThreadNative {
+        private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";
+        private static final String ONE_COUNT_COLUMN = "%21s %8d";
+        private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
+        private static final String TWO_COUNT_COLUMNS_DB = "%21s %8d %21s %8d";
         private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
 
         // Formatting for checkin service - update version if row format changes
@@ -676,11 +675,12 @@
             queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
         }
 
-        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
+        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd,
+                int profileType) {
             ProfilerControlData pcd = new ProfilerControlData();
             pcd.path = path;
             pcd.fd = fd;
-            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
+            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
         }
 
         public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
@@ -729,12 +729,17 @@
         }
 
         @Override
-        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (args != null && args.length == 1 && args[0].equals("graphics")) {
+        public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) {
+            FileOutputStream fout = new FileOutputStream(fd);
+            PrintWriter pw = new PrintWriter(fout);
+            try {
+                return dumpMemInfo(pw, args);
+            } finally {
                 pw.flush();
-                dumpGraphicsInfo(fd);
-                return;
             }
+        }
+
+        private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, String[] args) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -742,21 +747,13 @@
             Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
             Debug.getMemoryInfo(memInfo);
 
-            final int nativeShared = memInfo.nativeSharedDirty;
-            final int dalvikShared = memInfo.dalvikSharedDirty;
-            final int otherShared = memInfo.otherSharedDirty;
-
-            final int nativePrivate = memInfo.nativePrivateDirty;
-            final int dalvikPrivate = memInfo.dalvikPrivateDirty;
-            final int otherPrivate = memInfo.otherPrivateDirty;
-
             Runtime runtime = Runtime.getRuntime();
 
             long dalvikMax = runtime.totalMemory() / 1024;
             long dalvikFree = runtime.freeMemory() / 1024;
             long dalvikAllocated = dalvikMax - dalvikFree;
             long viewInstanceCount = ViewDebug.getViewInstanceCount();
-            long viewRootInstanceCount = ViewDebug.getViewAncestorInstanceCount();
+            long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
             long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
             long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
             int globalAssetCount = AssetManager.getGlobalAssetCount();
@@ -813,16 +810,18 @@
                 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
 
                 // Heap info - shared
-                pw.print(nativeShared); pw.print(',');
-                pw.print(dalvikShared); pw.print(',');
-                pw.print(otherShared); pw.print(',');
-                pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
+                pw.print(memInfo.nativeSharedDirty); pw.print(',');
+                pw.print(memInfo.dalvikSharedDirty); pw.print(',');
+                pw.print(memInfo.otherSharedDirty); pw.print(',');
+                pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty
+                        + memInfo.otherSharedDirty); pw.print(',');
 
                 // Heap info - private
-                pw.print(nativePrivate); pw.print(',');
-                pw.print(dalvikPrivate); pw.print(',');
-                pw.print(otherPrivate); pw.print(',');
-                pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
+                pw.print(memInfo.nativePrivateDirty); pw.print(',');
+                pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
+                pw.print(memInfo.otherPrivateDirty); pw.print(',');
+                pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty
+                        + memInfo.otherPrivateDirty); pw.print(',');
 
                 // Object counts
                 pw.print(viewInstanceCount); pw.print(',');
@@ -850,28 +849,42 @@
                     pw.print(',');
                 }
 
-                return;
+                return memInfo;
             }
 
             // otherwise, show human-readable format
-            printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
-            printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
-            printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
-                    nativeAllocated + dalvikAllocated);
-            printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
-                    nativeFree + dalvikFree);
+            printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap");
+            printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free");
+            printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------",
+                    "------");
+            printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty,
+                    memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree);
+            printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty,
+                    memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree);
 
-            printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
-                    memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
+            int otherPss = memInfo.otherPss;
+            int otherSharedDirty = memInfo.otherSharedDirty;
+            int otherPrivateDirty = memInfo.otherPrivateDirty;
 
-            printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
-                    nativeShared + dalvikShared + otherShared);
-            printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
-                    nativePrivate + dalvikPrivate + otherPrivate);
+            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
+                printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
+                        memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i),
+                        memInfo.getOtherPrivateDirty(i), "", "", "");
+                otherPss -= memInfo.getOtherPss(i);
+                otherSharedDirty -= memInfo.getOtherSharedDirty(i);
+                otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
+            }
+
+            printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty,
+                    otherPrivateDirty, "", "", "");
+            printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
+                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
+                    nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
+                    nativeFree+dalvikFree);
 
             pw.println(" ");
             pw.println(" Objects");
-            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewAncestors:",
+            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
                     viewRootInstanceCount);
 
             printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
@@ -916,6 +929,14 @@
                 pw.println(" Asset Allocations");
                 pw.print(assetAlloc);
             }
+
+            return memInfo;
+        }
+
+        @Override
+        public void dumpGfxInfo(FileDescriptor fd, String[] args) {
+            dumpGraphicsInfo(fd);
+            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
         }
 
         private void printRow(PrintWriter pw, String format, Object...objs) {
@@ -932,9 +953,13 @@
             ucd.info = info;
             queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
         }
+
+        public void scheduleTrimMemory(int level) {
+            queueOrSendMessage(H.TRIM_MEMORY, null, level);
+        }
     }
 
-    private final class H extends Handler {
+    private class H extends Handler {
         public static final int LAUNCH_ACTIVITY         = 100;
         public static final int PAUSE_ACTIVITY          = 101;
         public static final int PAUSE_ACTIVITY_FINISHING= 102;
@@ -975,6 +1000,7 @@
         public static final int SLEEPING                = 137;
         public static final int SET_CORE_SETTINGS       = 138;
         public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
+        public static final int TRIM_MEMORY             = 140;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -1018,6 +1044,7 @@
                     case SLEEPING: return "SLEEPING";
                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
                     case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
+                    case TRIM_MEMORY: return "TRIM_MEMORY";
                 }
             }
             return "(unknown)";
@@ -1122,7 +1149,7 @@
                     handleActivityConfigurationChanged((IBinder)msg.obj);
                     break;
                 case PROFILER_CONTROL:
-                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
+                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
                     break;
                 case CREATE_BACKUP_AGENT:
                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -1158,6 +1185,10 @@
                     break;
                 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
                     handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
+                    break;
+                case TRIM_MEMORY:
+                    handleTrimMemory(msg.arg1);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
         }
@@ -1189,7 +1220,7 @@
         }
     }
 
-    private final class Idler implements MessageQueue.IdleHandler {
+    private class Idler implements MessageQueue.IdleHandler {
         public final boolean queueIdle() {
             ActivityClientRecord a = mNewActivities;
             if (a != null) {
@@ -1200,12 +1231,13 @@
                     if (localLOGV) Slog.v(
                         TAG, "Reporting idle of " + a +
                         " finished=" +
-                        (a.activity != null ? a.activity.mFinished : false));
+                        (a.activity != null && a.activity.mFinished));
                     if (a.activity != null && !a.activity.mFinished) {
                         try {
                             am.activityIdle(a.token, a.createdConfig);
                             a.createdConfig = null;
                         } catch (RemoteException ex) {
+                            // Ignore
                         }
                     }
                     prev = a;
@@ -1225,7 +1257,7 @@
         }
     }
 
-    private final static class ResourcesKey {
+    private static class ResourcesKey {
         final private String mResDir;
         final private float mScale;
         final private int mHash;
@@ -1251,17 +1283,17 @@
         }
     }
 
-    public static final ActivityThread currentActivityThread() {
+    public static ActivityThread currentActivityThread() {
         return sThreadLocal.get();
     }
 
-    public static final String currentPackageName() {
+    public static String currentPackageName() {
         ActivityThread am = currentActivityThread();
         return (am != null && am.mBoundApplication != null)
             ? am.mBoundApplication.processName : null;
     }
 
-    public static final Application currentApplication() {
+    public static Application currentApplication() {
         ActivityThread am = currentActivityThread();
         return am != null ? am.mInitialApplication : null;
     }
@@ -1306,7 +1338,7 @@
         return config;
     }
 
-    private final Configuration mMainThreadConfig = new Configuration();
+    private Configuration mMainThreadConfig = new Configuration();
     Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) {
         if (config == null) {
             return null;
@@ -1425,6 +1457,7 @@
             ai = getPackageManager().getApplicationInfo(packageName,
                     PackageManager.GET_SHARED_LIBRARY_FILES);
         } catch (RemoteException e) {
+            // Ignore
         }
 
         if (ai != null) {
@@ -1474,7 +1507,7 @@
         }
     }
 
-    private final LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
+    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
             ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
         synchronized (mPackages) {
             WeakReference<LoadedApk> ref;
@@ -1681,15 +1714,15 @@
 
     // if the thread hasn't started yet, we don't have the handler, so just
     // save the messages until we're ready.
-    private final void queueOrSendMessage(int what, Object obj) {
+    private void queueOrSendMessage(int what, Object obj) {
         queueOrSendMessage(what, obj, 0, 0);
     }
 
-    private final void queueOrSendMessage(int what, Object obj, int arg1) {
+    private void queueOrSendMessage(int what, Object obj, int arg1) {
         queueOrSendMessage(what, obj, arg1, 0);
     }
 
-    private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
+    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
         synchronized (this) {
             if (DEBUG_MESSAGES) Slog.v(
                 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
@@ -1712,7 +1745,7 @@
         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
     }
 
-    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
 
         ActivityInfo aInfo = r.activityInfo;
@@ -1830,7 +1863,7 @@
         return activity;
     }
 
-    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -1886,11 +1919,12 @@
                 ActivityManagerNative.getDefault()
                     .finishActivity(r.token, Activity.RESULT_CANCELED, null);
             } catch (RemoteException ex) {
+                // Ignore
             }
         }
     }
 
-    private final void deliverNewIntents(ActivityClientRecord r,
+    private void deliverNewIntents(ActivityClientRecord r,
             List<Intent> intents) {
         final int N = intents.size();
         for (int i=0; i<N; i++) {
@@ -1918,7 +1952,7 @@
         }
     }
 
-    private final void handleNewIntent(NewIntentData data) {
+    private void handleNewIntent(NewIntentData data) {
         performNewIntents(data.token, data.intents);
     }
 
@@ -1933,7 +1967,7 @@
         return sCurrentBroadcastIntent.get();
     }
 
-    private final void handleReceiver(ReceiverData data) {
+    private void handleReceiver(ReceiverData data) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -1945,7 +1979,7 @@
 
         IActivityManager mgr = ActivityManagerNative.getDefault();
 
-        BroadcastReceiver receiver = null;
+        BroadcastReceiver receiver;
         try {
             java.lang.ClassLoader cl = packageInfo.getClassLoader();
             data.intent.setExtrasClassLoader(cl);
@@ -1995,7 +2029,7 @@
     }
 
     // Instantiate a BackupAgent and tell it that it's alive
-    private final void handleCreateBackupAgent(CreateBackupAgentData data) {
+    private void handleCreateBackupAgent(CreateBackupAgentData data) {
         if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
 
         // no longer idle; we have backup work to do
@@ -2060,7 +2094,7 @@
     }
 
     // Tear down a BackupAgent
-    private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
+    private void handleDestroyBackupAgent(CreateBackupAgentData data) {
         if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
 
         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
@@ -2079,7 +2113,7 @@
         }
     }
 
-    private final void handleCreateService(CreateServiceData data) {
+    private void handleCreateService(CreateServiceData data) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -2125,7 +2159,7 @@
         }
     }
 
-    private final void handleBindService(BindServiceData data) {
+    private void handleBindService(BindServiceData data) {
         Service s = mServices.get(data.token);
         if (s != null) {
             try {
@@ -2153,7 +2187,7 @@
         }
     }
 
-    private final void handleUnbindService(BindServiceData data) {
+    private void handleUnbindService(BindServiceData data) {
         Service s = mServices.get(data.token);
         if (s != null) {
             try {
@@ -2205,7 +2239,7 @@
         }
     }
 
-    private final void handleServiceArgs(ServiceArgsData data) {
+    private void handleServiceArgs(ServiceArgsData data) {
         Service s = mServices.get(data.token);
         if (s != null) {
             try {
@@ -2239,7 +2273,7 @@
         }
     }
 
-    private final void handleStopService(IBinder token) {
+    private void handleStopService(IBinder token) {
         Service s = mServices.remove(token);
         if (s != null) {
             try {
@@ -2434,7 +2468,7 @@
     private Bitmap mAvailThumbnailBitmap = null;
     private Canvas mThumbnailCanvas = null;
 
-    private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
+    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
         Bitmap thumbnail = mAvailThumbnailBitmap;
         try {
             if (thumbnail == null) {
@@ -2484,7 +2518,7 @@
         return thumbnail;
     }
 
-    private final void handlePauseActivity(IBinder token, boolean finished,
+    private void handlePauseActivity(IBinder token, boolean finished,
             boolean userLeaving, int configChanges) {
         ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
@@ -2590,7 +2624,7 @@
         CharSequence description;
     }
 
-    private final class ProviderRefCount {
+    private class ProviderRefCount {
         public int count;
         ProviderRefCount(int pCount) {
             count = pCount;
@@ -2605,7 +2639,7 @@
      * For the client, we want to call onStop()/onStart() to indicate when
      * the activity's UI visibillity changes.
      */
-    private final void performStopActivityInner(ActivityClientRecord r,
+    private void performStopActivityInner(ActivityClientRecord r,
             StopInfo info, boolean keepShown, boolean saveState) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
         Bundle state = null;
@@ -2668,7 +2702,7 @@
         }
     }
 
-    private final void updateVisibility(ActivityClientRecord r, boolean show) {
+    private void updateVisibility(ActivityClientRecord r, boolean show) {
         View v = r.activity.mDecor;
         if (v != null) {
             if (show) {
@@ -2695,7 +2729,7 @@
         }
     }
 
-    private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
+    private void handleStopActivity(IBinder token, boolean show, int configChanges) {
         ActivityClientRecord r = mActivities.get(token);
         r.activity.mConfigChangeFlags |= configChanges;
 
@@ -2729,7 +2763,7 @@
         }
     }
 
-    private final void handleWindowVisibility(IBinder token, boolean show) {
+    private void handleWindowVisibility(IBinder token, boolean show) {
         ActivityClientRecord r = mActivities.get(token);
         
         if (r == null) {
@@ -2754,7 +2788,7 @@
         }
     }
 
-    private final void handleSleeping(IBinder token, boolean sleeping) {
+    private void handleSleeping(IBinder token, boolean sleeping) {
         ActivityClientRecord r = mActivities.get(token);
 
         if (r == null) {
@@ -2815,7 +2849,7 @@
         WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
     }
 
-    private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
+    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
         final int N = results.size();
         for (int i=0; i<N; i++) {
             ResultInfo ri = results.get(i);
@@ -2838,7 +2872,7 @@
         }
     }
 
-    private final void handleSendResult(ResultData res) {
+    private void handleSendResult(ResultData res) {
         ActivityClientRecord r = mActivities.get(res.token);
         if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
         if (r != null) {
@@ -2884,7 +2918,7 @@
         return performDestroyActivity(token, finishing, 0, false);
     }
 
-    private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
+    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
             int configChanges, boolean getNonConfigInstance) {
         ActivityClientRecord r = mActivities.get(token);
         Class activityClass = null;
@@ -2977,7 +3011,7 @@
         return component == null ? "[Unknown]" : component.toShortString();
     }
 
-    private final void handleDestroyActivity(IBinder token, boolean finishing,
+    private void handleDestroyActivity(IBinder token, boolean finishing,
             int configChanges, boolean getNonConfigInstance) {
         ActivityClientRecord r = performDestroyActivity(token, finishing,
                 configChanges, getNonConfigInstance);
@@ -3092,7 +3126,7 @@
         }
     }
 
-    private final void handleRelaunchActivity(ActivityClientRecord tmp) {
+    private void handleRelaunchActivity(ActivityClientRecord tmp) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -3202,7 +3236,7 @@
         handleLaunchActivity(r, currentIntent);
     }
 
-    private final void handleRequestThumbnail(IBinder token) {
+    private void handleRequestThumbnail(IBinder token) {
         ActivityClientRecord r = mActivities.get(token);
         Bitmap thumbnail = createThumbnailBitmap(r);
         CharSequence description = null;
@@ -3277,7 +3311,7 @@
         return callbacks;
     }
 
-    private final void performConfigurationChanged(
+    private void performConfigurationChanged(
             ComponentCallbacks cb, Configuration config) {
         // Only for Activity objects, check that they actually call up to their
         // superclass implementation.  ComponentCallbacks is an interface, so
@@ -3420,6 +3454,9 @@
             }
             callbacks = collectComponentCallbacksLocked(false, config);
         }
+        
+        // Cleanup hardware accelerated stuff
+        WindowManagerImpl.getDefault().trimLocalMemory();
 
         if (callbacks != null) {
             final int N = callbacks.size();
@@ -3441,11 +3478,18 @@
         performConfigurationChanged(r.activity, mCompatConfiguration);
     }
 
-    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
+    final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
         if (start) {
             try {
-                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
-                        8 * 1024 * 1024, 0);
+                switch (profileType) {
+                    case 1:
+                        ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor());
+                        break;
+                    default:
+                        Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
+                                8 * 1024 * 1024, 0);
+                        break;
+                }
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Profiling failed on path " + pcd.path
                         + " -- can the process access this path?");
@@ -3457,7 +3501,15 @@
                 }
             }
         } else {
-            Debug.stopMethodTracing();
+            switch (profileType) {
+                case 1:
+                    ViewDebug.stopLooperProfiling();
+                    break;
+                default:
+                    Debug.stopMethodTracing();
+                    break;
+                    
+            }
         }
     }
 
@@ -3529,7 +3581,11 @@
         BinderInternal.forceGc("mem");
     }
 
-    private final void handleBindApplication(AppBindData data) {
+    final void handleTrimMemory(int level) {
+        WindowManagerImpl.getDefault().trimMemory(level);
+    }
+
+    private void handleBindApplication(AppBindData data) {
         mBoundApplication = data;
         mConfiguration = new Configuration(data.config);
         mCompatConfiguration = new Configuration(data.config);
@@ -3741,7 +3797,7 @@
         }
     }
 
-    private final void installContentProviders(
+    private void installContentProviders(
             Context context, List<ProviderInfo> providers) {
         final ArrayList<IActivityManager.ContentProviderHolder> results =
             new ArrayList<IActivityManager.ContentProviderHolder>();
@@ -3775,7 +3831,7 @@
         }
     }
 
-    private final IContentProvider getExistingProvider(Context context, String name) {
+    private IContentProvider getExistingProvider(Context context, String name) {
         synchronized(mProviderMap) {
             final ProviderClientRecord pr = mProviderMap.get(name);
             if (pr != null) {
@@ -3785,7 +3841,7 @@
         }
     }
 
-    private final IContentProvider getProvider(Context context, String name) {
+    private IContentProvider getProvider(Context context, String name) {
         IContentProvider existing = getExistingProvider(context, name);
         if (existing != null) {
             return existing;
@@ -3957,7 +4013,7 @@
         }
     }
 
-    private final IContentProvider installProvider(Context context,
+    private IContentProvider installProvider(Context context,
             IContentProvider provider, ProviderInfo info, boolean noisy) {
         ContentProvider localProvider = null;
         if (provider == null) {
@@ -3977,6 +4033,7 @@
                     c = context.createPackageContext(ai.packageName,
                             Context.CONTEXT_INCLUDE_CODE);
                 } catch (PackageManager.NameNotFoundException e) {
+                    // Ignore
                 }
             }
             if (c == null) {
@@ -4036,11 +4093,11 @@
         return provider;
     }
 
-    private final void attach(boolean system) {
+    private void attach(boolean system) {
         sThreadLocal.set(this);
         mSystemThread = system;
         if (!system) {
-            ViewAncestor.addFirstDrawHandler(new Runnable() {
+            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                 public void run() {
                     ensureJitEnabled();
                 }
@@ -4051,6 +4108,7 @@
             try {
                 mgr.attachApplication(mAppThread);
             } catch (RemoteException ex) {
+                // Ignore
             }
         } else {
             // Don't set application object here -- if the system crashes,
@@ -4070,7 +4128,7 @@
             }
         }
         
-        ViewAncestor.addConfigCallback(new ComponentCallbacks() {
+        ViewRootImpl.addConfigCallback(new ComponentCallbacks() {
             public void onConfigurationChanged(Configuration newConfig) {
                 synchronized (mPackages) {
                     // We need to apply this change to the resources
@@ -4116,7 +4174,7 @@
         }
     }
 
-    public static final void main(String[] args) {
+    public static void main(String[] args) {
         SamplingProfilerIntegration.start();
 
         // CloseGuard defaults to true and can be quite spammy.  We
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index dc0f529..9a5b527 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -376,10 +376,11 @@
         {
             data.enforceInterface(IApplicationThread.descriptor);
             boolean start = data.readInt() != 0;
+            int profileType = data.readInt();
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            profilerControl(start, path, fd);
+            profilerControl(start, path, fd, profileType);
             return true;
         }
         
@@ -478,6 +479,55 @@
             updatePackageCompatibilityInfo(pkg, compat);
             return true;
         }
+
+        case SCHEDULE_TRIM_MEMORY_TRANSACTION: {
+            data.enforceInterface(IApplicationThread.descriptor);
+            int level = data.readInt();
+            scheduleTrimMemory(level);
+            return true;
+        }
+
+        case DUMP_MEM_INFO_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            ParcelFileDescriptor fd = data.readFileDescriptor();
+            String[] args = data.readStringArray();
+            Debug.MemoryInfo mi = null;
+            if (fd != null) {
+                try {
+                    mi = dumpMemInfo(fd.getFileDescriptor(), args);
+                } finally {
+                    try {
+                        fd.close();
+                    } catch (IOException e) {
+                        // swallowed, not propagated back to the caller
+                    }
+                }
+            }
+            reply.writeNoException();
+            mi.writeToParcel(reply, 0);
+            return true;
+        }
+
+        case DUMP_GFX_INFO_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            ParcelFileDescriptor fd = data.readFileDescriptor();
+            String[] args = data.readStringArray();
+            if (fd != null) {
+                try {
+                    dumpGfxInfo(fd.getFileDescriptor(), args);
+                } finally {
+                    try {
+                        fd.close();
+                    } catch (IOException e) {
+                        // swallowed, not propagated back to the caller
+                    }
+                }
+            }
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -887,10 +937,11 @@
     }
     
     public void profilerControl(boolean start, String path,
-            ParcelFileDescriptor fd) throws RemoteException {
+            ParcelFileDescriptor fd, int profileType) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeInt(start ? 1 : 0);
+        data.writeInt(profileType);
         data.writeString(path);
         if (fd != null) {
             data.writeInt(1);
@@ -989,4 +1040,36 @@
         mRemote.transact(UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
     }
+
+    public void scheduleTrimMemory(int level) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeInt(level);
+        mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null,
+                IBinder.FLAG_ONEWAY);
+    }
+
+    public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
+        reply.readException();
+        Debug.MemoryInfo info = new Debug.MemoryInfo();
+        info.readFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+        return info;
+    }
+
+    public void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        mRemote.transact(DUMP_GFX_INFO_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index e5a7980..93330a7 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -224,6 +224,12 @@
                     writer.print(" mExitAnim=#");
                     writer.println(Integer.toHexString(mExitAnim));
         }
+        if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
+            writer.print(prefix); writer.print("mPopEnterAnim=#");
+                    writer.print(Integer.toHexString(mPopEnterAnim));
+                    writer.print(" mPopExitAnim=#");
+                    writer.println(Integer.toHexString(mPopExitAnim));
+        }
         if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
             writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
                     writer.print(Integer.toHexString(mBreadCrumbTitleRes));
@@ -248,13 +254,16 @@
                 writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
                         writer.print(" fragment="); writer.println(op.fragment);
                 if (op.enterAnim != 0 || op.exitAnim != 0) {
-                    writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim);
-                            writer.print(" exitAnim="); writer.println(op.exitAnim);
+                    writer.print(prefix); writer.print("enterAnim=#");
+                            writer.print(Integer.toHexString(op.enterAnim));
+                            writer.print(" exitAnim=#");
+                            writer.println(Integer.toHexString(op.exitAnim));
                 }
                 if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
-                    writer.print(prefix);
-                            writer.print("popEnterAnim="); writer.print(op.popEnterAnim);
-                            writer.print(" popExitAnim="); writer.println(op.popExitAnim);
+                    writer.print(prefix); writer.print("popEnterAnim=#");
+                            writer.print(Integer.toHexString(op.popEnterAnim));
+                            writer.print(" popExitAnim=#");
+                            writer.println(Integer.toHexString(op.popExitAnim));
                 }
                 if (op.removed != null && op.removed.size() > 0) {
                     for (int i=0; i<op.removed.size(); i++) {
@@ -695,11 +704,13 @@
                 } break;
                 case OP_DETACH: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popEnterAnim;
                     mManager.attachFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
                 } break;
                 case OP_ATTACH: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popExitAnim;
                     mManager.detachFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
                 } break;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d2323e7..a99cec2 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -59,6 +59,8 @@
 import android.net.Uri;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.IWifiP2pManager;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -83,6 +85,7 @@
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
+import android.view.textservice.TextServicesManager;
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
@@ -320,6 +323,11 @@
                     return InputMethodManager.getInstance(ctx);
                 }});
 
+        registerService(TEXT_SERVICES_MANAGER_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return TextServicesManager.getInstance();
+                }});
+
         registerService(KEYGUARD_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
                     // TODO: why isn't this caching it?  It wasn't
@@ -432,6 +440,13 @@
                     return new WifiManager(service, ctx.mMainThread.getHandler());
                 }});
 
+        registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
+                    IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
+                    return new WifiP2pManager(service);
+                }});
+
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
                     return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index cb97c46..e2746d4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -162,6 +162,9 @@
  * constructor to instantiate it.  If the empty constructor is not available,
  * a runtime exception will occur in some cases during state restore.
  *
+ * <p>For more documentation, also see the <a
+ * href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+ *
  * <p>Topics covered here:
  * <ol>
  * <li><a href="#OlderPlatforms">Older Platforms</a>
@@ -880,7 +883,7 @@
     public void setHasOptionsMenu(boolean hasMenu) {
         if (mHasMenu != hasMenu) {
             mHasMenu = hasMenu;
-            if (isAdded() && !isHidden()) {
+            if (isAdded() && !isHidden() && isResumed()) {
                 mActivity.invalidateOptionsMenu();
             }
         }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 285f1c1..24550c5 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -978,7 +978,7 @@
                 }
             }
 
-            if (mNeedMenuInvalidate && mActivity != null) {
+            if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
                 mActivity.invalidateOptionsMenu();
                 mNeedMenuInvalidate = false;
             }
@@ -1307,6 +1307,7 @@
             mExecutingActions = true;
             for (int i=0; i<numActions; i++) {
                 mTmpActions[i].run();
+                mTmpActions[i] = null;
             }
             mExecutingActions = false;
             didSomething = true;
@@ -1694,6 +1695,7 @@
     
     public void dispatchDestroy() {
         mDestroyed = true;
+        execPendingActions();
         moveToState(Fragment.INITIALIZING, false);
         mActivity = null;
     }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9e20764..64d77e8 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -284,7 +284,7 @@
     
     // Turn on/off profiling in a particular process.
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException;
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException;
     
     public boolean shutdown(int timeout) throws RemoteException;
     
@@ -363,6 +363,8 @@
 
     public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
 
+    public void updatePersistentConfiguration(Configuration values) throws RemoteException;
+    
     /*
      * Private non-Binder interfaces
      */
@@ -590,4 +592,5 @@
     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;
+    int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 05a68a8..d0607d0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -105,7 +105,7 @@
             throws RemoteException;
     void scheduleLowMemory() throws RemoteException;
     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
-    void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
+    void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType)
             throws RemoteException;
     void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
             throws RemoteException;
@@ -119,6 +119,9 @@
             throws RemoteException;
     void setCoreSettings(Bundle coreSettings) throws RemoteException;
     void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
+    void scheduleTrimMemory(int level) throws RemoteException;
+    Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException;
+    void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -162,4 +165,7 @@
     int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
     int SET_CORE_SETTINGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39;
     int UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40;
+    int SCHEDULE_TRIM_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41;
+    int DUMP_MEM_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+42;
+    int DUMP_GFX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43;
 }
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 2952e6b..f99b420 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -536,9 +536,11 @@
          */
         public final Activity waitForActivityWithTimeout(long timeOut) {
             synchronized (this) {
-                try {
-                    wait(timeOut);
-                } catch (InterruptedException e) {
+                if (mLastActivity == null) {
+                    try {
+                        wait(timeOut);
+                    } catch (InterruptedException e) {
+                    }
                 }
                 if (mLastActivity == null) {
                     return null;
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 42eda02..8e2d360 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -168,6 +168,7 @@
         SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar);
         searchBar.setSearchDialog(this);
         mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
+        mSearchView.setIconified(false);
         mSearchView.setOnCloseListener(mOnCloseListener);
         mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
         mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener);
@@ -633,31 +634,6 @@
         }
 
         /**
-         * Overrides the handling of the back key to move back to the previous
-         * sources or dismiss the search dialog, instead of dismissing the input
-         * method.
-         */
-        @Override
-        public boolean dispatchKeyEventPreIme(KeyEvent event) {
-            if (DBG)
-                Log.d(LOG_TAG, "onKeyPreIme(" + event + ")");
-            if (mSearchDialog != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-                KeyEvent.DispatcherState state = getKeyDispatcherState();
-                if (state != null) {
-                    if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                        state.startTracking(event, this);
-                        return true;
-                    } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()
-                            && state.isTracking(event)) {
-                        mSearchDialog.onBackPressed();
-                        return true;
-                    }
-                }
-            }
-            return super.dispatchKeyEventPreIme(event);
-        }
-
-        /**
          * Don't allow action modes in a SearchBar, it looks silly.
          */
         @Override
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index c179b35..4c21d04 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -662,12 +662,6 @@
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         writer.println("nothing to dump");
     }
-    
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        //Log.i("Service", "Finalizing Service: " + this);
-    }
 
     // ------------------ Internal API ------------------
     
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1af0983..ca64c88 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -97,9 +97,10 @@
         }
     }
 
-    public void setIcon(String slot, int iconId, int iconLevel) {
+    public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
         try {
-            mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel);
+            mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,
+                    contentDescription);
         } catch (RemoteException ex) {
             // system process is dead anyway.
             throw new RuntimeException(ex);
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 7fd5a7d..8472b31 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -40,7 +40,7 @@
 import android.os.ServiceManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -592,7 +592,7 @@
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewAncestor.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -630,7 +630,7 @@
             int x, int y, int z, Bundle extras) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewAncestor.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+            ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -650,7 +650,7 @@
      */
     public void clearWallpaperOffsets(IBinder windowToken) {
         try {
-            ViewAncestor.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
             // Ignore.
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index dce0a97..436fdf8 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -533,6 +534,16 @@
                 Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw ex;
             } finally {
+                // Send the EOD marker indicating that there is no more data
+                // forthcoming from this agent.
+                try {
+                    FileOutputStream out = new FileOutputStream(data.getFileDescriptor());
+                    byte[] buf = new byte[4];
+                    out.write(buf);
+                } catch (IOException e) {
+                    Log.e(TAG, "Unable to finalize backup stream!");
+                }
+
                 Binder.restoreCallingIdentity(ident);
                 try {
                     callbackBinder.opComplete(token);
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 8204a4f..08bc0ac 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -261,6 +261,10 @@
             TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
         appWidget.minHeight =
             TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics);
+        appWidget.minResizeWidth =
+            TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics);
+        appWidget.minResizeHeight =
+            TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics);
 
         synchronized (mViews) {
             v = mViews.get(appWidgetId);
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 019652c..1ef99a1 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -388,6 +388,10 @@
                         TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
                 info.minHeight =
                         TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
+                info.minResizeWidth =
+                    TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
+                info.minResizeHeight =
+                    TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
             }
             return providers;
         }
@@ -411,6 +415,10 @@
                         TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
                 info.minHeight =
                         TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
+                info.minResizeWidth =
+                    TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics);
+                info.minResizeHeight =
+                    TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics);
             }
             return info;
         }
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index b46802e..9c352d5 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,7 +54,8 @@
     public ComponentName provider;
 
     /**
-     * Minimum width of the AppWidget, in dp.
+     * The default height of the widget when added to a host, in dp. The widget will get
+     * at least this width, and will often be given more, depending on the host.
      *
      * <p>This field corresponds to the <code>android:minWidth</code> attribute in
      * the AppWidget meta-data file.
@@ -62,7 +63,8 @@
     public int minWidth;
 
     /**
-     * Minimum height of the AppWidget, in dp.
+     * The default height of the widget when added to a host, in dp. The widget will get
+     * at least this height, and will often be given more, depending on the host.
      *
      * <p>This field corresponds to the <code>android:minHeight</code> attribute in
      * the AppWidget meta-data file.
@@ -70,6 +72,24 @@
     public int minHeight;
 
     /**
+     * Minimum width (in dp) which the widget can be resized to. This field has no effect if it
+     * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
+     *
+     * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in
+     * the AppWidget meta-data file.
+     */
+    public int minResizeWidth;
+
+    /**
+     * Minimum height (in dp) which the widget can be resized to. This field has no effect if it
+     * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
+     *
+     * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in
+     * the AppWidget meta-data file.
+     */
+    public int minResizeHeight;
+
+    /**
      * How often, in milliseconds, that this AppWidget wants to be updated.
      * The AppWidget manager may place a limit on how often a AppWidget is updated.
      *
@@ -167,6 +187,8 @@
         }
         this.minWidth = in.readInt();
         this.minHeight = in.readInt();
+        this.minResizeWidth = in.readInt();
+        this.minResizeHeight = in.readInt();
         this.updatePeriodMillis = in.readInt();
         this.initialLayout = in.readInt();
         if (0 != in.readInt()) {
@@ -188,6 +210,8 @@
         }
         out.writeInt(this.minWidth);
         out.writeInt(this.minHeight);
+        out.writeInt(this.minResizeWidth);
+        out.writeInt(this.minResizeHeight);
         out.writeInt(this.updatePeriodMillis);
         out.writeInt(this.initialLayout);
         if (this.configure != null) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b993bd8..ca6f085 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1143,6 +1143,69 @@
         }
     }
 
+    /**
+     * Enable control of the Bluetooth Adapter for a single application.
+     *
+     * <p>Some applications need to use Bluetooth for short periods of time to
+     * transfer data but don't want all the associated implications like
+     * automatic connection to headsets etc.
+     *
+     * <p> Multiple applications can call this. This is reference counted and
+     * Bluetooth disabled only when no one else is using it. There will be no UI
+     * shown to the user while bluetooth is being enabled. Any user action will
+     * override this call. For example, if user wants Bluetooth on and the last
+     * user of this API wanted to disable Bluetooth, Bluetooth will not be
+     * turned off.
+     *
+     * <p> This API is only meant to be used by internal applications. Third
+     * party applications but use {@link #enable} and {@link #disable} APIs.
+     *
+     * <p> If this API returns true, it means the callback will be called.
+     * The callback will be called with the current state of Bluetooth.
+     * If the state is not what was requested, an internal error would be the
+     * reason.
+     *
+     * @param on True for on, false for off.
+     * @param callback The callback to notify changes to the state.
+     * @hide
+     */
+    public boolean changeApplicationBluetoothState(boolean on,
+                                                   BluetoothStateChangeCallback callback) {
+        if (callback == null) return false;
+
+        try {
+            return mService.changeApplicationBluetoothState(on, new
+                    StateChangeCallbackWrapper(callback), new Binder());
+        } catch (RemoteException e) {
+            Log.e(TAG, "changeBluetoothState", e);
+        }
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    public interface BluetoothStateChangeCallback {
+        public void onBluetoothStateChange(boolean on);
+    }
+
+    /**
+     * @hide
+     */
+    public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
+        private BluetoothStateChangeCallback mCallback;
+
+        StateChangeCallbackWrapper(BluetoothStateChangeCallback
+                callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void onBluetoothStateChange(boolean on) {
+            mCallback.onBluetoothStateChange(on);
+        }
+    }
+
     private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
         Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
         for (int i = 0; i < addresses.length; i++) {
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index ab3a426..095cd11 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -120,6 +120,7 @@
     private Pair<Integer, String> mIncomingConnections;
     private PowerManager.WakeLock mWakeLock;
     private PowerManager mPowerManager;
+    private boolean mPairingRequestRcvd = false;
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -187,27 +188,38 @@
                 Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY);
                 msg.arg1 = val;
                 sendMessage(msg);
+            } else if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
+                mPairingRequestRcvd = true;
+            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
+                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
+                        BluetoothDevice.ERROR);
+                if (state == BluetoothDevice.BOND_BONDED && mPairingRequestRcvd) {
+                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
+                    mPairingRequestRcvd = false;
+                } else if (state == BluetoothDevice.BOND_NONE) {
+                    mPairingRequestRcvd = false;
+                }
             }
         }
     };
 
     private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) {
-      // This works only because these broadcast intents are "sticky"
-      Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
-      if (i != null) {
-          int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-          if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-              BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-              if (device != null && autoConnectDevice.equals(device)) {
-                  return true;
-              }
-          }
-      }
-      return false;
-  }
+        // This works only because these broadcast intents are "sticky"
+        Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
+        if (i != null) {
+            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
+            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                if (device != null && autoConnectDevice.equals(device)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 
     public BluetoothDeviceProfileState(Context context, String address,
-          BluetoothService service, BluetoothA2dpService a2dpService) {
+          BluetoothService service, BluetoothA2dpService a2dpService, boolean setTrust) {
         super(address);
         mContext = context;
         mDevice = new BluetoothDevice(address);
@@ -231,6 +243,8 @@
         filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
         filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
+        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
 
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
@@ -247,6 +261,10 @@
                                               PowerManager.ACQUIRE_CAUSES_WAKEUP |
                                               PowerManager.ON_AFTER_RELEASE, TAG);
         mWakeLock.setReferenceCounted(false);
+
+        if (setTrust) {
+            setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
+        }
     }
 
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 3284361..8f2b3d8 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -661,7 +661,7 @@
      */
     public boolean disconnectHeadsetInternal(BluetoothDevice device) {
         if (DBG) log("disconnectHeadsetInternal");
-        if (mService != null && isEnabled()) {
+        if (mService != null && !isDisabled()) {
             try {
                  return mService.disconnectHeadsetInternal(device);
             } catch (RemoteException e) {Log.e(TAG, e.toString());}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 183772d..be43c51 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
 import android.bluetooth.IBluetoothHealthCallback;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHealthAppConfiguration;
@@ -52,6 +53,9 @@
     byte[] readOutOfBandData();
 
     int getAdapterConnectionState();
+    boolean changeApplicationBluetoothState(boolean on,
+                                in IBluetoothStateChangeCallback callback, in
+                                IBinder b);
 
     boolean createBond(in String address);
     boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
diff --git a/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
new file mode 100644
index 0000000..feccdce
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.bluetooth;
+
+/**
+ * System private API for Bluetooth state change callback.
+ *
+ * {@hide}
+ */
+interface IBluetoothStateChangeCallback
+{
+    void onBluetoothStateChange(boolean on);
+}
diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java
index dad60b0..37cc141 100644
--- a/core/java/android/content/ComponentCallbacks.java
+++ b/core/java/android/content/ComponentCallbacks.java
@@ -51,4 +51,13 @@
      * The system will perform a gc for you after returning from this method.
      */
     void onLowMemory();
+
+    /** @hide */
+    static final int TRIM_MEMORY_COMPLETE = 80;
+
+    /** @hide */
+    static final int TRIM_MEMORY_MODERATE = 50;
+
+    /** @hide */
+    static final int TRIM_MEMORY_BACKGROUND = 20;
 }
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index a2af558..0e83dc0 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -20,17 +20,21 @@
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.util.SparseIntArray;
 import android.Manifest;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 /**
@@ -70,6 +74,40 @@
             } else {
                 mSyncManager.dump(fd, pw);
             }
+            pw.println();
+            pw.println("Observer tree:");
+            synchronized (mRootNode) {
+                int[] counts = new int[2];
+                final SparseIntArray pidCounts = new SparseIntArray();
+                mRootNode.dumpLocked(fd, pw, args, "", "  ", counts, pidCounts);
+                pw.println();
+                ArrayList<Integer> sorted = new ArrayList<Integer>();
+                for (int i=0; i<pidCounts.size(); i++) {
+                    sorted.add(pidCounts.keyAt(i));
+                }
+                Collections.sort(sorted, new Comparator<Integer>() {
+                    @Override
+                    public int compare(Integer lhs, Integer rhs) {
+                        int lc = pidCounts.get(lhs);
+                        int rc = pidCounts.get(rhs);
+                        if (lc < rc) {
+                            return 1;
+                        } else if (lc > rc) {
+                            return -1;
+                        }
+                        return 0;
+                    }
+
+                });
+                for (int i=0; i<sorted.size(); i++) {
+                    int pid = sorted.get(i);
+                    pw.print("  pid "); pw.print(pid); pw.print(": ");
+                            pw.print(pidCounts.get(pid)); pw.println(" observers");
+                }
+                pw.println();
+                pw.print(" Total number of nodes: "); pw.println(counts[0]);
+                pw.print(" Total number of observers: "); pw.println(counts[1]);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -102,7 +140,8 @@
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
         synchronized (mRootNode) {
-            mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode);
+            mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode,
+                    Binder.getCallingUid(), Binder.getCallingPid());
             if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
                     " with notifyForDescendents " + notifyForDescendents);
         }
@@ -465,12 +504,17 @@
     public static final class ObserverNode {
         private class ObserverEntry implements IBinder.DeathRecipient {
             public final IContentObserver observer;
+            public final int uid;
+            public final int pid;
             public final boolean notifyForDescendents;
             private final Object observersLock;
 
-            public ObserverEntry(IContentObserver o, boolean n, Object observersLock) {
+            public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
+                    int _uid, int _pid) {
                 this.observersLock = observersLock;
                 observer = o;
+                uid = _uid;
+                pid = _pid;
                 notifyForDescendents = n;
                 try {
                     observer.asBinder().linkToDeath(this, 0);
@@ -484,6 +528,16 @@
                     removeObserverLocked(observer);
                 }
             }
+
+            public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+                    String name, String prefix, SparseIntArray pidCounts) {
+                pidCounts.put(pid, pidCounts.get(pid)+1);
+                pw.print(prefix); pw.print(name); pw.print(": pid=");
+                        pw.print(pid); pw.print(" uid=");
+                        pw.print(uid); pw.print(" target=");
+                        pw.println(Integer.toHexString(System.identityHashCode(
+                                observer != null ? observer.asBinder() : null)));
+            }
         }
 
         public static final int INSERT_TYPE = 0;
@@ -498,6 +552,37 @@
             mName = name;
         }
 
+        public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+                String name, String prefix, int[] counts, SparseIntArray pidCounts) {
+            String innerName = null;
+            if (mObservers.size() > 0) {
+                if ("".equals(name)) {
+                    innerName = mName;
+                } else {
+                    innerName = name + "/" + mName;
+                }
+                for (int i=0; i<mObservers.size(); i++) {
+                    counts[1]++;
+                    mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix,
+                            pidCounts);
+                }
+            }
+            if (mChildren.size() > 0) {
+                if (innerName == null) {
+                    if ("".equals(name)) {
+                        innerName = mName;
+                    } else {
+                        innerName = name + "/" + mName;
+                    }
+                }
+                for (int i=0; i<mChildren.size(); i++) {
+                    counts[0]++;
+                    mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix,
+                            counts, pidCounts);
+                }
+            }
+        }
+
         private String getUriSegment(Uri uri, int index) {
             if (uri != null) {
                 if (index == 0) {
@@ -518,15 +603,16 @@
         }
 
         public void addObserverLocked(Uri uri, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock) {
-            addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock);
+                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
+            addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid);
         }
 
         private void addObserverLocked(Uri uri, int index, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock) {
+                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
             // If this is the leaf node add the observer
             if (index == countUriSegments(uri)) {
-                mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock));
+                mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock,
+                        uid, pid));
                 return;
             }
 
@@ -539,7 +625,8 @@
             for (int i = 0; i < N; i++) {
                 ObserverNode node = mChildren.get(i);
                 if (node.mName.equals(segment)) {
-                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
+                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
+                            observersLock, uid, pid);
                     return;
                 }
             }
@@ -547,7 +634,8 @@
             // No child found, create one
             ObserverNode node = new ObserverNode(segment);
             mChildren.add(node);
-            node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
+            node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
+                    observersLock, uid, pid);
         }
 
         public boolean removeObserverLocked(IContentObserver observer) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fed6d81..2a02446 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -129,7 +129,7 @@
     /**
      * Flag for {@link #bindService}: don't allow this binding to raise
      * the target service's process to the foreground scheduling priority.
-     * It will still be raised to the at least the same memory priority
+     * It will still be raised to at least the same memory priority
      * as the client (so that its process will not be killable in any
      * situation where the client is not killable), but for CPU scheduling
      * purposes it may be left in the background.  This only has an impact
@@ -138,6 +138,16 @@
      */
     public static final int BIND_NOT_FOREGROUND = 0x0004;
 
+    /**
+     * Flag for {@link #bindService}: allow the process hosting the bound
+     * service to go through its normal memory management.  It will be
+     * treated more like a running service, allowing the system to
+     * (temporarily) expunge the process if low on memory or for some other
+     * whim it may have.
+     * @hide
+     */
+    public static final int BIND_ALLOW_OOM_MANAGEMENT = 0x0008;
+
     /** Return an AssetManager instance for your application's package. */
     public abstract AssetManager getAssets();
 
@@ -1572,6 +1582,17 @@
     public static final String WIFI_SERVICE = "wifi";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.net.wifi.p2p.WifiP2pManager} for handling management of
+     * Wi-Fi p2p.
+     *
+     * @see #getSystemService
+     * @see android.net.wifi.p2p.WifiP2pManager
+     * @hide
+     */
+    public static final String WIFI_P2P_SERVICE = "wifip2p";
+
+    /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.media.AudioManager} for handling management of volume,
      * ringer modes and audio routing.
@@ -1612,6 +1633,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.view.textservice.TextServicesManager} for accessing
+     * text services.
+     *
+     * @see #getSystemService
+     */
+    public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
      *
      * @hide
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 4e70b74..368c33e 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -40,6 +40,8 @@
  *
  * <p>Most implementations should not derive directly from this class, but
  * instead inherit from {@link AsyncTaskLoader}.</p>
+ * <p>For more information, see the <a
+ * href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p>
  *
  * @param <D> The result returned when the load is complete
  */
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
index 3d89e92..e1a8d21 100644
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ b/core/java/android/content/SearchRecentSuggestionsProvider.java
@@ -186,6 +186,9 @@
 
             mSuggestionProjection = new String [] {
                     "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
+                    "'android.resource://system/"
+                            + com.android.internal.R.drawable.ic_menu_recent_history + "' AS "
+                            + SearchManager.SUGGEST_COLUMN_ICON_1,
                     "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                     "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
                     "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
@@ -196,6 +199,9 @@
 
             mSuggestionProjection = new String [] {
                     "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
+                    "'android.resource://system/"
+                            + com.android.internal.R.drawable.ic_menu_recent_history + "' AS "
+                            + SearchManager.SUGGEST_COLUMN_ICON_1,
                     "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                     "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
                     "_id"
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 2cb8a86..5be6ec1 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1691,12 +1691,28 @@
                         continue;
                     }
 
-                    // skip the sync if it isn't manual and auto sync or
-                    // background data usage is disabled
+                    final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+                    syncAdapterInfo = mSyncAdapters.getServiceInfo(
+                            SyncAdapterType.newKey(op.authority, op.account.type));
+
+                    // only proceed if network is connected for requesting UID
+                    final boolean uidNetworkConnected;
+                    if (syncAdapterInfo != null) {
+                        final NetworkInfo networkInfo = getConnectivityManager()
+                                .getActiveNetworkInfoForUid(syncAdapterInfo.uid);
+                        uidNetworkConnected = networkInfo != null && networkInfo.isConnected();
+                    } else {
+                        uidNetworkConnected = false;
+                    }
+
+                    // skip the sync if it isn't manual, and auto sync or
+                    // background data usage is disabled or network is
+                    // disconnected for the target UID.
                     if (!op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
                             && (syncableState > 0)
                             && (!masterSyncAutomatically
                                 || !backgroundDataUsageAllowed
+                                || !uidNetworkConnected
                                 || !mSyncStorageEngine.getSyncAutomatically(
                                        op.account, op.authority))) {
                         operationIterator.remove();
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index d4e5cc1..b32664e 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -45,16 +45,23 @@
      * {@link #toChars} or {@link #toCharsString()}.
      */
     public Signature(String text) {
-        final int N = text.length()/2;
-        byte[] sig = new byte[N];
-        for (int i=0; i<N; i++) {
-            char c = text.charAt(i*2);
-            byte b = (byte)(
-                    (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4);
-            c = text.charAt(i*2 + 1);
-            b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0'));
-            sig[i] = b;
+        final byte[] input = text.getBytes();
+        final int N = input.length;
+        final byte[] sig = new byte[N / 2];
+        int sigIndex = 0;
+
+        for (int i = 0; i < N;) {
+            int b;
+
+            final int hi = input[i++];
+            b = (hi >= 'a' ? (hi - 'a' + 10) : (hi - '0')) << 4;
+
+            final int lo = input[i++];
+            b |= (lo >= 'a' ? (lo - 'a' + 10) : (lo - '0')) & 0x0F;
+
+            sig[sigIndex++] = (byte) (b & 0xFF);
         }
+
         mSignature = sig;
     }
 
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index 5c1b968..6e68b6b 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -272,6 +272,12 @@
     }
 
     @Override
+    public byte[] getBlob(int column) {
+        Object value = get(column);
+        return (byte[]) value;
+    }
+
+    @Override
     public int getType(int column) {
         return DatabaseUtils.getTypeOfObject(get(column));
     }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 8a42693..d6dbc15 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -16,7 +16,10 @@
 
 package android.hardware;
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.graphics.ImageFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.os.Handler;
@@ -33,6 +36,7 @@
 import java.util.List;
 import java.util.StringTokenizer;
 
+
 /**
  * The Camera class is used to set image capture settings, start/stop preview,
  * snap pictures, and retrieve frames for encoding for video.  This class is a
@@ -126,7 +130,9 @@
     private static final int CAMERA_MSG_POSTVIEW_FRAME   = 0x040;
     private static final int CAMERA_MSG_RAW_IMAGE        = 0x080;
     private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
-    private static final int CAMERA_MSG_ALL_MSGS         = 0x1FF;
+    private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200;
+    private static final int CAMERA_MSG_FACE             = 0x400;
+    private static final int CAMERA_MSG_ALL_MSGS         = 0x4FF;
 
     private int mNativeContext; // accessed by native methods
     private EventHandler mEventHandler;
@@ -137,9 +143,46 @@
     private PictureCallback mPostviewCallback;
     private AutoFocusCallback mAutoFocusCallback;
     private OnZoomChangeListener mZoomListener;
+    private FaceDetectionListener mFaceListener;
     private ErrorCallback mErrorCallback;
     private boolean mOneShot;
     private boolean mWithBuffer;
+    private boolean mFaceDetectionRunning = false;
+
+    /**
+     * Broadcast Action:  A new picture is taken by the camera, and the entry of
+     * the picture has been added to the media store.
+     * {@link android.content.Intent#getData} is URI of the picture.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+
+    /**
+     * Broadcast Action:  A new video is recorded by the camera, and the entry
+     * of the video has been added to the media store.
+     * {@link android.content.Intent#getData} is URI of the video.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+
+    /**
+     * Hardware face detection. It does not use much CPU.
+     *
+     * @see #startFaceDetection(int)
+     * @see Parameters#getMaxNumDetectedFaces(int)
+     * @see #CAMERA_FACE_DETECTION_SW
+     * @hide
+     */
+    public static final int CAMERA_FACE_DETECTION_HW = 0;
+
+    /**
+     * Software face detection. It uses some CPU. Applications must use
+     * {@link #setPreviewTexture(SurfaceTexture)} for preview in this mode.
+     *
+     * @see #CAMERA_FACE_DETECTION_HW
+     * @hide
+     */
+    public static final int CAMERA_FACE_DETECTION_SW = 1;
 
     /**
      * Returns the number of physical cameras available on this device.
@@ -277,6 +320,7 @@
      */
     public final void release() {
         native_release();
+        mFaceDetectionRunning = false;
     }
 
     /**
@@ -442,7 +486,12 @@
      * Stops capturing and drawing preview frames to the surface, and
      * resets the camera for a future call to {@link #startPreview()}.
      */
-    public native final void stopPreview();
+    public final void stopPreview() {
+        _stopPreview();
+        mFaceDetectionRunning = false;
+    }
+
+    private native final void _stopPreview();
 
     /**
      * Return current preview state.
@@ -672,6 +721,12 @@
                 }
                 return;
 
+            case CAMERA_MSG_FACE:
+                if (mFaceListener != null) {
+                    mFaceListener.onFaceDetection((FaceMetadata[])msg.obj, mCamera);
+                }
+                return;
+
             case CAMERA_MSG_ERROR :
                 Log.e(TAG, "Error " + msg.arg1);
                 if (mErrorCallback != null) {
@@ -720,8 +775,20 @@
          * onAutoFocus will be called immediately with a fake value of
          * <code>success</code> set to <code>true</code>.
          *
+         * The auto-focus routine may lock auto-exposure and auto-white balance
+         * after it completes. To check for the state of these locks, use the
+         * {@link android.hardware.Camera.Parameters#getAutoExposureLock()} and
+         * {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()}
+         * methods. If such locking is undesirable, use
+         * {@link android.hardware.Camera.Parameters#setAutoExposureLock(boolean)}
+         * and
+         * {@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)}
+         * to release the locks.
+         *
          * @param success true if focus was successful, false if otherwise
          * @param camera  the Camera service object
+         * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean)
+         * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)
          */
         void onAutoFocus(boolean success, Camera camera);
     };
@@ -747,8 +814,21 @@
      * {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}, flash may be
      * fired during auto-focus, depending on the driver and camera hardware.<p>
      *
+     * The auto-focus routine may lock auto-exposure and auto-white balance
+     * after it completes. To check for the state of these locks, use the
+     * {@link android.hardware.Camera.Parameters#getAutoExposureLock()} and
+     * {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()}
+     * methods after the {@link AutoFocusCallback#onAutoFocus(boolean, Camera)}
+     * callback is invoked. If such locking is undesirable, use
+     * {@link android.hardware.Camera.Parameters#setAutoExposureLock(boolean)}
+     * and
+     * {@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)}
+     * to release the locks.
+     *
      * @param cb the callback to run
      * @see #cancelAutoFocus()
+     * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean)
+     * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)
      */
     public final void autoFocus(AutoFocusCallback cb)
     {
@@ -763,7 +843,13 @@
      * this function will return the focus position to the default.
      * If the camera does not support auto-focus, this is a no-op.
      *
+     * Canceling auto-focus will return the auto-exposure lock and auto-white
+     * balance lock to their state before {@link #autoFocus(AutoFocusCallback)}
+     * was called.
+     *
      * @see #autoFocus(Camera.AutoFocusCallback)
+     * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean)
+     * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)
      */
     public final void cancelAutoFocus()
     {
@@ -982,6 +1068,139 @@
         mZoomListener = listener;
     }
 
+    /**
+     * Callback interface for face detected in the preview frame.
+     *
+     * @hide
+     */
+    public interface FaceDetectionListener
+    {
+        /**
+         * Notify the listener of the detected faces in the preview frame.
+         *
+         * @param faceMetadata the face information. The list is sorted by the
+         *        score. The highest score is the first element.
+         * @param camera  the Camera service object
+         */
+        void onFaceDetection(FaceMetadata[] faceMetadata, Camera camera);
+    }
+
+    /**
+     * Registers a listener to be notified about the face detected of the
+     * preview frame.
+     *
+     * @param listener the listener to notify
+     * @see #startFaceDetection(int)
+     * @hide
+     */
+    public final void setFaceDetectionListener(FaceDetectionListener listener)
+    {
+        mFaceListener = listener;
+    }
+
+    /**
+     * Start the face detection. This should be called after preview is started.
+     * The camera will notify {@link FaceDetectionListener} of the detected
+     * faces in the preview frame. The detected faces may be the same as the
+     * previous ones. Applications should call {@link #stopFaceDetection} to
+     * stop the face detection. This method is supported if {@link
+     * Parameters#getMaxNumDetectedFaces(int)} returns a number larger than 0.
+     * Hardware and software face detection cannot be used at the same time.
+     * If the face detection has started, apps should not call this again.
+     *
+     * In hardware face detection mode, {@link Parameters#setWhiteBalance(String)},
+     * {@link Parameters#setFocusAreas(List)}, and {@link Parameters#setMeteringAreas(List)}
+     * have no effect.
+     *
+     * @param type face detection type. This can be either {@link
+     *        #CAMERA_FACE_DETECTION_HW} or {@link #CAMERA_FACE_DETECTION_SW}
+     * @throws IllegalArgumentException if the face detection type is
+     *         unsupported or invalid.
+     * @throws RuntimeException if the method fails or the face detection is
+     *         already running.
+     * @see #CAMERA_FACE_DETECTION_HW
+     * @see #CAMERA_FACE_DETECTION_SW
+     * @see FaceDetectionListener
+     * @see #stopFaceDetection()
+     * @see Parameters#getMaxNumDetectedFaces(int)
+     * @hide
+     */
+    public final void startFaceDetection(int type) {
+        if (type != CAMERA_FACE_DETECTION_HW && type != CAMERA_FACE_DETECTION_SW) {
+            throw new IllegalArgumentException("Invalid face detection type " + type);
+        }
+        if (mFaceDetectionRunning) {
+            throw new RuntimeException("Face detection is already running");
+        }
+        _startFaceDetection(type);
+        mFaceDetectionRunning = true;
+    }
+
+    /**
+     * Stop the face detection.
+     *
+     * @see #startFaceDetection(int)
+     * @hide
+     */
+    public final void stopFaceDetection() {
+        _stopFaceDetection();
+        mFaceDetectionRunning = false;
+    }
+
+    private native final void _startFaceDetection(int type);
+    private native final void _stopFaceDetection();
+
+    /**
+     * The information of a face.
+     *
+     * @hide
+     */
+    public static class FaceMetadata {
+        /**
+         * Bounds of the face. (-1000, -1000) represents the top-left of the
+         * camera field of view, and (1000, 1000) represents the bottom-right of
+         * the field of view. This is supported by both hardware and software
+         * face detection.
+         *
+         * @see #startFaceDetection(int)
+         */
+        Rect face;
+
+        /**
+         * The confidence level of the face. The range is 1 to 100. 100 is the
+         * highest confidence. This is supported by both hardware and software
+         * face detction.
+         *
+         * @see #startFaceDetection(int)
+         */
+        int score;
+
+        /**
+         * An unique id per face while the face is visible to the tracker. If
+         * the face leaves the field-of-view and comes back, it will get a new
+         * id. If the value is 0, id is not supported.
+         */
+        int id;
+
+        /**
+         * The coordinates of the center of the left eye. null if this is not
+         * supported.
+         */
+        Point leftEye;
+
+        /**
+         * The coordinates of the center of the right eye. null if this is not
+         * supported.
+         */
+        Point rightEye;
+
+        /**
+         * The coordinates of the center of the mouth. null if this is not
+         * supported.
+         */
+        Point mouth;
+    }
+
     // Error codes match the enum in include/ui/Camera.h
 
     /**
@@ -1246,6 +1465,8 @@
         private static final String KEY_VIDEO_SIZE = "video-size";
         private static final String KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO =
                                             "preferred-preview-size-for-video";
+        private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw";
+        private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw";
 
         // Parameter key suffix for supported values.
         private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -2562,8 +2783,6 @@
          *        routine is free to run normally.
          *
          * @see #getAutoExposureLock()
-         *
-         * @hide
          */
         public void setAutoExposureLock(boolean toggle) {
             set(KEY_AUTO_EXPOSURE_LOCK, toggle ? TRUE : FALSE);
@@ -2583,7 +2802,6 @@
          *
          * @see #setAutoExposureLock(boolean)
          *
-         * @hide
          */
         public boolean getAutoExposureLock() {
             String str = get(KEY_AUTO_EXPOSURE_LOCK);
@@ -2598,7 +2816,6 @@
          * @return true if auto-exposure lock is supported.
          * @see #setAutoExposureLock(boolean)
          *
-         * @hide
          */
         public boolean isAutoExposureLockSupported() {
             String str = get(KEY_AUTO_EXPOSURE_LOCK_SUPPORTED);
@@ -2645,8 +2862,6 @@
          *        auto-white balance routine is free to run normally.
          *
          * @see #getAutoWhiteBalanceLock()
-         *
-         * @hide
          */
         public void setAutoWhiteBalanceLock(boolean toggle) {
             set(KEY_AUTO_WHITEBALANCE_LOCK, toggle ? TRUE : FALSE);
@@ -2668,7 +2883,6 @@
          *
          * @see #setAutoWhiteBalanceLock(boolean)
          *
-         * @hide
          */
         public boolean getAutoWhiteBalanceLock() {
             String str = get(KEY_AUTO_WHITEBALANCE_LOCK);
@@ -2683,7 +2897,6 @@
          * @return true if auto-white balance lock is supported.
          * @see #setAutoWhiteBalanceLock(boolean)
          *
-         * @hide
          */
         public boolean isAutoWhiteBalanceLockSupported() {
             String str = get(KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED);
@@ -2936,6 +3149,25 @@
             set(KEY_METERING_AREAS, meteringAreas);
         }
 
+        /**
+         * Gets the maximum number of detected faces supported. This is the
+         * maximum length of the list returned from {@link FaceDetectionListener}.
+         * If the return value is 0, face detection of the specified type is not
+         * supported.
+         *
+         * @return the maximum number of detected face supported by the camera.
+         * @see #startFaceDetection(int)
+         * @hide
+         */
+        public int getMaxNumDetectedFaces(int type) {
+            if (type == CAMERA_FACE_DETECTION_HW) {
+                return getInt(KEY_MAX_NUM_DETECTED_FACES_HW, 0);
+            } else if (type == CAMERA_FACE_DETECTION_SW){
+                return getInt(KEY_MAX_NUM_DETECTED_FACES_SW, 0);
+            }
+            throw new IllegalArgumentException("Invalid face detection type " + type);
+        }
+
         // Splits a comma delimited string to an ArrayList of String.
         // Return null if the passing string is null or the size is 0.
         private ArrayList<String> split(String str) {
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 67d200c..b548623 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -409,9 +409,10 @@
 
     /**
      * Sets the current USB function.
+     * If function is null, then the current function is set to the default function.
      *
-     * @param function name of the USB function
-     * @param makeDefault true if this should be set as the default
+     * @param function name of the USB function, or null to restore the default function
+     * @param makeDefault true if the function should be set as the new default function
      *
      * {@hide}
      */
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index eafff49..5cfa998 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -172,7 +172,10 @@
 
         @Override
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
-            return mCallback.onActionItemClicked(this, item);
+            if (mCallback != null) {
+                return mCallback.onActionItemClicked(this, item);
+            }
+            return false;
         }
 
         @Override
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 3447e76c..44e7e52a 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -98,11 +98,8 @@
     }
     
     @Override public boolean onTextContextMenuItem(int id) {
-        // Horrible hack: select word option has to be handled by original view to work.
-        if (mIME != null && id != android.R.id.startSelectingText) {
-            if (mIME.onExtractTextContextMenuItem(id)) {
-                return true;
-            }
+        if (mIME != null && mIME.onExtractTextContextMenuItem(id)) {
+            return true;
         }
         return super.onTextContextMenuItem(id);
     }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ce6f697..a564d97 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -653,6 +653,17 @@
         }
     }
 
+    /**
+     * {@hide}
+     */
+    public int setUsbTethering(boolean enable) {
+        try {
+            return mService.setUsbTethering(enable);
+        } catch (RemoteException e) {
+            return TETHER_ERROR_SERVICE_UNAVAIL;
+        }
+    }
+
     /** {@hide} */
     public static final int TETHER_ERROR_NO_ERROR           = 0;
     /** {@hide} */
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index a866436..b035c51 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -103,6 +103,10 @@
         public void interfaceRemoved(String iface) {
             mTracker.interfaceRemoved(iface);
         }
+
+        public void limitReached(String limitName, String iface) {
+            // Ignored.
+        }
     }
 
     private EthernetDataTracker() {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d6f5643..b1d99a4 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -88,6 +88,8 @@
 
     String[] getTetherableBluetoothRegexs();
 
+    int setUsbTethering(boolean enable);
+
     void requestNetworkTransitionWakelock(in String forWhom);
 
     void reportInetCondition(int networkType, int percentage);
@@ -100,7 +102,7 @@
 
     void setDataDependency(int networkType, boolean met);
 
-    void protectVpn(in ParcelFileDescriptor socket);
+    boolean protectVpn(in ParcelFileDescriptor socket);
 
     boolean prepareVpn(String oldPackage, String newPackage);
 
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index 4436e6e..a97f203 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -52,4 +52,14 @@
      * @param iface The interface.
      */
     void interfaceRemoved(String iface);
+
+    /**
+     * A networking quota limit has been reached. The quota might not
+     * be specific to an interface.
+     *
+     * @param limitName The name of the limit that triggered.
+     * @param iface The interface on which the limit was detected.
+     */
+    void limitReached(String limitName, String iface);
+
 }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 82495e3..3e07b0a 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -18,6 +18,7 @@
 
 import android.net.INetworkPolicyListener;
 import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
 
 /**
  * Interface that creates and modifies network policy rules.
@@ -37,4 +38,9 @@
     void setNetworkPolicies(in NetworkPolicy[] policies);
     NetworkPolicy[] getNetworkPolicies();
 
+    void snoozePolicy(in NetworkTemplate template);
+
+    void setRestrictBackground(boolean restrictBackground);
+    boolean getRestrictBackground();
+
 }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 19894a0..132f3ba 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -52,11 +52,26 @@
 public class LinkProperties implements Parcelable {
 
     String mIfaceName;
-    private Collection<LinkAddress> mLinkAddresses;
-    private Collection<InetAddress> mDnses;
-    private Collection<RouteInfo> mRoutes;
+    private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
+    private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
+    private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
     private ProxyProperties mHttpProxy;
 
+    public static class CompareResult<T> {
+        public Collection<T> removed = new ArrayList<T>();
+        public Collection<T> added = new ArrayList<T>();
+
+        @Override
+        public String toString() {
+            String retVal = "removed=[";
+            for (T addr : removed) retVal += addr.toString() + ",";
+            retVal += "] added=[";
+            for (T addr : added) retVal += addr.toString() + ",";
+            retVal += "]";
+            return retVal;
+        }
+    }
+
     public LinkProperties() {
         clear();
     }
@@ -121,9 +136,9 @@
 
     public void clear() {
         mIfaceName = null;
-        mLinkAddresses = new ArrayList<LinkAddress>();
-        mDnses = new ArrayList<InetAddress>();
-        mRoutes = new ArrayList<RouteInfo>();
+        mLinkAddresses.clear();
+        mDnses.clear();
+        mRoutes.clear();
         mHttpProxy = null;
     }
 
@@ -155,6 +170,63 @@
         return ifaceName + linkAddresses + routes + dns + proxy;
     }
 
+    /**
+     * Compares this {@code LinkProperties} interface name against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalInterfaceName(LinkProperties target) {
+        return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
+    }
+
+    /**
+     * Compares this {@code LinkProperties} interface name against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalAddresses(LinkProperties target) {
+        Collection<InetAddress> targetAddresses = target.getAddresses();
+        Collection<InetAddress> sourceAddresses = getAddresses();
+        return (sourceAddresses.size() == targetAddresses.size()) ?
+                    sourceAddresses.containsAll(targetAddresses) : false;
+    }
+
+    /**
+     * Compares this {@code LinkProperties} DNS addresses against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalDnses(LinkProperties target) {
+        Collection<InetAddress> targetDnses = target.getDnses();
+        return (mDnses.size() == targetDnses.size()) ?
+                    mDnses.containsAll(targetDnses) : false;
+    }
+
+    /**
+     * Compares this {@code LinkProperties} Routes against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalRoutes(LinkProperties target) {
+        Collection<RouteInfo> targetRoutes = target.getRoutes();
+        return (mRoutes.size() == targetRoutes.size()) ?
+                    mRoutes.containsAll(targetRoutes) : false;
+    }
+
+    /**
+     * Compares this {@code LinkProperties} HttpProxy against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalHttpProxy(LinkProperties target) {
+        return getHttpProxy() == null ? target.getHttpProxy() == null :
+                    getHttpProxy().equals(target.getHttpProxy());
+    }
 
     @Override
     /**
@@ -176,32 +248,107 @@
 
         if (!(obj instanceof LinkProperties)) return false;
 
-        boolean sameAddresses;
-        boolean sameDnses;
-        boolean sameRoutes;
-
         LinkProperties target = (LinkProperties) obj;
 
-        Collection<InetAddress> targetAddresses = target.getAddresses();
-        Collection<InetAddress> sourceAddresses = getAddresses();
-        sameAddresses = (sourceAddresses.size() == targetAddresses.size()) ?
-                sourceAddresses.containsAll(targetAddresses) : false;
-
-        Collection<InetAddress> targetDnses = target.getDnses();
-        sameDnses = (mDnses.size() == targetDnses.size()) ?
-                mDnses.containsAll(targetDnses) : false;
-
-        Collection<RouteInfo> targetRoutes = target.getRoutes();
-        sameRoutes = (mRoutes.size() == targetRoutes.size()) ?
-                mRoutes.containsAll(targetRoutes) : false;
-
-        return
-            sameAddresses && sameDnses && sameRoutes
-            && TextUtils.equals(getInterfaceName(), target.getInterfaceName())
-            && (getHttpProxy() == null ? target.getHttpProxy() == null :
-                getHttpProxy().equals(target.getHttpProxy()));
+        return isIdenticalInterfaceName(target) &&
+                isIdenticalAddresses(target) &&
+                isIdenticalDnses(target) &&
+                isIdenticalRoutes(target) &&
+                isIdenticalHttpProxy(target);
     }
 
+    /**
+     * Return two lists, a list of addresses that would be removed from
+     * mLinkAddresses and a list of addresses that would be added to
+     * mLinkAddress which would then result in target and mLinkAddresses
+     * being the same list.
+     *
+     * @param target is a LinkProperties with the new list of addresses
+     * @return the removed and added lists.
+     */
+    public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
+        /*
+         * Duplicate the LinkAddresses into removed, we will be removing
+         * address which are common between mLinkAddresses and target
+         * leaving the addresses that are different. And address which
+         * are in target but not in mLinkAddresses are placed in the
+         * addedAddresses.
+         */
+        CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
+        result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
+        result.added.clear();
+        if (target != null) {
+            for (LinkAddress newAddress : target.getLinkAddresses()) {
+                if (! result.removed.remove(newAddress)) {
+                    result.added.add(newAddress);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Return two lists, a list of dns addresses that would be removed from
+     * mDnses and a list of addresses that would be added to
+     * mDnses which would then result in target and mDnses
+     * being the same list.
+     *
+     * @param target is a LinkProperties with the new list of dns addresses
+     * @return the removed and added lists.
+     */
+    public CompareResult<InetAddress> compareDnses(LinkProperties target) {
+        /*
+         * Duplicate the InetAddresses into removed, we will be removing
+         * dns address which are common between mDnses and target
+         * leaving the addresses that are different. And dns address which
+         * are in target but not in mDnses are placed in the
+         * addedAddresses.
+         */
+        CompareResult<InetAddress> result = new CompareResult<InetAddress>();
+
+        result.removed = new ArrayList<InetAddress>(mDnses);
+        result.added.clear();
+        if (target != null) {
+            for (InetAddress newAddress : target.getDnses()) {
+                if (! result.removed.remove(newAddress)) {
+                    result.added.add(newAddress);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Return two lists, a list of routes that would be removed from
+     * mRoutes and a list of routes that would be added to
+     * mRoutes which would then result in target and mRoutes
+     * being the same list.
+     *
+     * @param target is a LinkProperties with the new list of routes
+     * @return the removed and added lists.
+     */
+    public CompareResult<RouteInfo> compareRoutes(LinkProperties target) {
+        /*
+         * Duplicate the RouteInfos into removed, we will be removing
+         * routes which are common between mDnses and target
+         * leaving the routes that are different. And route address which
+         * are in target but not in mRoutes are placed in added.
+         */
+        CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
+
+        result.removed = new ArrayList<RouteInfo>(mRoutes);
+        result.added.clear();
+        if (target != null) {
+            for (RouteInfo r : target.getRoutes()) {
+                if (! result.removed.remove(r)) {
+                    result.added.add(r);
+                }
+            }
+        }
+        return result;
+    }
+
+
     @Override
     /**
      * generate hashcode based on significant fields
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index ccef122..aa6400bb 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -19,6 +19,7 @@
 import static android.net.ConnectivityManager.isNetworkTypeMobile;
 
 import android.content.Context;
+import android.os.Build;
 import android.telephony.TelephonyManager;
 
 import com.android.internal.util.Objects;
@@ -68,7 +69,7 @@
             subTypeName = Integer.toString(mSubType);
         }
 
-        final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
+        final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
         final String roaming = mRoaming ? ", ROAMING" : "";
         return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
                 + scrubSubscriberId + roaming + "]";
@@ -91,6 +92,17 @@
     }
 
     /**
+     * Scrub given IMSI on production builds.
+     */
+    public static String scrubSubscriberId(String subscriberId) {
+        if ("eng".equals(Build.TYPE)) {
+            return subscriberId;
+        } else {
+            return subscriberId != null ? "valid" : "null";
+        }
+    }
+
+    /**
      * Build a {@link NetworkIdentity} from the given {@link NetworkState},
      * assuming that any mobile networks are using the current IMSI.
      */
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 52cab30..aaad8a1 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -21,6 +21,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Objects;
+
 /**
  * Policy for networks matching a {@link NetworkTemplate}, including usage cycle
  * and limits to be enforced.
@@ -30,20 +32,21 @@
 public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     public static final long WARNING_DISABLED = -1;
     public static final long LIMIT_DISABLED = -1;
+    public static final long SNOOZE_NEVER = -1;
 
     public final NetworkTemplate template;
     public int cycleDay;
     public long warningBytes;
     public long limitBytes;
+    public long lastSnooze;
 
-    // TODO: teach how to snooze limit for current cycle
-
-    public NetworkPolicy(
-            NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes) {
+    public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes,
+            long lastSnooze) {
         this.template = checkNotNull(template, "missing NetworkTemplate");
         this.cycleDay = cycleDay;
         this.warningBytes = warningBytes;
         this.limitBytes = limitBytes;
+        this.lastSnooze = lastSnooze;
     }
 
     public NetworkPolicy(Parcel in) {
@@ -51,6 +54,7 @@
         cycleDay = in.readInt();
         warningBytes = in.readLong();
         limitBytes = in.readLong();
+        lastSnooze = in.readLong();
     }
 
     /** {@inheritDoc} */
@@ -59,6 +63,7 @@
         dest.writeInt(cycleDay);
         dest.writeLong(warningBytes);
         dest.writeLong(limitBytes);
+        dest.writeLong(lastSnooze);
     }
 
     /** {@inheritDoc} */
@@ -80,9 +85,25 @@
     }
 
     @Override
+    public int hashCode() {
+        return Objects.hashCode(template, cycleDay, warningBytes, limitBytes, lastSnooze);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NetworkPolicy) {
+            final NetworkPolicy other = (NetworkPolicy) obj;
+            return Objects.equal(template, other.template) && cycleDay == other.cycleDay
+                    && warningBytes == other.warningBytes && limitBytes == other.limitBytes
+                    && lastSnooze == other.lastSnooze;
+        }
+        return false;
+    }
+
+    @Override
     public String toString() {
         return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes="
-                + warningBytes + ", limitBytes=" + limitBytes;
+                + warningBytes + ", limitBytes=" + limitBytes + ", lastSnooze=" + lastSnooze;
     }
 
     public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 593b2b7..1e9d813 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -52,26 +52,10 @@
     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
 
     /**
-     * {@link Intent} action launched when user selects {@link NetworkPolicy}
-     * warning notification.
+     * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
+     * applies to.
      */
-    public static final String ACTION_DATA_USAGE_WARNING =
-            "android.intent.action.DATA_USAGE_WARNING";
-
-    /**
-     * {@link Intent} action launched when user selects {@link NetworkPolicy}
-     * limit notification.
-     */
-    public static final String ACTION_DATA_USAGE_LIMIT =
-            "android.intent.action.DATA_USAGE_LIMIT";
-
-    /**
-     * {@link Intent} extra included in {@link #ACTION_DATA_USAGE_WARNING} and
-     * {@link #ACTION_DATA_USAGE_LIMIT} to indicate which
-     * {@link NetworkTemplate} rule it applies to.
-     */
-    public static final String EXTRA_NETWORK_TEMPLATE =
-            "android.intent.extra.NETWORK_TEMPLATE";
+    public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
 
     private INetworkPolicyManager mService;
 
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 9381f1d..cd49023 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -16,9 +16,11 @@
 
 package android.net;
 
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
 import static android.net.ConnectivityManager.isNetworkTypeMobile;
+import static android.net.NetworkIdentity.scrubSubscriberId;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
@@ -38,41 +40,69 @@
  */
 public class NetworkTemplate implements Parcelable {
 
+    /** {@hide} */
+    public static final int MATCH_MOBILE_ALL = 1;
+    /** {@hide} */
+    public static final int MATCH_MOBILE_3G_LOWER = 2;
+    /** {@hide} */
+    public static final int MATCH_MOBILE_4G = 3;
+    /** {@hide} */
+    public static final int MATCH_WIFI = 4;
+    /** {@hide} */
+    public static final int MATCH_ETHERNET = 5;
+
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
      * networks together. Only uses statistics for requested IMSI.
      */
-    public static final int MATCH_MOBILE_ALL = 1;
+    public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
+        return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
+    }
 
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
      * networks together that roughly meet a "3G" definition, or lower. Only
      * uses statistics for requested IMSI.
      */
-    public static final int MATCH_MOBILE_3G_LOWER = 2;
+    public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
+        return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId);
+    }
 
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
      * networks together that meet a "4G" definition. Only uses statistics for
      * requested IMSI.
      */
-    public static final int MATCH_MOBILE_4G = 3;
+    public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
+        return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId);
+    }
 
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
      * networks together.
      */
-    public static final int MATCH_WIFI = 4;
+    public static NetworkTemplate buildTemplateWifi() {
+        return new NetworkTemplate(MATCH_WIFI, null);
+    }
 
-    final int mMatchRule;
-    final String mSubscriberId;
+    /**
+     * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
+     * networks together.
+     */
+    public static NetworkTemplate buildTemplateEthernet() {
+        return new NetworkTemplate(MATCH_ETHERNET, null);
+    }
 
+    private final int mMatchRule;
+    private final String mSubscriberId;
+
+    /** {@hide} */
     public NetworkTemplate(int matchRule, String subscriberId) {
         this.mMatchRule = matchRule;
         this.mSubscriberId = subscriberId;
     }
 
-    public NetworkTemplate(Parcel in) {
+    private NetworkTemplate(Parcel in) {
         mMatchRule = in.readInt();
         mSubscriberId = in.readString();
     }
@@ -90,7 +120,7 @@
 
     @Override
     public String toString() {
-        final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
+        final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
         return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId="
                 + scrubSubscriberId;
     }
@@ -110,16 +140,18 @@
         return false;
     }
 
+    /** {@hide} */
     public int getMatchRule() {
         return mMatchRule;
     }
 
+    /** {@hide} */
     public String getSubscriberId() {
         return mSubscriberId;
     }
 
     /**
-     * Test if this network matches the given template and IMEI.
+     * Test if this network matches the given template and IMSI.
      */
     public boolean matches(NetworkIdentity ident) {
         switch (mMatchRule) {
@@ -131,13 +163,15 @@
                 return matchesMobile4g(ident);
             case MATCH_WIFI:
                 return matchesWifi(ident);
+            case MATCH_ETHERNET:
+                return matchesEthernet(ident);
             default:
                 throw new IllegalArgumentException("unknown network template");
         }
     }
 
     /**
-     * Check if mobile network with matching IMEI. Also matches
+     * Check if mobile network with matching IMSI. Also matches
      * {@link #TYPE_WIMAX}.
      */
     private boolean matchesMobile(NetworkIdentity ident) {
@@ -150,7 +184,7 @@
     }
 
     /**
-     * Check if mobile network classified 3G or lower with matching IMEI.
+     * Check if mobile network classified 3G or lower with matching IMSI.
      */
     private boolean matchesMobile3gLower(NetworkIdentity ident) {
         if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
@@ -165,7 +199,7 @@
     }
 
     /**
-     * Check if mobile network classified 4G with matching IMEI. Also matches
+     * Check if mobile network classified 4G with matching IMSI. Also matches
      * {@link #TYPE_WIMAX}.
      */
     private boolean matchesMobile4g(NetworkIdentity ident) {
@@ -190,7 +224,17 @@
         return false;
     }
 
-    public static String getMatchRuleName(int matchRule) {
+    /**
+     * Check if matches Ethernet network template.
+     */
+    private boolean matchesEthernet(NetworkIdentity ident) {
+        if (ident.mType == TYPE_ETHERNET) {
+            return true;
+        }
+        return false;
+    }
+
+    private static String getMatchRuleName(int matchRule) {
         switch (matchRule) {
             case MATCH_MOBILE_3G_LOWER:
                 return "MOBILE_3G_LOWER";
@@ -200,6 +244,8 @@
                 return "MOBILE_ALL";
             case MATCH_WIFI:
                 return "WIFI";
+            case MATCH_ETHERNET:
+                return "ETHERNET";
             default:
                 return "UNKNOWN";
         }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 76534ef..e289fc1 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -20,6 +20,7 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.UnknownHostException;
+import java.util.Collection;
 
 import android.util.Log;
 
@@ -235,4 +236,18 @@
             throw new IllegalArgumentException(e);
         }
     }
+
+    /**
+     * Create a string array of host addresses from a collection of InetAddresses
+     * @param addrs a Collection of InetAddresses
+     * @return an array of Strings containing their host addresses
+     */
+    public static String[] makeStrings(Collection<InetAddress> addrs) {
+        String[] result = new String[addrs.size()];
+        int i = 0;
+        for (InetAddress addr : addrs) {
+            result[i++] = addr.getHostAddress();
+        }
+        return result;
+    }
 }
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 8e5ddda..275f32a 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -43,6 +43,7 @@
     private final InetAddress mGateway;
 
     private final boolean mIsDefault;
+    private final boolean mIsHost;
 
     public RouteInfo(LinkAddress destination, InetAddress gateway) {
         if (destination == null) {
@@ -68,6 +69,7 @@
                 destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
         mGateway = gateway;
         mIsDefault = isDefault();
+        mIsHost = isHost();
     }
 
     public RouteInfo(InetAddress gateway) {
@@ -88,6 +90,10 @@
         }
     }
 
+    private boolean isHost() {
+        return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY));
+    }
+
     private boolean isDefault() {
         boolean val = false;
         if (mGateway != null) {
@@ -100,6 +106,7 @@
         return val;
     }
 
+
     public LinkAddress getDestination() {
         return mDestination;
     }
@@ -112,6 +119,10 @@
         return mIsDefault;
     }
 
+    public boolean isHostRoute() {
+        return mIsHost;
+    }
+
     public String toString() {
         String val = "";
         if (mDestination != null) val = mDestination.toString();
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 2b59dba..e054930 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -97,6 +97,15 @@
     }
 
     /**
+     * Get the active tag used when accounting {@link Socket} traffic originating
+     * from the current thread. Only one active tag per thread is supported.
+     * {@link #tagSocket(Socket)}.
+     */
+    public static int getThreadStatsTag() {
+        return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+    }
+
+    /**
      * @deprecated unsupported, will eventually be removed
      */
     @Deprecated
diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java
new file mode 100644
index 0000000..25cedb6
--- /dev/null
+++ b/core/java/android/net/VpnBuilder.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.net.VpnConfig;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.DatagramSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+
+/**
+ * VpnBuilder is a framework which enables applications to build their
+ * own VPN solutions. In general, it creates a virtual network interface,
+ * configures addresses and routing rules, and returns a file descriptor
+ * to the application. Each read from the descriptor retrieves an outgoing
+ * packet which was routed to the interface. Each write to the descriptor
+ * injects an incoming packet just like it was received from the interface.
+ * The framework is running on Internet Protocol (IP), so packets are
+ * always started with IP headers. The application then completes a VPN
+ * connection by processing and exchanging packets with a remote server
+ * over a secured tunnel.
+ *
+ * <p>Letting applications intercept packets raises huge security concerns.
+ * Besides, a VPN application can easily break the network, and two of them
+ * may conflict with each other. The framework takes several actions to
+ * address these issues. Here are some key points:
+ * <ul>
+ *   <li>User action is required to create a VPN connection.</li>
+ *   <li>There can be only one VPN connection running at the same time. The
+ *       existing interface is deactivated when a new one is created.</li>
+ *   <li>A system-managed notification is shown during the lifetime of a
+ *       VPN connection.</li>
+ *   <li>A system-managed dialog gives the information of the current VPN
+ *       connection. It also provides a button to disconnect.</li>
+ *   <li>The network is restored automatically when the file descriptor is
+ *       closed. It also covers the cases when a VPN application is crashed
+ *       or killed by the system.</li>
+ * </ul>
+ *
+ * <p>There are two primary methods in this class: {@link #prepare} and
+ * {@link #establish}. The former deals with the user action and stops
+ * the existing VPN connection created by another application. The latter
+ * creates a VPN interface using the parameters supplied to this builder.
+ * An application must call {@link #prepare} to grant the right to create
+ * an interface, and it can be revoked at any time by another application.
+ * The application got revoked is notified by an {@link #ACTION_VPN_REVOKED}
+ * broadcast. Here are the general steps to create a VPN connection:
+ * <ol>
+ *   <li>When the user press the button to connect, call {@link #prepare}
+ *       and launch the intent if necessary.</li>
+ *   <li>Register a receiver for {@link #ACTION_VPN_REVOKED} broadcasts.
+ *   <li>Connect to the remote server and negotiate the network parameters
+ *       of the VPN connection.</li>
+ *   <li>Use those parameters to configure a VpnBuilder and create a VPN
+ *       interface by calling {@link #establish}.</li>
+ *   <li>Start processing packets between the returned file descriptor and
+ *       the VPN tunnel.</li>
+ *   <li>When an {@link #ACTION_VPN_REVOKED} broadcast is received, the
+ *       interface is already deactivated by the framework. Close the file
+ *       descriptor and shut down the VPN tunnel gracefully.
+ * </ol>
+ * Methods in this class can be used in activities and services. However,
+ * the intent returned from {@link #prepare} must be launched from an
+ * activity. The broadcast receiver can be registered at any time, but doing
+ * it before calling {@link #establish} effectively avoids race conditions.
+ *
+ * <p class="note">Using this class requires
+ * {@link android.Manifest.permission#VPN} permission.
+ */
+public class VpnBuilder {
+
+    /**
+     * Broadcast intent action indicating that the VPN application has been
+     * revoked. This can be only received by the target application on the
+     * receiver explicitly registered using {@link Context#registerReceiver}.
+     *
+     * <p>This is a protected intent that can only be sent by the system.
+     */
+    public static final String ACTION_VPN_REVOKED = VpnConfig.ACTION_VPN_REVOKED;
+
+    /**
+     * Use IConnectivityManager instead since those methods are hidden and
+     * not available in ConnectivityManager.
+     */
+    private static IConnectivityManager getService() {
+        return IConnectivityManager.Stub.asInterface(
+                ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+    }
+
+    /**
+     * Prepare to establish a VPN connection. This method returns {@code null}
+     * if the VPN application is already prepared. Otherwise, it returns an
+     * {@link Intent} to a system activity. The application should launch the
+     * activity using {@link Activity#startActivityForResult} to get itself
+     * prepared. The activity may pop up a dialog to require user action, and
+     * the result will come back to the application through its
+     * {@link Activity#onActivityResult}. The application becomes prepared if
+     * the result is {@link Activity#RESULT_OK}, and it is granted to create a
+     * VPN interface by calling {@link #establish}.
+     *
+     * <p>Only one application can be granted at the same time. The right
+     * is revoked when another application is granted. The application
+     * losing the right will be notified by an {@link #ACTION_VPN_REVOKED}
+     * broadcast, and its VPN interface will be deactivated by the system.
+     * The application should then notify the remote server and disconnect
+     * gracefully. Unless the application becomes prepared again, subsequent
+     * calls to {@link #establish} will return {@code null}.
+     *
+     * @see #establish
+     * @see #ACTION_VPN_REVOKED
+     */
+    public static Intent prepare(Context context) {
+        try {
+            if (getService().prepareVpn(context.getPackageName(), null)) {
+                return null;
+            }
+        } catch (RemoteException e) {
+            // ignore
+        }
+        return VpnConfig.getIntentForConfirmation();
+    }
+
+    private VpnConfig mConfig = new VpnConfig();
+    private StringBuilder mAddresses = new StringBuilder();
+    private StringBuilder mRoutes = new StringBuilder();
+
+    /**
+     * Set the name of this session. It will be displayed in system-managed
+     * dialogs and notifications. This is recommended not required.
+     */
+    public VpnBuilder setSession(String session) {
+        mConfig.session = session;
+        return this;
+    }
+
+    /**
+     * Set the {@link PendingIntent} to an activity for users to configure
+     * the VPN connection. If it is not set, the button to configure will
+     * not be shown in system-managed dialogs.
+     */
+    public VpnBuilder setConfigureIntent(PendingIntent intent) {
+        mConfig.configureIntent = intent;
+        return this;
+    }
+
+    /**
+     * Set the maximum transmission unit (MTU) of the VPN interface. If it
+     * is not set, the default value in the operating system will be used.
+     *
+     * @throws IllegalArgumentException if the value is not positive.
+     */
+    public VpnBuilder setMtu(int mtu) {
+        if (mtu <= 0) {
+            throw new IllegalArgumentException("Bad mtu");
+        }
+        mConfig.mtu = mtu;
+        return this;
+    }
+
+    /**
+     * Private method to validate address and prefixLength.
+     */
+    private static void check(InetAddress address, int prefixLength) {
+        if (address.isLoopbackAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+        if (address instanceof Inet4Address) {
+            if (prefixLength < 0 || prefixLength > 32) {
+                throw new IllegalArgumentException("Bad prefixLength");
+            }
+        } else if (address instanceof Inet6Address) {
+            if (prefixLength < 0 || prefixLength > 128) {
+                throw new IllegalArgumentException("Bad prefixLength");
+            }
+        } else {
+            throw new IllegalArgumentException("Unsupported family");
+        }
+    }
+
+    /**
+     * Convenience method to add a network address to the VPN interface
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     * @see #addAddress(InetAddress, int)
+     */
+    public VpnBuilder addAddress(String address, int prefixLength) {
+        return addAddress(InetAddress.parseNumericAddress(address), prefixLength);
+    }
+
+    /**
+     * Add a network address to the VPN interface. Both IPv4 and IPv6
+     * addresses are supported. At least one address must be set before
+     * calling {@link #establish}.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     */
+    public VpnBuilder addAddress(InetAddress address, int prefixLength) {
+        check(address, prefixLength);
+
+        if (address.isAnyLocalAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+
+        mAddresses.append(String.format(" %s/%d", address.getHostAddress(), prefixLength));
+        return this;
+    }
+
+    /**
+     * Convenience method to add a network route to the VPN interface
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @see #addRoute(InetAddress, int)
+     * @throws IllegalArgumentException if the route is invalid.
+     */
+    public VpnBuilder addRoute(String address, int prefixLength) {
+        return addRoute(InetAddress.parseNumericAddress(address), prefixLength);
+    }
+
+    /**
+     * Add a network route to the VPN interface. Both IPv4 and IPv6
+     * routes are supported.
+     *
+     * @throws IllegalArgumentException if the route is invalid.
+     */
+    public VpnBuilder addRoute(InetAddress address, int prefixLength) {
+        check(address, prefixLength);
+
+        int offset = prefixLength / 8;
+        byte[] bytes = address.getAddress();
+        if (offset < bytes.length) {
+            if ((byte)(bytes[offset] << (prefixLength % 8)) != 0) {
+                throw new IllegalArgumentException("Bad address");
+            }
+            while (++offset < bytes.length) {
+                if (bytes[offset] != 0) {
+                    throw new IllegalArgumentException("Bad address");
+                }
+            }
+        }
+
+        mRoutes.append(String.format(" %s/%d", address.getHostAddress(), prefixLength));
+        return this;
+    }
+
+    /**
+     * Convenience method to add a DNS server to the VPN connection
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     * @see #addDnsServer(InetAddress)
+     */
+    public VpnBuilder addDnsServer(String address) {
+        return addDnsServer(InetAddress.parseNumericAddress(address));
+    }
+
+    /**
+     * Add a DNS server to the VPN connection. Both IPv4 and IPv6
+     * addresses are supported. If none is set, the DNS servers of
+     * the default network will be used.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     */
+    public VpnBuilder addDnsServer(InetAddress address) {
+        if (address.isLoopbackAddress() || address.isAnyLocalAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+        if (mConfig.dnsServers == null) {
+            mConfig.dnsServers = new ArrayList<String>();
+        }
+        mConfig.dnsServers.add(address.getHostAddress());
+        return this;
+    }
+
+    /**
+     * Add a search domain to the DNS resolver.
+     */
+    public VpnBuilder addSearchDomain(String domain) {
+        if (mConfig.searchDomains == null) {
+            mConfig.searchDomains = new ArrayList<String>();
+        }
+        mConfig.searchDomains.add(domain);
+        return this;
+    }
+
+    /**
+     * Create a VPN interface using the parameters supplied to this builder.
+     * The interface works on IP packets, and a file descriptor is returned
+     * for the application to access them. Each read retrieves an outgoing
+     * packet which was routed to the interface. Each write injects an
+     * incoming packet just like it was received from the interface. The file
+     * descriptor is put into non-blocking mode by default to avoid blocking
+     * Java threads. To use the file descriptor completely in native space,
+     * see {@link ParcelFileDescriptor#detachFd()}. The application MUST
+     * close the file descriptor when the VPN connection is terminated. The
+     * VPN interface will be removed and the network will be restored by the
+     * framework automatically.
+     *
+     * <p>To avoid conflicts, there can be only one active VPN interface at
+     * the same time. Usually network parameters are never changed during the
+     * lifetime of a VPN connection. It is also common for an application to
+     * create a new file descriptor after closing the previous one. However,
+     * it is rare but not impossible to have two interfaces while performing a
+     * seamless handover. In this case, the old interface will be deactivated
+     * when the new one is configured successfully. Both file descriptors are
+     * valid but now outgoing packets will be routed to the new interface.
+     * Therefore, after draining the old file descriptor, the application MUST
+     * close it and start using the new file descriptor. If the new interface
+     * cannot be created, the existing interface and its file descriptor remain
+     * untouched.
+     *
+     * <p>An exception will be thrown if the interface cannot be created for
+     * any reason. However, this method returns {@code null} if the application
+     * is not prepared or is revoked by another application. This helps solve
+     * possible race conditions while handling {@link #ACTION_VPN_REVOKED}
+     * broadcasts.
+     *
+     * @return {@link ParcelFileDescriptor} of the VPN interface, or
+     *         {@code null} if the application is not prepared.
+     * @throws IllegalArgumentException if a parameter is not accepted by the
+     *         operating system.
+     * @throws IllegalStateException if a parameter cannot be applied by the
+     *         operating system.
+     * @see #prepare
+     */
+    public ParcelFileDescriptor establish() {
+        mConfig.addresses = mAddresses.toString();
+        mConfig.routes = mRoutes.toString();
+
+        try {
+            return getService().establishVpn(mConfig);
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Protect a socket from VPN connections. The socket will be bound to the
+     * current default network interface, so its traffic will not be forwarded
+     * through VPN. This method is useful if some connections need to be kept
+     * outside of VPN. For example, a VPN tunnel should protect itself if its
+     * destination is covered by VPN routes. Otherwise its outgoing packets
+     * will be sent back to the VPN interface and cause an infinite loop.
+     *
+     * <p>The socket is NOT closed by this method.
+     *
+     * @return {@code true} on success.
+     */
+    public static boolean protect(int socket) {
+        ParcelFileDescriptor dup = null;
+        try {
+            dup = ParcelFileDescriptor.fromFd(socket);
+            return getService().protectVpn(dup);
+        } catch (Exception e) {
+            return false;
+        } finally {
+            try {
+                dup.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Protect a {@link Socket} from VPN connections.
+     *
+     * @return {@code true} on success.
+     * @see #protect(int)
+     */
+    public static boolean protect(Socket socket) {
+        return protect(socket.getFileDescriptor$().getInt$());
+    }
+
+    /**
+     * Protect a {@link DatagramSocket} from VPN connections.
+     *
+     * @return {@code true} on success.
+     * @see #protect(int)
+     */
+    public static boolean protect(DatagramSocket socket) {
+        return protect(socket.getFileDescriptor$().getInt$());
+    }
+}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index dcbe9da..2ed6619 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -46,8 +46,6 @@
 
     // NfcAdapter-class related methods
     boolean isEnabled();
-    NdefMessage localGet();
-    void localSet(in NdefMessage message);
     void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent,
             in IntentFilter[] filters, in TechListParcel techLists);
     void disableForegroundDispatch(in ComponentName activity);
@@ -62,4 +60,7 @@
     int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength);
     boolean disable();
     boolean enable();
+    boolean enableZeroClick();
+    boolean disableZeroClick();
+    boolean zeroClickEnabled();
 }
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index aa5937e..7bdefe7 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -44,5 +44,6 @@
     Tag rediscover(int nativehandle);
 
     int setTimeout(int technology, int timeout);
+    int getTimeout(int technology);
     void resetTimeouts();
 }
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 0eb8cd8..b668f30 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -334,8 +334,6 @@
 
     /**
      * Creates an NDEF record of well known type URI.
-     * TODO: Make a public API
-     * @hide
      */
     public static NdefRecord createUri(Uri uri) {
         return createUri(uri.toString());
@@ -343,8 +341,6 @@
 
     /**
      * Creates an NDEF record of well known type URI.
-     * TODO: Make a public API
-     * @hide
      */
     public static NdefRecord createUri(String uriString) {
         byte prefix = 0x0;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 738e75f..4d04027 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -684,44 +684,45 @@
     }
 
     /**
-     * Set the NDEF Message that this NFC adapter should appear as to Tag
-     * readers.
-     * <p>
-     * Any Tag reader can read the contents of the local tag when it is in
-     * proximity, without any further user confirmation.
-     * <p>
-     * The implementation of this method must either
-     * <ul>
-     * <li>act as a passive tag containing this NDEF message
-     * <li>provide the NDEF message on over LLCP to peer NFC adapters
-     * </ul>
-     * The NDEF message is preserved across reboot.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * Enable zero-click sharing.
      *
-     * @param message NDEF message to make public
      * @hide
      */
-    public void setLocalNdefMessage(NdefMessage message) {
+    public boolean enableZeroClick() {
         try {
-            sService.localSet(message);
+            return sService.enableZeroClick();
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
+            return false;
         }
     }
 
     /**
-     * Get the NDEF Message that this adapter appears as to Tag readers.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * Disable zero-click sharing.
      *
-     * @return NDEF Message that is publicly readable
      * @hide
      */
-    public NdefMessage getLocalNdefMessage() {
+    public boolean disableZeroClick() {
         try {
-            return sService.localGet();
+            return sService.disableZeroClick();
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
-            return null;
+            return false;
+        }
+    }
+
+    /**
+     * Return true if zero-click sharing is enabled.
+     *
+     * @return true if zero-click sharing is enabled
+     * @hide
+     */
+    public boolean zeroClickEnabled() {
+        try {
+            return sService.zeroClickEnabled();
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return false;
         }
     }
 
diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
index d02086f..0672a4e 100644
--- a/core/java/android/nfc/tech/IsoDep.java
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -101,6 +101,24 @@
     }
 
     /**
+     * Gets the currently set timeout of {@link #transceive} in milliseconds.
+     *
+     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+     *
+     * @return timeout value in milliseconds
+     * @hide
+     */
+    // TODO Unhide for ICS
+    public int getTimeout() {
+        try {
+            return mTag.getTagService().getTimeout(TagTechnology.ISO_DEP);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return 0;
+        }
+    }
+
+    /**
      * Return the ISO-DEP historical bytes for {@link NfcA} tags.
      * <p>Does not cause any RF activity and does not block.
      * <p>The historical bytes can be used to help identify a tag. They are present
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
index 5cafe5b..93e7cbd 100644
--- a/core/java/android/nfc/tech/MifareClassic.java
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -597,6 +597,24 @@
         }
     }
 
+    /**
+     * Gets the currently set timeout of {@link #transceive} in milliseconds.
+     *
+     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+     *
+     * @return timeout value in milliseconds
+     * @hide
+     */
+    // TODO Unhide for ICS
+    public int getTimeout() {
+        try {
+            return mTag.getTagService().getTimeout(TagTechnology.MIFARE_CLASSIC);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return 0;
+        }
+    }
+
     private static void validateSector(int sector) {
         // Do not be too strict on upper bounds checking, since some cards
         // have more addressable memory than they report. For example,
diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java
index 3d4cdd1..ca74ebe 100644
--- a/core/java/android/nfc/tech/MifareUltralight.java
+++ b/core/java/android/nfc/tech/MifareUltralight.java
@@ -238,6 +238,24 @@
         }
     }
 
+    /**
+     * Gets the currently set timeout of {@link #transceive} in milliseconds.
+     *
+     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+     *
+     * @return timeout value in milliseconds
+     * @hide
+     */
+    // TODO Unhide for ICS
+    public int getTimeout() {
+        try {
+            return mTag.getTagService().getTimeout(TagTechnology.MIFARE_ULTRALIGHT);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return 0;
+        }
+    }
+
     private static void validatePageIndex(int pageIndex) {
         // Do not be too strict on upper bounds checking, since some cards
         // may have more addressable memory than they report.
diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java
index 08095e6..bd1f95a 100644
--- a/core/java/android/nfc/tech/NfcA.java
+++ b/core/java/android/nfc/tech/NfcA.java
@@ -141,4 +141,22 @@
             Log.e(TAG, "NFC service dead", e);
         }
     }
+
+    /**
+     * Gets the currently set timeout of {@link #transceive} in milliseconds.
+     *
+     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+     *
+     * @return timeout value in milliseconds
+     * @hide
+     */
+    // TODO Unhide for ICS
+    public int getTimeout() {
+        try {
+            return mTag.getTagService().getTimeout(TagTechnology.NFC_A);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return 0;
+        }
+    }
 }
diff --git a/core/java/android/nfc/tech/NfcF.java b/core/java/android/nfc/tech/NfcF.java
index 85abf89..7b25a72 100644
--- a/core/java/android/nfc/tech/NfcF.java
+++ b/core/java/android/nfc/tech/NfcF.java
@@ -140,4 +140,22 @@
             Log.e(TAG, "NFC service dead", e);
         }
     }
+
+    /**
+     * Gets the currently set timeout of {@link #transceive} in milliseconds.
+     *
+     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+     *
+     * @return timeout value in milliseconds
+     * @hide
+     */
+    // TODO Unhide for ICS
+    public int getTimeout() {
+        try {
+            return mTag.getTagService().getTimeout(TagTechnology.NFC_F);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return 0;
+        }
+    }
 }
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index ba69246..da2afb6 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -129,6 +129,11 @@
         /** The shared dirty pages used by everything else. */
         public int otherSharedDirty;
 
+        /** @hide */
+        public static final int NUM_OTHER_STATS = 9;
+
+        private int[] otherStats = new int[NUM_OTHER_STATS*3];
+
         public MemoryInfo() {
         }
 
@@ -153,6 +158,38 @@
             return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
         }
 
+        /* @hide */
+        public int getOtherPss(int which) {
+            return otherStats[which*3];
+        }
+
+        /* @hide */
+        public int getOtherPrivateDirty(int which) {
+            return otherStats[which*3 + 1];
+        }
+
+        /* @hide */
+        public int getOtherSharedDirty(int which) {
+            return otherStats[which*3 + 2];
+        }
+
+
+        /* @hide */
+        public static String getOtherLabel(int which) {
+            switch (which) {
+                case 0: return "Cursor";
+                case 1: return "Ashmem";
+                case 2: return "Other dev";
+                case 3: return ".so mmap";
+                case 4: return ".jar mmap";
+                case 5: return ".apk mmap";
+                case 6: return ".ttf mmap";
+                case 7: return ".dex mmap";
+                case 8: return "Other mmap";
+                default: return "????";
+            }
+        }
+
         public int describeContents() {
             return 0;
         }
@@ -167,6 +204,7 @@
             dest.writeInt(otherPss);
             dest.writeInt(otherPrivateDirty);
             dest.writeInt(otherSharedDirty);
+            dest.writeIntArray(otherStats);
         }
 
         public void readFromParcel(Parcel source) {
@@ -179,6 +217,7 @@
             otherPss = source.readInt();
             otherPrivateDirty = source.readInt();
             otherSharedDirty = source.readInt();
+            otherStats = source.createIntArray();
         }
 
         public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 165e438..bc37244 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -169,6 +169,21 @@
     }
 
     /**
+     * Returns a string representing the name of the specified message.
+     * The default implementation will either return the class name of the
+     * message callback if any, or the hexadecimal representation of the
+     * message "what" field.
+     *  
+     * @param message The message whose name is being queried 
+     */
+    public String getMessageName(Message message) {
+        if (message.callback != null) {
+            return message.callback.getClass().getName();
+        }
+        return "0x" + Integer.toHexString(message.what);
+    }
+
+    /**
      * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
      * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
      *  If you don't want that facility, just call Message.obtain() instead.
@@ -346,7 +361,8 @@
 
     /**
      * Remove any pending posts of Runnable <var>r</var> with Object
-     * <var>token</var> that are in the message queue.
+     * <var>token</var> that are in the message queue.  If <var>token</var> is null,
+     * all callbacks will be removed.
      */
     public final void removeCallbacks(Runnable r, Object token)
     {
@@ -502,7 +518,8 @@
 
     /**
      * Remove any pending posts of messages with code 'what' and whose obj is
-     * 'object' that are in the message queue.
+     * 'object' that are in the message queue.  If <var>token</var> is null,
+     * all messages will be removed.
      */
     public final void removeMessages(int what, Object object) {
         mQueue.removeMessages(this, what, object, true);
@@ -510,7 +527,8 @@
 
     /**
      * Remove any pending posts of callbacks and sent messages whose
-     * <var>obj</var> is <var>token</var>.
+     * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
+     * all callbacks and messages will be removed.
      */
     public final void removeCallbacksAndMessages(Object token) {
         mQueue.removeCallbacksAndMessages(this, token);
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index f230526..3704248 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -180,7 +180,7 @@
     /**
      * Stop Wifi Access Point
      */
-    void stopAccessPoint();
+    void stopAccessPoint(String wlanIface);
 
     /**
      * Set Access Point config
@@ -212,7 +212,7 @@
     /**
      * Set quota for an interface.
      */
-    void setInterfaceQuota(String iface, long quota);
+    void setInterfaceQuota(String iface, long quotaBytes);
 
     /**
      * Remove quota for an interface.
@@ -220,6 +220,21 @@
     void removeInterfaceQuota(String iface);
 
     /**
+     * Set alert for an interface; requires that iface already has quota.
+     */
+    void setInterfaceAlert(String iface, long alertBytes);
+
+    /**
+     * Remove alert for an interface.
+     */
+    void removeInterfaceAlert(String iface);
+
+    /**
+     * Set alert across all interfaces.
+     */
+    void setGlobalAlert(long alertBytes);
+
+    /**
      * Control network activity of a UID over interfaces with a quota limit.
      */
     void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
@@ -252,12 +267,12 @@
     void setDnsServersForInterface(String iface, in String[] servers);
 
     /**
-     * Flush the DNS cache associated with the default interface
+     * Flush the DNS cache associated with the default interface.
      */
     void flushDefaultDnsCache();
 
     /**
-     * Flush the DNS cache associated with the specified interface
+     * Flush the DNS cache associated with the specified interface.
      */
     void flushInterfaceDnsCache(String iface);
 }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 0067e940..9a53d76 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -20,12 +20,15 @@
 import android.os.WorkSource;
 
 /** @hide */
+
 interface IPowerManager
 {
+    // WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
     void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
     void goToSleep(long time);
     void goToSleepWithReason(long time, int reason);
+    // WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
     void releaseWakeLock(IBinder lock, int flags);
     void userActivity(long when, boolean noChangeLights);
     void userActivityWithForce(long when, boolean noChangeLights, boolean force);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index c0be664..c61f28a 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -52,7 +52,6 @@
   */
 public class Looper {
     private static final String TAG = "Looper";
-    private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
 
     // sThreadLocal.get() will return null unless you've called prepare().
     private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@@ -70,7 +69,7 @@
       * {@link #loop()} after calling this method, and end it by calling
       * {@link #quit()}.
       */
-    public static final void prepare() {
+    public static void prepare() {
         if (sThreadLocal.get() != null) {
             throw new RuntimeException("Only one Looper may be created per thread");
         }
@@ -83,7 +82,7 @@
      * is created by the Android environment, so you should never need
      * to call this function yourself.  See also: {@link #prepare()}
      */
-    public static final void prepareMainLooper() {
+    public static void prepareMainLooper() {
         prepare();
         setMainLooper(myLooper());
         myLooper().mQueue.mQuitAllowed = false;
@@ -95,7 +94,7 @@
 
     /** Returns the application's main looper, which lives in the main thread of the application.
      */
-    public synchronized static final Looper getMainLooper() {
+    public synchronized static Looper getMainLooper() {
         return mMainLooper;
     }
 
@@ -103,7 +102,7 @@
      * Run the message queue in this thread. Be sure to call
      * {@link #quit()} to end the loop.
      */
-    public static final void loop() {
+    public static void loop() {
         Looper me = myLooper();
         if (me == null) {
             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
@@ -122,20 +121,37 @@
                     // No target is a magic identifier for the quit message.
                     return;
                 }
-                if (me.mLogging != null) me.mLogging.println(
-                        ">>>>> Dispatching to " + msg.target + " "
-                        + msg.callback + ": " + msg.what
-                        );
+
+                long wallStart = 0;
+                long threadStart = 0;
+
+                // This must be in a local variable, in case a UI event sets the logger
+                Printer logging = me.mLogging;
+                if (logging != null) {
+                    logging.println(">>>>> Dispatching to " + msg.target + " " +
+                            msg.callback + ": " + msg.what);
+                    wallStart = SystemClock.currentTimeMicro();
+                    threadStart = SystemClock.currentThreadTimeMicro();
+                }
+
                 msg.target.dispatchMessage(msg);
-                if (me.mLogging != null) me.mLogging.println(
-                        "<<<<< Finished to    " + msg.target + " "
-                        + msg.callback);
-                
+
+                if (logging != null) {
+                    long wallTime = SystemClock.currentTimeMicro() - wallStart;
+                    long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
+
+                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
+                    if (logging instanceof Profiler) {
+                        ((Profiler) logging).profile(msg, wallStart, wallTime,
+                                threadStart, threadTime);
+                    }
+                }
+
                 // Make sure that during the course of dispatching the
                 // identity of the thread wasn't corrupted.
                 final long newIdent = Binder.clearCallingIdentity();
                 if (ident != newIdent) {
-                    Log.wtf("Looper", "Thread identity changed from 0x"
+                    Log.wtf(TAG, "Thread identity changed from 0x"
                             + Long.toHexString(ident) + " to 0x"
                             + Long.toHexString(newIdent) + " while dispatching to "
                             + msg.target.getClass().getName() + " "
@@ -151,7 +167,7 @@
      * Return the Looper object associated with the current thread.  Returns
      * null if the calling thread is not associated with a Looper.
      */
-    public static final Looper myLooper() {
+    public static Looper myLooper() {
         return sThreadLocal.get();
     }
 
@@ -173,7 +189,7 @@
      * thread.  This must be called from a thread running a Looper, or a
      * NullPointerException will be thrown.
      */
-    public static final MessageQueue myQueue() {
+    public static MessageQueue myQueue() {
         return myLooper().mQueue;
     }
 
@@ -225,23 +241,14 @@
     }
 
     public String toString() {
-        return "Looper{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + "}";
+        return "Looper{" + Integer.toHexString(System.identityHashCode(this)) + "}";
     }
 
-    static class HandlerException extends Exception {
-
-        HandlerException(Message message, Throwable cause) {
-            super(createMessage(cause), cause);
-        }
-
-        static String createMessage(Throwable cause) {
-            String causeMsg = cause.getMessage();
-            if (causeMsg == null) {
-                causeMsg = cause.toString();
-            }
-            return causeMsg;
-        }
+    /**
+     * @hide
+     */
+    public static interface Profiler {
+        void profile(Message message, long wallStart, long wallTime,
+                long threadStart, long threadTime);
     }
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5b1f563..3362575 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -86,6 +86,12 @@
     public static final int WIFI_UID = 1010;
 
     /**
+     * Defines the UID/GID for the mediaserver process.
+     * @hide
+     */
+    public static final int MEDIA_UID = 1013;
+
+    /**
      * Defines the GID for the group that allows write access to the SD card.
      * @hide
      */
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index ae605fb..73e8d98 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -357,20 +357,11 @@
     }
 
     /**
-     * Reboot into the recovery system to wipe the /data partition and toggle
-     * Encrypted File Systems on/off.
-     * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
+     * Reboot into the recovery system to wipe the /cache partition.
      * @throws IOException if something goes wrong.
-     *
-     * @hide
      */
-    public static void rebootToggleEFS(Context context, boolean efsEnabled)
-        throws IOException {
-        if (efsEnabled) {
-            bootCommand(context, "--set_encrypted_filesystem=on");
-        } else {
-            bootCommand(context, "--set_encrypted_filesystem=off");
-        }
+    public static void rebootWipeCache(Context context) throws IOException {
+        bootCommand(context, "--wipe_cache");
     }
 
     /**
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 2dd6749..7291739 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -157,4 +157,22 @@
      * @return elapsed milliseconds in the thread
      */
     public static native long currentThreadTimeMillis();
+
+    /**
+     * Returns microseconds running in the current thread.
+     * 
+     * @return elapsed microseconds in the thread
+     * 
+     * @hide
+     */
+    public static native long currentThreadTimeMicro();
+
+    /**
+     * Returns current wall time in  microseconds.
+     * 
+     * @return elapsed microseconds in wall time
+     * 
+     * @hide
+     */
+    public static native long currentTimeMicro();
 }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 60900e1..2c4b8631 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -172,7 +172,10 @@
 
     @Override
     public String toString() {
-        return mPath;
+        return "StorageVolume [mAllowMassStorage=" + mAllowMassStorage + ", mDescription="
+                + mDescription + ", mEmulated=" + mEmulated + ", mMaxFileSize=" + mMaxFileSize
+                + ", mMtpReserveSpace=" + mMtpReserveSpace + ", mPath=" + mPath + ", mRemovable="
+                + mRemovable + ", mStorageId=" + mStorageId + "]";
     }
 
     public static final Parcelable.Creator<StorageVolume> CREATOR =
diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java
index 7c78a81..21fc594 100644
--- a/core/java/android/pim/ContactsAsyncHelper.java
+++ b/core/java/android/pim/ContactsAsyncHelper.java
@@ -186,7 +186,7 @@
                     InputStream inputStream = null;
                     try {
                         inputStream = Contacts.openContactPhotoInputStream(
-                                args.context.getContentResolver(), args.uri);
+                                args.context.getContentResolver(), args.uri, true);
                     } catch (Exception e) {
                         Log.e(LOG_TAG, "Error opening photo input stream", e);
                     }
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
index 437e553..166b21b 100644
--- a/core/java/android/preference/CheckBoxPreference.java
+++ b/core/java/android/preference/CheckBoxPreference.java
@@ -61,8 +61,8 @@
         View checkboxView = view.findViewById(com.android.internal.R.id.checkbox);
         if (checkboxView != null && checkboxView instanceof Checkable) {
             ((Checkable) checkboxView).setChecked(mChecked);
-
-            sendAccessibilityEventForView(checkboxView);
+            // Post this so this view is bound and attached when firing the event.
+            postSendAccessibilityEventForView(checkboxView);
         }
 
         syncSummaryView(view);
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index c90de17..78c9010 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -563,6 +563,12 @@
             // Single pane, showing just a prefs fragment.
             findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
             mPrefsContainer.setVisibility(View.VISIBLE);
+            if (initialTitle != 0) {
+                CharSequence initialTitleStr = getText(initialTitle);
+                CharSequence initialShortTitleStr = initialShortTitle != 0
+                        ? getText(initialShortTitle) : null;
+                showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+            }
         } else if (mHeaders.size() > 0) {
             setListAdapter(new HeaderAdapter(this, mHeaders));
             if (!mSinglePane) {
@@ -1093,6 +1099,10 @@
         } else {
             getListView().clearChoices();
         }
+        showBreadCrumbs(header);
+    }
+
+    void showBreadCrumbs(Header header) {
         if (header != null) {
             CharSequence title = header.getBreadCrumbTitle(getResources());
             if (title == null) title = header.getTitle(getResources());
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index b8919c2..7133d3a 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -77,6 +77,11 @@
     }
 
     @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getInt(index, 0);
+    }
+
+    @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         if (event.getAction() != KeyEvent.ACTION_UP) {
             if (keyCode == KeyEvent.KEYCODE_PLUS
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index f681526..3dbd522 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -102,8 +102,8 @@
         View checkableView = view.findViewById(com.android.internal.R.id.switchWidget);
         if (checkableView != null && checkableView instanceof Checkable) {
             ((Checkable) checkableView).setChecked(mChecked);
-
-            sendAccessibilityEventForView(checkableView);
+            // Post this so this view is bound and attached when firing the event.
+            postSendAccessibilityEventForView(checkableView);
 
             if (checkableView instanceof Switch) {
                 final Switch switchView = (Switch) checkableView;
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 8e21c4c..55ef108 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -16,7 +16,6 @@
 
 package android.preference;
 
-import android.app.Service;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
@@ -39,28 +38,20 @@
     private CharSequence mSummaryOff;
     boolean mChecked;
     private boolean mSendAccessibilityEventViewClickedType;
-    private AccessibilityManager mAccessibilityManager;
     private boolean mDisableDependentsState;
 
+    private SendAccessibilityEventTypeViewClicked mSendAccessibilityEventTypeViewClicked;
+
     public TwoStatePreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-
-        mAccessibilityManager =
-                (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
     }
 
     public TwoStatePreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        mAccessibilityManager =
-                (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
+        this(context, attrs, 0);
     }
 
     public TwoStatePreference(Context context) {
-        super(context);
-
-        mAccessibilityManager =
-                (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
+        this(context, null);
     }
 
     @Override
@@ -198,20 +189,23 @@
     }
 
     /**
-     * Send an accessibility event for the given view if appropriate
+     * Post send an accessibility event for the given view if appropriate.
+     *
      * @param view View that should send the event
      */
-    void sendAccessibilityEventForView(View view) {
+    void postSendAccessibilityEventForView(View view) {
         // send an event to announce the value change of the state. It is done here
         // because clicking a preference does not immediately change the checked state
         // for example when enabling the WiFi
-        if (mSendAccessibilityEventViewClickedType &&
-                mAccessibilityManager.isEnabled() &&
-                view.isEnabled()) {
+        if (mSendAccessibilityEventViewClickedType
+                && AccessibilityManager.getInstance(getContext()).isEnabled()
+                && view.isEnabled()) {
             mSendAccessibilityEventViewClickedType = false;
-
-            int eventType = AccessibilityEvent.TYPE_VIEW_CLICKED;
-            view.sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
+            if (mSendAccessibilityEventTypeViewClicked == null) {
+                mSendAccessibilityEventTypeViewClicked = new SendAccessibilityEventTypeViewClicked();
+            }
+            mSendAccessibilityEventTypeViewClicked.mView = view;
+            view.post(mSendAccessibilityEventTypeViewClicked);
         }
     }
 
@@ -306,4 +300,13 @@
             }
         };
     }
+
+    private final class SendAccessibilityEventTypeViewClicked implements Runnable {
+        private View mView;
+
+        @Override
+        public void run() {
+            mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+        }
+    }
 }
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 382fcf3..b8ef7be 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -184,6 +184,15 @@
         public static final String VOICEMAIL_URI = "voicemail_uri";
 
         /**
+         * Whether this item has been read or otherwise consumed by the user.
+         * <p>
+         * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
+         * existence of the entry, this implies the user has interacted with the entry.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String IS_READ = "is_read";
+
+        /**
          * Adds a call to the call log.
          *
          * @param ci the CallerInfo object to get the target contact from.  Can be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index ec67683c..5765dde 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -17,6 +17,7 @@
 package android.provider;
 
 import android.accounts.Account;
+import android.app.Activity;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
@@ -27,6 +28,7 @@
 import android.content.Entity;
 import android.content.EntityIterator;
 import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
@@ -39,6 +41,7 @@
 import android.view.View;
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 
@@ -749,11 +752,25 @@
         public static final String PHOTO_ID = "photo_id";
 
         /**
+         * Photo file ID of the full-size photo.  If present, this will be used to populate
+         * {@link #PHOTO_URI}.  The ID can also be used with
+         * {@link ContactsContract.DisplayPhoto#CONTENT_URI} to create a URI to the photo.
+         * If this is present, {@link #PHOTO_ID} is also guaranteed to be populated.
+         *
+         * <P>Type: INTEGER</P>
+         */
+        public static final String PHOTO_FILE_ID = "photo_file_id";
+
+        /**
          * A URI that can be used to retrieve the contact's full-size photo.
+         * If PHOTO_FILE_ID is not null, this will be populated with a URI based off
+         * {@link ContactsContract.DisplayPhoto#CONTENT_URI}.  Otherwise, this will
+         * be populated with the same value as {@link #PHOTO_THUMBNAIL_URI}.
          * A photo can be referred to either by a URI (this field) or by ID
-         * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
-         * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
-         * Thus using PHOTO_URI is a more robust method of retrieving contact photos.
+         * (see {@link #PHOTO_ID}). If either PHOTO_FILE_ID or PHOTO_ID is not null,
+         * PHOTO_URI and PHOTO_THUMBNAIL_URI shall not be null (but not necessarily
+         * vice versa).  Thus using PHOTO_URI is a more robust method of retrieving
+         * contact photos.
          *
          * <P>Type: TEXT</P>
          */
@@ -766,7 +783,7 @@
          * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
          * If the content provider does not differentiate between full-size photos
          * and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain
-         * the same value, but either both shell be null or both not null.
+         * the same value, but either both shall be null or both not null.
          *
          * <P>Type: TEXT</P>
          */
@@ -1422,6 +1439,13 @@
                 CONTENT_URI, "strequent");
 
         /**
+         * The content:// style URI for showing frequently contacted person listing.
+         * @hide
+         */
+        public static final Uri CONTENT_FREQUENT_URI = Uri.withAppendedPath(
+                CONTENT_URI, "frequent");
+
+        /**
          * The content:// style URI used for "type-to-filter" functionality on the
          * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match
          * various parts of the contact name. The filter argument should be passed
@@ -1690,10 +1714,15 @@
 
         /**
          * A <i>read-only</i> sub-directory of a single contact that contains
-         * the contact's primary photo.
+         * the contact's primary photo.  The photo may be stored in up to two ways -
+         * the default "photo" is a thumbnail-sized image stored directly in the data
+         * row, while the "display photo", if present, is a larger version stored as
+         * a file.
          * <p>
          * Usage example:
-         *
+         * <dl>
+         * <dt>Retrieving the thumbnail-sized photo</dt>
+         * <dd>
          * <pre>
          * public InputStream openPhoto(long contactId) {
          *     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
@@ -1716,10 +1745,29 @@
          *     return null;
          * }
          * </pre>
+         * </dd>
+         * <dt>Retrieving the larger photo version</dt>
+         * <dd>
+         * <pre>
+         * public InputStream openDisplayPhoto(long contactId) {
+         *     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+         *     Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
+         *     try {
+         *         AssetFileDescriptor fd =
+         *             getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
+         *         return fd.createInputStream();
+         *     } catch (IOException e) {
+         *         return null;
+         *     }
+         * }
+         * </pre>
+         * </dd>
+         * </dl>
          *
          * </p>
-         * <p>You should also consider using the convenience method
-         * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)}
+         * <p>You may also consider using the convenience method
+         * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri, boolean)}
+         * to retrieve the raw photo contents of either the thumbnail-sized or the full-sized photo.
          * </p>
          * <p>
          * This directory can be used either with a {@link #CONTENT_URI} or
@@ -1738,6 +1786,19 @@
             public static final String CONTENT_DIRECTORY = "photo";
 
             /**
+             * The directory twig for retrieving the full-size display photo.
+             */
+            public static final String DISPLAY_PHOTO = "display_photo";
+
+            /**
+             * Full-size photo file ID of the raw contact.
+             * See {@link ContactsContract.DisplayPhoto}.
+             * <p>
+             * Type: NUMBER
+             */
+            public static final String PHOTO_FILE_ID = DATA14;
+
+            /**
              * Thumbnail photo of the raw contact. This is the raw bytes of an image
              * that could be inflated using {@link android.graphics.BitmapFactory}.
              * <p>
@@ -1747,22 +1808,37 @@
         }
 
         /**
-         * Opens an InputStream for the contacts's default photo and returns the
-         * photo as a byte stream. If there is not photo null will be returned.
-         *
+         * Opens an InputStream for the contacts's photo and returns the
+         * photo as a byte stream.
+         * @param cr The content resolver to use for querying
          * @param contactUri the contact whose photo should be used. This can be used with
          * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI.
-         * </p>
-
+         * @param preferHighres If this is true and the contact has a higher resolution photo
+         * available, it is returned. If false, this function always tries to get the thumbnail
          * @return an InputStream of the photo, or null if no photo is present
          */
-        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
+        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri,
+                boolean preferHighres) {
+            if (preferHighres) {
+                final Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
+                        Contacts.Photo.DISPLAY_PHOTO);
+                InputStream inputStream;
+                try {
+                    AssetFileDescriptor fd = cr.openAssetFileDescriptor(displayPhotoUri, "r");
+                    return fd.createInputStream();
+                } catch (IOException e) {
+                    // fallback to the thumbnail code
+                }
+           }
+
             Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY);
             if (photoUri == null) {
                 return null;
             }
             Cursor cursor = cr.query(photoUri,
-                    new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
+                    new String[] {
+                        ContactsContract.CommonDataKinds.Photo.PHOTO
+                    }, null, null, null);
             try {
                 if (cursor == null || !cursor.moveToNext()) {
                     return null;
@@ -1778,6 +1854,20 @@
                 }
             }
         }
+
+        /**
+         * Opens an InputStream for the contacts's thumbnail photo and returns the
+         * photo as a byte stream.
+         * @param cr The content resolver to use for querying
+         * @param contactUri the contact whose photo should be used. This can be used with
+         * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI.
+         * @return an InputStream of the photo, or null if no photo is present
+         * @see #openContactPhotoInputStream(ContentResolver, Uri, boolean), if instead
+         * of the thumbnail the high-res picture is preferred
+         */
+        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
+            return openContactPhotoInputStream(cr, contactUri, false);
+        }
     }
 
     /**
@@ -1883,6 +1973,16 @@
         public static final String DATA_SET = "data_set";
 
         /**
+         * A concatenation of the account type and data set (delimited by a forward
+         * slash) - if the data set is empty, this will be the same as the account
+         * type.  For applications that need to be aware of the data set, this can
+         * be used instead of account type to distinguish sets of data.  This is
+         * never intended to be used for specifying accounts.
+         * @hide
+         */
+        public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
+
+        /**
          * The aggregation mode for this contact.
          * <P>Type: INTEGER</P>
          */
@@ -2498,6 +2598,56 @@
         }
 
         /**
+         * <p>
+         * A sub-directory of a single raw contact that represents its primary
+         * display photo.  To access this directory append
+         * {@link RawContacts.DisplayPhoto#CONTENT_DIRECTORY} to the raw contact URI.
+         * The resulting URI represents an image file, and should be interacted with
+         * using ContentResolver.openAssetFileDescriptor.
+         * <p>
+         * <p>
+         * Note that this sub-directory also supports opening the photo as an asset file
+         * in write mode.  Callers can create or replace the primary photo associated
+         * with this raw contact by opening the asset file and writing the full-size
+         * photo contents into it.  When the file is closed, the image will be parsed,
+         * sized down if necessary for the full-size display photo and thumbnail
+         * dimensions, and stored.
+         * </p>
+         * <p>
+         * Usage example:
+         * <pre>
+         * public void writeDisplayPhoto(long rawContactId, byte[] photo) {
+         *     Uri rawContactPhotoUri = Uri.withAppendedPath(
+         *             ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+         *             RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
+         *     try {
+         *         AssetFileDescriptor fd =
+         *             getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "rw");
+         *         OutputStream os = fd.createOutputStream();
+         *         os.write(photo);
+         *         os.close();
+         *         fd.close();
+         *     } catch (IOException e) {
+         *         // Handle error cases.
+         *     }
+         * }
+         * </pre>
+         * </p>
+         */
+        public static final class DisplayPhoto {
+            /**
+             * No public constructor since this is a utility class
+             */
+            private DisplayPhoto() {
+            }
+
+            /**
+             * The directory twig for this sub-table
+             */
+            public static final String CONTENT_DIRECTORY = "display_photo";
+        }
+
+        /**
          * TODO: javadoc
          * @param cursor
          * @return
@@ -2671,7 +2821,7 @@
 
         /**
          * The package containing resources for this status: label and icon.
-         * <p>Type: NUMBER</p>
+         * <p>Type: TEXT</p>
          */
         public static final String STATUS_RES_PACKAGE = "status_res_package";
 
@@ -2739,7 +2889,7 @@
      * 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.COMMENTS, "3 people reshared this");
      * values.put(StreamItems.ACTION, action);
      * values.put(StreamItems.ACTION_URI, actionUri);
      * Uri streamItemUri = getContentResolver().insert(
@@ -2754,7 +2904,7 @@
      * 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.COMMENTS, "3 people reshared this");
      * values.put(StreamItems.ACTION, action);
      * values.put(StreamItems.ACTION_URI, actionUri);
      * Uri streamItemUri = getContentResolver().insert(StreamItems.CONTENT_URI, values);
@@ -2773,7 +2923,7 @@
      * <pre>
      * values.clear();
      * values.put(StreamItemPhotos.SORT_INDEX, 1);
-     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.PHOTO, photoData);
      * values.put(StreamItemPhotos.ACTION, action);
      * values.put(StreamItemPhotos.ACTION_URI, actionUri);
      * getContentResolver().insert(Uri.withAppendedPath(
@@ -2787,7 +2937,7 @@
      * values.clear();
      * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId);
      * values.put(StreamItemPhotos.SORT_INDEX, 1);
-     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.PHOTO, photoData);
      * values.put(StreamItemPhotos.ACTION, action);
      * values.put(StreamItemPhotos.ACTION_URI, actionUri);
      * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values);
@@ -2875,8 +3025,7 @@
 
         /**
          * 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.
+         * that will be stored under any single raw contact.
          */
         public static final Uri CONTENT_LIMIT_URI =
                 Uri.withAppendedPath(AUTHORITY_URI, "stream_items_limit");
@@ -2889,13 +3038,6 @@
         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
@@ -2934,7 +3076,7 @@
          * 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>
+         * <P>Type: TEXT</P>
          */
         public static final String RES_PACKAGE = "res_package";
 
@@ -3028,7 +3170,7 @@
      * <pre>
      * ContentValues values = new ContentValues();
      * values.put(StreamItemPhotos.SORT_INDEX, 1);
-     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.PHOTO, photoData);
      * values.put(StreamItemPhotos.ACTION, action);
      * values.put(StreamItemPhotos.ACTION_URI, actionUri);
      * Uri photoUri = getContentResolver().insert(Uri.withAppendedPath(
@@ -3043,7 +3185,7 @@
      * 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.PHOTO, photoData);
      * values.put(StreamItemPhotos.ACTION, action);
      * values.put(StreamItemPhotos.ACTION_URI, actionUri);
      * Uri photoUri = getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values);
@@ -3065,7 +3207,7 @@
      * <dd>
      * <pre>
      * ContentValues values = new ContentValues();
-     * values.put(StreamItemPhotos.PICTURE, newPhotoData);
+     * values.put(StreamItemPhotos.PHOTO, newPhotoData);
      * getContentResolver().update(
      *     ContentUris.withAppendedId(
      *         Uri.withAppendedPath(
@@ -3079,7 +3221,7 @@
      * <pre>
      * ContentValues values = new ContentValues();
      * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId);
-     * values.put(StreamItemPhotos.PICTURE, newPhotoData);
+     * values.put(StreamItemPhotos.PHOTO, newPhotoData);
      * getContentResolver().update(StreamItems.CONTENT_PHOTO_URI, values);
      * </pre>
      * </dd>
@@ -3138,6 +3280,21 @@
      *     null, null, null, StreamItemPhotos.SORT_INDEX);
      * </pre>
      * </dl>
+     * The record will contain both a {@link StreamItemPhotos#PHOTO_FILE_ID} and a
+     * {@link StreamItemPhotos#PHOTO_URI}.  The {@link StreamItemPhotos#PHOTO_FILE_ID}
+     * can be used in conjunction with the {@link ContactsContract.DisplayPhoto} API to
+     * retrieve photo content, or you can open the {@link StreamItemPhotos#PHOTO_URI} as
+     * an asset file, as follows:
+     * <pre>
+     * public InputStream openDisplayPhoto(String photoUri) {
+     *     try {
+     *         AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(photoUri, "r");
+     *         return fd.createInputStream();
+     *     } catch (IOException e) {
+     *         return null;
+     *     }
+     * }
+     * <pre>
      * </dd>
      * </dl>
      */
@@ -3147,6 +3304,20 @@
          */
         private StreamItemPhotos() {
         }
+
+        /**
+         * <p>
+         * The binary representation of the photo.  Any size photo can be inserted;
+         * the provider will resize it appropriately for storage and display.
+         * </p>
+         * <p>
+         * This is only intended for use when inserting or updating a stream item photo.
+         * To retrieve the photo that was stored, open {@link StreamItemPhotos#PHOTO_URI}
+         * as an asset file.
+         * </p>
+         * <P>Type: BLOB</P>
+         */
+        public static final String PHOTO = "photo";
     }
 
     /**
@@ -3169,13 +3340,18 @@
         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>
+         * Photo file ID for the photo.
+         * See {@link ContactsContract.DisplayPhoto}.
+         * <P>Type: NUMBER</P>
          */
-        public static final String PICTURE = "picture";
+        public static final String PHOTO_FILE_ID = "photo_file_id";
+
+        /**
+         * URI for retrieving the photo content, automatically populated.  Callers
+         * may retrieve the photo content by opening this URI as an asset file.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PHOTO_URI = "photo_uri";
 
         /**
          * The activity action to execute when the photo is tapped.
@@ -3192,6 +3368,50 @@
     }
 
     /**
+     * <p>
+     * Constants for the photo files table, which tracks metadata for hi-res photos
+     * stored in the file system.
+     * </p>
+     *
+     * @hide
+     */
+    public static final class PhotoFiles implements BaseColumns, PhotoFilesColumns {
+        /**
+         * No public constructor since this is a utility class
+         */
+        private PhotoFiles() {
+        }
+    }
+
+    /**
+     * Columns in the PhotoFiles table.
+     *
+     * @see ContactsContract.PhotoFiles
+     *
+     * @hide
+     */
+    protected interface PhotoFilesColumns {
+
+        /**
+         * The height, in pixels, of the photo this entry is associated with.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String HEIGHT = "height";
+
+        /**
+         * The width, in pixels, of the photo this entry is associated with.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String WIDTH = "width";
+
+        /**
+         * The size, in bytes, of the photo stored on disk.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String FILESIZE = "filesize";
+    }
+
+    /**
      * Columns in the Data table.
      *
      * @see ContactsContract.Data
@@ -5891,7 +6111,7 @@
 
         /**
          * <p>
-         * A data kind representing an photo for the contact.
+         * A data kind representing a photo for the contact.
          * </p>
          * <p>
          * Some sync adapters will choose to download photos in a separate
@@ -5911,10 +6131,17 @@
          * <th>Alias</th><th colspan='2'>Data column</th>
          * </tr>
          * <tr>
+         * <td>NUMBER</td>
+         * <td>{@link #PHOTO_FILE_ID}</td>
+         * <td>{@link #DATA14}</td>
+         * <td>ID of the hi-res photo file.</td>
+         * </tr>
+         * <tr>
          * <td>BLOB</td>
          * <td>{@link #PHOTO}</td>
          * <td>{@link #DATA15}</td>
-         * <td>By convention, binary data is stored in DATA15.</td>
+         * <td>By convention, binary data is stored in DATA15.  The thumbnail of the
+         * photo is stored in this column.</td>
          * </tr>
          * </table>
          */
@@ -5928,6 +6155,14 @@
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
 
             /**
+             * Photo file ID for the display photo of the raw contact.
+             * See {@link ContactsContract.DisplayPhoto}.
+             * <p>
+             * Type: NUMBER
+             */
+            public static final String PHOTO_FILE_ID = DATA14;
+
+            /**
              * Thumbnail photo of the raw contact. This is the raw bytes of an image
              * that could be inflated using {@link android.graphics.BitmapFactory}.
              * <p>
@@ -6219,6 +6454,16 @@
         public static final String DATA_SET = "data_set";
 
         /**
+         * A concatenation of the account type and data set (delimited by a forward
+         * slash) - if the data set is empty, this will be the same as the account
+         * type.  For applications that need to be aware of the data set, this can
+         * be used instead of account type to distinguish sets of data.  This is
+         * never intended to be used for specifying accounts.
+         * @hide
+         */
+        public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
+
+        /**
          * The display title of this group.
          * <p>
          * Type: TEXT
@@ -6251,6 +6496,28 @@
         public static final String NOTES = "notes";
 
         /**
+         * The Activity action to open the group in the source app (e.g.
+         * {@link Intent#ACTION_VIEW}). Can be NULL if the group does not have a dedicated viewer.
+         * This is used in conjunction with {@link #ACTION_URI}: In order to show an "Open in
+         * (sourceapp)"-button, both of these fields must be set
+         * <p>
+         * Type: TEXT
+         */
+        public static final String ACTION = "action";
+
+
+        /**
+         * Uri to open the group in the source app.
+         * Can be NULL if the group does not have a dedicated viewer.
+         * This is used in conjunction with {@link #ACTION}: In order to show an "Open in
+         * (sourceapp)"-button, both of these fields must be set
+         * <p>
+         * Type: TEXT
+         */
+        public static final String ACTION_URI = "action_uri";
+
+
+        /**
          * The ID of this group if it is a System Group, i.e. a group that has a special meaning
          * to the sync adapter, null otherwise.
          * <P>Type: TEXT</P>
@@ -6267,6 +6534,32 @@
         public static final String SUMMARY_COUNT = "summ_count";
 
         /**
+         * A boolean query parameter that can be used with {@link Groups#CONTENT_SUMMARY_URI}.
+         * It will additionally return {@link #SUMMARY_GROUP_COUNT_PER_ACCOUNT}.
+         *
+         * @hide
+         */
+        public static final String PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT =
+                "return_group_count_per_account";
+
+        /**
+         * The total number of groups of the account that a group belongs to.
+         * This column is available only when the parameter
+         * {@link #PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT} is specified in
+         * {@link Groups#CONTENT_SUMMARY_URI}.
+         *
+         * For example, when the account "A" has two groups "group1" and "group2", and the account
+         * "B" has a group "group3", the rows for "group1" and "group2" return "2" and the row for
+         * "group3" returns "1" for this column.
+         *
+         * Note: This counts only non-favorites, non-auto-add, and not deleted groups.
+         *
+         * Type: INTEGER
+         * @hide
+         */
+        public static final String SUMMARY_GROUP_COUNT_PER_ACCOUNT = "group_count_per_account";
+
+        /**
          * The total number of {@link Contacts} that have both
          * {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers.
          * Read-only value that is only present when querying
@@ -7047,6 +7340,67 @@
     }
 
     /**
+     * Helper class for accessing full-size photos by photo file ID.
+     * <p>
+     * Usage example:
+     * <dl>
+     * <dt>Retrieving a full-size photo by photo file ID (see
+     * {@link ContactsContract.ContactsColumns#PHOTO_FILE_ID})
+     * </dt>
+     * <dd>
+     * <pre>
+     * public InputStream openDisplayPhoto(long photoFileId) {
+     *     Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey);
+     *     try {
+     *         AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(
+     *             displayPhotoUri, "r");
+     *         return fd.createInputStream();
+     *     } catch (IOException e) {
+     *         return null;
+     *     }
+     * }
+     * </pre>
+     * </dd>
+     * </dl>
+     * </p>
+     */
+    public static final class DisplayPhoto {
+        /**
+         * no public constructor since this is a utility class
+         */
+        private DisplayPhoto() {}
+
+        /**
+         * The content:// style URI for this class, which allows access to full-size photos,
+         * given a key.
+         */
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "display_photo");
+
+        /**
+         * This URI allows the caller to query for the maximum dimensions of a display photo
+         * or thumbnail.  Requests to this URI can be performed on the UI thread because
+         * they are always unblocking.
+         */
+        public static final Uri CONTENT_MAX_DIMENSIONS_URI =
+                Uri.withAppendedPath(AUTHORITY_URI, "photo_dimensions");
+
+        /**
+         * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+         * contain this column, populated with the maximum height and width (in pixels)
+         * that will be stored for a display photo.  Larger photos will be down-sized to
+         * fit within a square of this many pixels.
+         */
+        public static final String DISPLAY_MAX_DIM = "display_max_dim";
+
+        /**
+         * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+         * contain this column, populated with the height and width (in pixels) for photo
+         * thumbnails.
+         */
+        public static final String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+    }
+
+    /**
      * Contains helper classes used to create or manage {@link android.content.Intent Intents}
      * that involve contacts.
      */
@@ -7079,6 +7433,16 @@
                 "com.android.contacts.action.ATTACH_IMAGE";
 
         /**
+         * This is the intent that is fired when the user clicks the "invite to the network" button
+         * on a contact.  Only sent to an activity which is explicitly registered by a contact
+         * provider which supports the "invite to the network" feature.
+         * <p>
+         * {@link Intent#getData()} contains the lookup URI for the contact.
+         */
+        public static final String INVITE_CONTACT =
+                "com.android.contacts.action.INVITE_CONTACT";
+
+        /**
          * Takes as input a data URI with a mailto: or tel: scheme. If a single
          * contact exists with the given data it will be shown. If no contact
          * exists, a dialog will ask the user if they want to create a new
@@ -7527,6 +7891,19 @@
              * @hide
              */
             public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
+
+            /**
+             * Used to specify the data set within the account in which to create the
+             * new contact.
+             * <p>
+             * This value is optional - if it is not specified, the contact will be
+             * created in the base account, with no data set.
+             * <p>
+             * Type: String
+             *
+             * @hide
+             */
+            public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
         }
     }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 23b53ae..cd4e32e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,8 +16,6 @@
 
 package android.provider;
 
-
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.SearchManager;
@@ -48,7 +46,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 
-
 /**
  * The Settings provider contains global system-level device preferences.
  */
@@ -1045,6 +1042,14 @@
         }
 
         /**
+         * @hide Erase the fields in the Configuration that should be applied
+         * by the settings.
+         */
+        public static void clearConfiguration(Configuration inoutConfig) {
+            inoutConfig.fontScale = 0;
+        }
+        
+        /**
          * Convenience function to write a batch of configuration-related
          * settings from a {@link Configuration} object.
          *
@@ -2683,6 +2688,11 @@
         public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
 
         /**
+         * If touch exploration is enabled.
+         */
+        public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
+
+        /**
          * List of the enabled accessibility providers.
          */
         public static final String ENABLED_ACCESSIBILITY_SERVICES =
@@ -2862,6 +2872,7 @@
          * The acceptable packet loss percentage (range 0 - 100) before trying
          * another AP on the same network.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE =
                 "wifi_watchdog_acceptable_packet_loss_percentage";
 
@@ -2869,11 +2880,13 @@
          * The number of access points required for a network in order for the
          * watchdog to monitor it.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
 
         /**
          * The delay between background checks.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
                 "wifi_watchdog_background_check_delay_ms";
 
@@ -2881,12 +2894,14 @@
          * Whether the Wi-Fi watchdog is enabled for background checking even
          * after it thinks the user has connected to a good access point.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED =
                 "wifi_watchdog_background_check_enabled";
 
         /**
          * The timeout for a background ping
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS =
                 "wifi_watchdog_background_check_timeout_ms";
 
@@ -2896,6 +2911,7 @@
          * calculation. For example, one network always seemed to time out for
          * the first couple pings, so this is set to 3 by default.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT =
             "wifi_watchdog_initial_ignored_ping_count";
 
@@ -2905,6 +2921,7 @@
          * initial connection state for the network. This is a safeguard for
          * networks containing multiple APs whose DNS does not respond to pings.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
 
         /**
@@ -2915,24 +2932,85 @@
         /**
          * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
 
         /**
          * The number of pings to test if an access point is a good connection.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
 
         /**
          * The delay between pings.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
 
         /**
          * The timeout per ping.
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
 
         /**
+         * ms delay before rechecking an 'online' wifi connection when it is thought to be unstable.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS =
+                "wifi_watchdog_dns_check_short_interval_ms";
+
+        /**
+         * ms delay before rechecking an 'online' wifi connection when it is thought to be stable.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS =
+                "wifi_watchdog_dns_check_long_interval_ms";
+
+        /**
+         * ms delay before rechecking a connect SSID for walled garden with a http download.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS =
+                "wifi_watchdog_walled_garden_interval_ms";
+
+        /**
+         * max blacklist calls on an SSID before full dns check failures disable the network.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_MAX_SSID_BLACKLISTS =
+                "wifi_watchdog_max_ssid_blacklists";
+
+        /**
+         * Number of dns pings per check.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_NUM_DNS_PINGS = "wifi_watchdog_num_dns_pings";
+
+        /**
+         * Minimum number of responses to the dns pings to consider the test 'successful'.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_MIN_DNS_RESPONSES =
+                "wifi_watchdog_min_dns_responses";
+
+        /**
+         * Timeout on dns pings
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS =
+                "wifi_watchdog_dns_ping_timeout_ms";
+
+        /**
+         * We consider action from a 'blacklist' call to have finished by the end of
+         * this interval.  If we are connected to the same AP with no network connection,
+         * we are likely stuck on an SSID with no external connectivity.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS =
+                "wifi_watchdog_blacklist_followup_interval_ms";
+
+        /**
          * Setting to turn off walled garden test on Wi-Fi. Feature is enabled by default and
          * the setting needs to be set to 0 to disable it.
          * @hide
@@ -2957,6 +3035,14 @@
                 "wifi_watchdog_walled_garden_pattern";
 
         /**
+         * Boolean to determine whether to notify on disabling a network.  Secure setting used
+         * to notify user only once.  This setting is not monitored continuously.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP =
+                "wifi_watchdog_show_disabled_network_popup";
+
+        /**
          * The maximum number of times we will retry a connection to an access
          * point for which we have failed in acquiring an IP address from DHCP.
          * A value of N means that we will make N+1 connection attempts in all.
@@ -3646,6 +3732,15 @@
          */
         public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
+
+        /**
+         * The {@link ComponentName} string of the service to be used as the spell checker
+         * service which is one of the services managed by the text service manager.
+         *
+         * @hide
+         */
+        public static final String SPELL_CHECKER_SERVICE = "spell_checker_service";
+
         /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
@@ -3838,6 +3933,10 @@
         /** Timeout in milliseconds to wait for NTP server. {@hide} */
         public static final String NTP_TIMEOUT = "ntp_timeout";
 
+        /** Autofill server address (Used in WebView/browser). {@hide} */
+        public static final String WEB_AUTOFILL_QUERY_URL =
+            "web_autofill_query_url";
+
         /**
          * @hide
          */
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index d0712d5..a31374f 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -16,6 +16,9 @@
 
 package android.provider;
 
+import android.Manifest;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.Uri;
@@ -25,11 +28,26 @@
  * The contract between the voicemail provider and applications. Contains
  * definitions for the supported URIs and columns.
  *
+ * <P>The content providers exposes two tables through this interface:
+ * <ul>
+ *   <li> Voicemails table: This stores the actual voicemail records. The
+ *   columns and URIs for accessing this table are defined by the
+ *   {@link Voicemails} class.
+ *   </li>
+ *   <li> Status table: This provides a way for the voicemail source application
+ *   to convey its current state to the system. The columns and URIS for
+ *   accessing this table are defined by the {@link Status} class.
+ *   </li>
+ * </ul>
+ *
+ * <P> The minimum permission needed to access this content provider is
+ * {@link Manifest.permission#READ_WRITE_OWN_VOICEMAIL}
+ *
  * <P>Voicemails are inserted by what is called as a "voicemail source"
  * application, which is responsible for syncing voicemail data between a remote
  * server and the local voicemail content provider. "voicemail source"
- * application should use the source specific {@link #CONTENT_URI_SOURCE} URI
- * to insert and retrieve voicemails.
+ * application should always set the {@link #PARAM_KEY_SOURCE_PACKAGE} in the
+ * URI to identify its package.
  *
  * <P>In addition to the {@link ContentObserver} notifications the voicemail
  * provider also generates broadcast intents to notify change for applications
@@ -43,9 +61,7 @@
  *    made into the database, including new voicemail.
  *   </li>
  * </ul>
- * @hide
  */
-// TODO: unhide when the API is approved by android-api-council
 public class VoicemailContract {
     /** Not instantiable. */
     private VoicemailContract() {
@@ -59,18 +75,18 @@
      */
     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. */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     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 if the receiving
-     * package made this change.
+     * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
+     * receiving package made this change.
      */
     public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
 
     /**
      * Name of the source package field, which must be same across all voicemail related tables.
+     * This is an internal field.
      * @hide
      */
     public static final String SOURCE_PACKAGE_FIELD = "source_package";
@@ -85,9 +101,12 @@
         public static final Uri CONTENT_URI =
             Uri.parse("content://" + AUTHORITY + "/voicemail");
 
-        /** The mime type for a collection of voicemails. */
+        /** The MIME type for a collection of voicemails. */
         public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
 
+        /** The MIME type for a single voicemail. */
+        public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
+
         /**
          * Phone number of the voicemail sender.
          * <P>Type: TEXT</P>
@@ -104,22 +123,32 @@
          */
         public static final String DURATION = Calls.DURATION;
         /**
-         * Whether this is a new voicemail (i.e. has not been heard).
+         * Whether this item has been read or otherwise consumed by the user.
          * <P>Type: INTEGER (boolean)</P>
          */
-        public static final String NEW = Calls.NEW;
+        public static final String IS_READ = Calls.IS_READ;
         /**
-         * The mail box state of the voicemail.
+         * The mail box state of the voicemail. This field is currently not used by the system.
          * <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED},
          * {@link #STATE_UNDELETED}.
          * <P>Type: INTEGER</P>
+         * @hide
          */
         public static final String STATE = "state";
-        /** Value of {@link #STATE} when the voicemail is in inbox. */
+        /**
+         * Value of {@link #STATE} when the voicemail is in inbox.
+         * @hide
+         */
         public static int STATE_INBOX = 0;
-        /** Value of {@link #STATE} when the voicemail has been marked as deleted. */
+        /**
+         * Value of {@link #STATE} when the voicemail has been marked as deleted.
+         * @hide
+         */
         public static int STATE_DELETED = 1;
-        /** Value of {@link #STATE} when the voicemail has marked as undeleted. */
+        /**
+         * Value of {@link #STATE} when the voicemail has marked as undeleted.
+         * @hide
+         */
         public static int STATE_UNDELETED = 2;
         /**
          * Package name of the source application that inserted the voicemail.
@@ -166,9 +195,9 @@
     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. */
+        /** 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. */
+        /** The MIME type for a single voicemail source status entry. */
         public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
 
         /** Not instantiable. */
@@ -201,10 +230,17 @@
          * <P>Type: INTEGER</P>
          */
         public static final String CONFIGURATION_STATE = "configuration_state";
+        /** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */
         public static final int CONFIGURATION_STATE_OK = 0;
+        /**
+         * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
+         * yet configured on this device.
+         */
         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
+         * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
+         * yet configured on this device but can be configured by the user.
+         * <p> 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;
@@ -218,7 +254,14 @@
          * <P>Type: INTEGER</P>
          */
         public static final String DATA_CHANNEL_STATE = "data_channel_state";
+        /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine.
+         */
         public static final int DATA_CHANNEL_STATE_OK = 0;
+        /**
+         * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel connection is not
+         * working.
+         */
         public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
         /**
          * The notification channel state of the voicemail source. This is the channel through which
@@ -231,10 +274,20 @@
          * <P>Type: INTEGER</P>
          */
         public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+        /**
+         * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is
+         * working fine.
+         */
         public static final int NOTIFICATION_CHANNEL_STATE_OK = 0;
+        /**
+         * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel
+         * connection is not working.
+         */
         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
+         * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that there are messages waiting
+         * on the server but the details are not known.
+         * <p> 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;
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
new file mode 100644
index 0000000..83f5a9f
--- /dev/null
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -0,0 +1,653 @@
+/*
+ * 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.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetoothStateChangeCallback;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.util.IState;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import java.io.PrintWriter;
+
+/**
+ * Bluetooth Adapter StateMachine
+ * All the states are at the same level, ie, no hierarchy.
+ *                         (BluetootOn)<----------------------<-
+ *                           |    ^    -------------------->-  |
+ *                           |    |                         |  |
+ *                 TURN_OFF  |    | BECAME_PAIRABLE     m1 |  | USER_TURN_ON
+ *         AIRPLANE_MODE_ON  |    |                         |  |
+ *                           V    |                         |  |
+ *                         (Switching)                   (PerProcessState)
+ *                           |    ^                         |  |
+ *     BECAME_NON_PAIRABLE&  |    | TURN_ON(_CONTINUE)      |  |
+ * ALL_DEVICES_DISCONNECTED  |    |                     m2  |  |
+ *                           V    |------------------------<   | BECAME_PAIRABLE
+ *                          (HotOff)---------------------------- PER_PROCESS_TURN_ON
+ *                           /    ^
+ *                          /     |  SERVICE_RECORD_LOADED
+ *                         |      |
+ *              TURN_COLD  |   (Warmup)
+ *                         \      ^
+ *                          \     |  TURN_HOT/TURN_ON
+ *                           |    |  AIRPLANE_MODE_OFF(when Bluetooth was on before)
+ *                           V    |
+ *                           (PowerOff)   <----- initial state
+ *
+ * Legend:
+ * m1 = USER_TURN_OFF
+ * m2 = Transition to HotOff when number of process wanting BT on is 0.
+ *      BECAME_NON_PAIRABLE will make the transition.
+ */
+final class BluetoothAdapterStateMachine extends StateMachine {
+    private static final String TAG = "BluetoothAdapterStateMachine";
+    private static final boolean DBG = false;
+
+    // Message(what) to take an action
+    //
+    // We get this message when user tries to turn on BT
+    static final int USER_TURN_ON = 1;
+    // We get this message when user tries to turn off BT
+    static final int USER_TURN_OFF = 2;
+
+    // Message(what) to report a event that the state machine need to respond to
+    //
+    // Event indicates sevice records have been loaded
+    static final int SERVICE_RECORD_LOADED = 51;
+    // Event indicates all the remote Bluetooth devices has been disconnected
+    static final int ALL_DEVICES_DISCONNECTED = 52;
+    // Event indicates the Bluetooth is connectable
+    static final int BECAME_PAIRABLE = 53;
+    // Event indicates the Bluetooth is non-connectable.
+    static final int BECAME_NON_PAIRABLE = 54;
+    // Event indicates airplane mode is turned on
+    static final int AIRPLANE_MODE_ON = 55;
+    // Event indicates airplane mode is turned off
+    static final int AIRPLANE_MODE_OFF = 56;
+
+    // private internal messages
+    //
+    // Turn on Bluetooth Module, Load firmware, and do all the preparation
+    // needed to get the Bluetooth Module ready but keep it not discoverable
+    // and not connectable. This way the Bluetooth Module can be quickly
+    // switched on if needed
+    private static final int TURN_HOT = 101;
+    // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
+    // state change intent so that we will not broadcast the intent again in
+    // other state
+    private static final int TURN_ON_CONTINUE = 102;
+    // Unload firmware, turning off Bluetooth module power
+    private static final int TURN_COLD = 103;
+    // Per process enable / disable messages
+    static final int PER_PROCESS_TURN_ON = 104;
+    static final int PER_PROCESS_TURN_OFF = 105;
+
+    private Context mContext;
+    private BluetoothService mBluetoothService;
+    private BluetoothEventLoop mEventLoop;
+
+    private BluetoothOn mBluetoothOn;
+    private Switching mSwitching;
+    private HotOff mHotOff;
+    private WarmUp mWarmUp;
+    private PowerOff mPowerOff;
+    private PerProcessState mPerProcessState;
+
+    // this is the BluetoothAdapter state that reported externally
+    private int mPublicState;
+
+    BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
+                                 BluetoothAdapter bluetoothAdapter) {
+        super(TAG);
+        mContext = context;
+        mBluetoothService = bluetoothService;
+        mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this);
+
+        mBluetoothOn = new BluetoothOn();
+        mSwitching = new Switching();
+        mHotOff = new HotOff();
+        mWarmUp = new WarmUp();
+        mPowerOff = new PowerOff();
+        mPerProcessState = new PerProcessState();
+
+        addState(mBluetoothOn);
+        addState(mSwitching);
+        addState(mHotOff);
+        addState(mWarmUp);
+        addState(mPowerOff);
+        addState(mPerProcessState);
+
+        setInitialState(mPowerOff);
+        mPublicState = BluetoothAdapter.STATE_OFF;
+
+        if (mContext.getResources().getBoolean
+            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+            sendMessage(TURN_HOT);
+        }
+    }
+
+    /**
+     * Bluetooth module's power is off, firmware is not loaded.
+     */
+    private class PowerOff extends State {
+        @Override
+        public void enter() {
+            if (DBG) log("Enter PowerOff: ");
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("PowerOff process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch(message.what) {
+                case USER_TURN_ON:
+                    // starts turning on BT module, broadcast this out
+                    transitionTo(mWarmUp);
+                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                    if (prepareBluetooth()) {
+                        // this is user request, save the setting
+                        if ((Boolean) message.obj) {
+                            persistSwitchSetting(true);
+                        }
+                        // We will continue turn the BT on all the way to the BluetoothOn state
+                        deferMessage(obtainMessage(TURN_ON_CONTINUE));
+                    } else {
+                        Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+                        transitionTo(mPowerOff);
+                        broadcastState(BluetoothAdapter.STATE_OFF);
+                    }
+                    break;
+                case TURN_HOT:
+                    if (prepareBluetooth()) {
+                        transitionTo(mWarmUp);
+                    }
+                    break;
+                case AIRPLANE_MODE_OFF:
+                    if (getBluetoothPersistedSetting()) {
+                        // starts turning on BT module, broadcast this out
+                        transitionTo(mWarmUp);
+                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                        if (prepareBluetooth()) {
+                            // We will continue turn the BT on all the way to the BluetoothOn state
+                            deferMessage(obtainMessage(TURN_ON_CONTINUE));
+                            transitionTo(mWarmUp);
+                        } else {
+                            Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+                            transitionTo(mPowerOff);
+                            broadcastState(BluetoothAdapter.STATE_OFF);
+                        }
+                    } else if (mContext.getResources().getBoolean
+                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+                        sendMessage(TURN_HOT);
+                    }
+                    break;
+                case PER_PROCESS_TURN_ON:
+                    if (prepareBluetooth()) {
+                        transitionTo(mWarmUp);
+                    }
+                    deferMessage(obtainMessage(PER_PROCESS_TURN_ON));
+                    break;
+                case PER_PROCESS_TURN_OFF:
+                    perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj);
+                    break;
+                case AIRPLANE_MODE_ON:
+                case USER_TURN_OFF: // ignore
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+
+        /**
+         * Turn on Bluetooth Module, Load firmware, and do all the preparation
+         * needed to get the Bluetooth Module ready but keep it not discoverable
+         * and not connectable.
+         * The last step of this method sets up the local service record DB.
+         * There will be a event reporting the status of the SDP setup.
+         */
+        private boolean prepareBluetooth() {
+            if (mBluetoothService.enableNative() != 0) {
+                return false;
+            }
+
+            // try to start event loop, give 2 attempts
+            int retryCount = 2;
+            boolean eventLoopStarted = false;
+            while ((retryCount-- > 0) && !eventLoopStarted) {
+                mEventLoop.start();
+                // it may take a moment for the other thread to do its
+                // thing.  Check periodically for a while.
+                int pollCount = 5;
+                while ((pollCount-- > 0) && !eventLoopStarted) {
+                    if (mEventLoop.isEventLoopRunning()) {
+                        eventLoopStarted = true;
+                        break;
+                    }
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException e) {
+                        break;
+                    }
+                }
+            }
+
+            if (!eventLoopStarted) {
+                mBluetoothService.disableNative();
+                return false;
+            }
+
+            // get BluetoothService ready
+            if (!mBluetoothService.prepareBluetooth()) {
+                mEventLoop.stop();
+                mBluetoothService.disableNative();
+                return false;
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * Turning on Bluetooth module's power, loading firmware, starting
+     * event loop thread to listen on Bluetooth module event changes.
+     */
+    private class WarmUp extends State {
+
+        @Override
+        public void enter() {
+            if (DBG) log("Enter WarmUp");
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("WarmUp process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch(message.what) {
+                case SERVICE_RECORD_LOADED:
+                    transitionTo(mHotOff);
+                    break;
+                case USER_TURN_ON: // handle this at HotOff state
+                case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
+                                       // on to the BluetoothOn state
+                case AIRPLANE_MODE_ON:
+                case AIRPLANE_MODE_OFF:
+                case PER_PROCESS_TURN_ON:
+                case PER_PROCESS_TURN_OFF:
+                    deferMessage(message);
+                    break;
+                case USER_TURN_OFF: // ignore
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+
+    }
+
+    /**
+     * Bluetooth Module has powered, firmware loaded, event loop started,
+     * SDP loaded, but the modules stays non-discoverable and
+     * non-connectable.
+     */
+    private class HotOff extends State {
+        @Override
+        public void enter() {
+            if (DBG) log("Enter HotOff:");
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("HotOff process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch(message.what) {
+                case USER_TURN_ON:
+                    if ((Boolean) message.obj) {
+                        persistSwitchSetting(true);
+                    }
+                    // let it fall to TURN_ON_CONTINUE:
+                    //$FALL-THROUGH$
+                case TURN_ON_CONTINUE:
+                    mBluetoothService.switchConnectable(true);
+                    transitionTo(mSwitching);
+                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                    break;
+                case AIRPLANE_MODE_ON:
+                case TURN_COLD:
+                    mBluetoothService.shutoffBluetooth();
+                    mEventLoop.stop();
+                    transitionTo(mPowerOff);
+                    // ASSERT no support of config_bluetooth_adapter_quick_switch
+                    broadcastState(BluetoothAdapter.STATE_OFF);
+                    break;
+                case AIRPLANE_MODE_OFF:
+                    if (getBluetoothPersistedSetting()) {
+                        transitionTo(mSwitching);
+                        mBluetoothService.switchConnectable(true);
+                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                    }
+                    break;
+                case USER_TURN_OFF: // ignore
+                    break;
+                case PER_PROCESS_TURN_ON:
+                    transitionTo(mPerProcessState);
+
+                    // Resend the PER_PROCESS_TURN_ON message so that the callback
+                    // can be sent through.
+                    deferMessage(message);
+
+                    mBluetoothService.switchConnectable(true);
+                    break;
+                case PER_PROCESS_TURN_OFF:
+                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+
+    }
+
+    private class Switching extends State {
+
+        @Override
+        public void enter() {
+            int what = getCurrentMessage().what;
+            if (DBG) log("Enter Switching: " + what);
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("Switching process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch(message.what) {
+                case BECAME_PAIRABLE:
+                    String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")};
+                    mEventLoop.onPropertyChanged(propVal);
+
+                    // run bluetooth now that it's turned on
+                    mBluetoothService.runBluetooth();
+                    transitionTo(mBluetoothOn);
+                    broadcastState(BluetoothAdapter.STATE_ON);
+                    break;
+                case BECAME_NON_PAIRABLE:
+                    if (mBluetoothService.getAdapterConnectionState() ==
+                        BluetoothAdapter.STATE_DISCONNECTED) {
+                        transitionTo(mHotOff);
+                        finishSwitchingOff();
+                    }
+                    break;
+                case ALL_DEVICES_DISCONNECTED:
+                    if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) {
+                        transitionTo(mHotOff);
+                        finishSwitchingOff();
+                    }
+                    break;
+                case USER_TURN_ON:
+                case AIRPLANE_MODE_OFF:
+                case AIRPLANE_MODE_ON:
+                case PER_PROCESS_TURN_ON:
+                case PER_PROCESS_TURN_OFF:
+                case USER_TURN_OFF:
+                    deferMessage(message);
+                    break;
+
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+
+        private void finishSwitchingOff() {
+            mBluetoothService.finishDisable();
+            if (mContext.getResources().getBoolean
+                (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+                broadcastState(BluetoothAdapter.STATE_OFF);
+            } else {
+                deferMessage(obtainMessage(TURN_COLD));
+            }
+        }
+    }
+
+    private class BluetoothOn extends State {
+        private boolean mPersistBluetoothOff = false;
+
+        @Override
+        public void enter() {
+            if (DBG) log("Enter BluetoothOn: " + mPersistBluetoothOff);
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("BluetoothOn process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch(message.what) {
+                case USER_TURN_OFF:
+                    if ((Boolean) message.obj) {
+                        persistSwitchSetting(false);
+                    }
+
+                    if (mBluetoothService.isDiscovering()) {
+                        mBluetoothService.cancelDiscovery();
+                    }
+                    if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
+                        transitionTo(mPerProcessState);
+                        deferMessage(obtainMessage(USER_TURN_OFF));
+                        break;
+                    }
+                    //$FALL-THROUGH$ to AIRPLANE_MODE_ON
+                case AIRPLANE_MODE_ON:
+                    transitionTo(mSwitching);
+                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+                    mBluetoothService.switchConnectable(false);
+                    mBluetoothService.disconnectDevices();
+
+                    // we turn all the way to PowerOff with AIRPLANE_MODE_ON
+                    if (message.what == AIRPLANE_MODE_ON) {
+                        // We inform all the per process callbacks
+                        allProcessesCallback(false);
+                        deferMessage(obtainMessage(AIRPLANE_MODE_ON));
+                    }
+                    break;
+                case AIRPLANE_MODE_OFF: // ignore
+                case USER_TURN_ON: // ignore
+                    break;
+                case PER_PROCESS_TURN_ON:
+                    perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj);
+                    break;
+                case PER_PROCESS_TURN_OFF:
+                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+
+    }
+
+
+    private class PerProcessState extends State {
+        IBluetoothStateChangeCallback mCallback = null;
+
+        @Override
+        public void enter() {
+            if (DBG) log("Enter PerProcessState");
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log("PerProcessState process message: " + message.what);
+
+            boolean retValue = HANDLED;
+            switch (message.what) {
+                case PER_PROCESS_TURN_ON:
+                    mCallback = (IBluetoothStateChangeCallback)getCurrentMessage().obj;
+
+                    // If this is not the first application call the callback.
+                    if (mBluetoothService.getNumberOfApplicationStateChangeTrackers() > 1) {
+                        perProcessCallback(true, mCallback);
+                    }
+                    break;
+                case BECAME_PAIRABLE:
+                    perProcessCallback(true, mCallback);
+                    break;
+                case USER_TURN_ON:
+                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                    persistSwitchSetting(true);
+
+                    String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")};
+                    mEventLoop.onPropertyChanged(propVal);
+
+                    // run bluetooth now that it's turned on
+                    mBluetoothService.runBluetooth();
+                    transitionTo(mBluetoothOn);
+                    broadcastState(BluetoothAdapter.STATE_ON);
+                    break;
+               case USER_TURN_OFF:
+                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+                    if (mBluetoothService.getAdapterConnectionState() !=
+                        BluetoothAdapter.STATE_DISCONNECTED) {
+                        mBluetoothService.disconnectDevices();
+                        break;
+                    }
+                    //$FALL-THROUGH$ all devices are already disconnected
+                case ALL_DEVICES_DISCONNECTED:
+                    mBluetoothService.finishDisable();
+                    broadcastState(BluetoothAdapter.STATE_OFF);
+                    break;
+               case PER_PROCESS_TURN_OFF:
+                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+                    if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
+                        mBluetoothService.switchConnectable(false);
+                    }
+                    break;
+                case BECAME_NON_PAIRABLE:
+                    transitionTo(mHotOff);
+                    if (!mContext.getResources().getBoolean
+                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+                        deferMessage(obtainMessage(TURN_COLD));
+                    }
+                    break;
+                case AIRPLANE_MODE_ON:
+                    mBluetoothService.switchConnectable(false);
+                    allProcessesCallback(false);
+                    // we turn all the way to PowerOff with AIRPLANE_MODE_ON
+                    deferMessage(obtainMessage(AIRPLANE_MODE_ON));
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return retValue;
+        }
+    }
+
+
+    private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) {
+        if (c == null) return;
+
+        try {
+            c.onBluetoothStateChange(on);
+        } catch (RemoteException e) {}
+    }
+
+    private void allProcessesCallback(boolean on) {
+        for (IBluetoothStateChangeCallback c:
+             mBluetoothService.getApplicationStateChangeCallbacks()) {
+            perProcessCallback(on, c);
+        }
+        if (!on) {
+            mBluetoothService.clearApplicationStateChangeTracker();
+        }
+    }
+
+    /**
+     * Return the public BluetoothAdapter state
+     */
+    int getBluetoothAdapterState() {
+        return mPublicState;
+    }
+
+    BluetoothEventLoop getBluetoothEventLoop() {
+        return mEventLoop;
+    }
+
+    private void persistSwitchSetting(boolean setOn) {
+        long origCallerIdentityToken = Binder.clearCallingIdentity();
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                               Settings.Secure.BLUETOOTH_ON,
+                               setOn ? 1 : 0);
+        Binder.restoreCallingIdentity(origCallerIdentityToken);
+    }
+
+    private boolean getBluetoothPersistedSetting() {
+        ContentResolver contentResolver = mContext.getContentResolver();
+        return (Settings.Secure.getInt(contentResolver,
+                                       Settings.Secure.BLUETOOTH_ON, 0) > 0);
+    }
+
+    private void broadcastState(int newState) {
+
+        log("Bluetooth state " + mPublicState + " -> " + newState);
+        if (mPublicState == newState) {
+            return;
+        }
+
+        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState);
+        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mPublicState = newState;
+
+        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
+    }
+
+    private void dump(PrintWriter pw) {
+        IState currentState = getCurrentState();
+        if (currentState == mPowerOff) {
+            pw.println("Bluetooth OFF - power down\n");
+        } else if (currentState == mWarmUp) {
+            pw.println("Bluetooth OFF - warm up\n");
+        } else if (currentState == mHotOff) {
+            pw.println("Bluetooth OFF - hot but off\n");
+        } else if (currentState == mSwitching) {
+            pw.println("Bluetooth Switching\n");
+        } else if (currentState == mBluetoothOn) {
+            pw.println("Bluetooth ON\n");
+        } else {
+            pw.println("ERROR: Bluetooth UNKNOWN STATE ");
+        }
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
index 75f38f9..30a8b2a 100644
--- a/core/java/android/server/BluetoothBondState.java
+++ b/core/java/android/server/BluetoothBondState.java
@@ -21,8 +21,13 @@
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothHeadset;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.io.BufferedReader;
@@ -74,11 +79,17 @@
     private BluetoothA2dp mA2dpProxy;
     private BluetoothHeadset mHeadsetProxy;
 
+    private ArrayList<String> mPairingRequestRcvd = new ArrayList<String>();
+
     BluetoothBondState(Context context, BluetoothService service) {
         mContext = context;
         mService = service;
         mBluetoothInputProfileHandler =
             BluetoothInputProfileHandler.getInstance(mContext, mService);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        mContext.registerReceiver(mReceiver, filter);
     }
 
     synchronized void setPendingOutgoingBonding(String address) {
@@ -137,11 +148,18 @@
         }
 
         if (state == BluetoothDevice.BOND_BONDED) {
-            mService.addProfileState(address);
+            boolean setTrust = false;
+            if (mPairingRequestRcvd.contains(address)) setTrust = true;
+
+            mService.addProfileState(address, setTrust);
+            mPairingRequestRcvd.remove(address);
+
         } else if (state == BluetoothDevice.BOND_BONDING) {
             if (mA2dpProxy == null || mHeadsetProxy == null) {
                 getProfileProxy();
             }
+        } else if (state == BluetoothDevice.BOND_NONE) {
+            mPairingRequestRcvd.remove(address);
         }
 
         setProfilePriorities(address, state);
@@ -452,4 +470,17 @@
         }
     }
 
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent == null) return;
+
+            String action = intent.getAction();
+            if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
+                BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                String address = dev.getAddress();
+                mPairingRequestRcvd.add(address);
+            }
+        }
+    };
 }
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 63c420a..2cab05c 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -52,6 +52,7 @@
     private final HashMap<String, Integer> mAuthorizationAgentRequestData;
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
+    private final BluetoothAdapterStateMachine mBluetoothState;
     private BluetoothA2dp mA2dp;
     private BluetoothInputDevice mInputDevice;
     private final Context mContext;
@@ -107,9 +108,11 @@
     private static native void classInitNative();
 
     /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
-            BluetoothService bluetoothService) {
+                                     BluetoothService bluetoothService,
+                                     BluetoothAdapterStateMachine bluetoothState) {
         mBluetoothService = bluetoothService;
         mContext = context;
+        mBluetoothState = bluetoothState;
         mPasskeyAgentRequestData = new HashMap<String, Integer>();
         mAuthorizationAgentRequestData = new HashMap<String, Integer>();
         mAdapter = adapter;
@@ -299,8 +302,8 @@
 
     /**
      * Called by native code on a PropertyChanged signal from
-     * org.bluez.Adapter. This method is also called from Java at
-     * {@link BluetoothService.EnableThread#run()} to set the "Pairable"
+     * org.bluez.Adapter. This method is also called from
+     * {@link BluetoothAdapterStateMachine} to set the "Pairable"
      * property when Bluetooth is enabled.
      *
      * @param propValues a string array containing the key and one or more
@@ -334,6 +337,15 @@
                 return;
 
             adapterProperties.setProperty(name, propValues[1]);
+
+            if (name.equals("Pairable")) {
+                if (pairable.equals("true")) {
+                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_PAIRABLE);
+                } else {
+                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_NON_PAIRABLE);
+                }
+            }
+
             int mode = BluetoothService.bluezStringToScanMode(
                     pairable.equals("true"),
                     discoverable.equals("true"));
@@ -660,7 +672,6 @@
             case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
             case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
             case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
-            case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
             case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
                 if (mBluetoothService.attemptAutoPair(address)) return;
            }
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index ff16c18..9e66957 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -39,6 +39,7 @@
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothHealthCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -68,13 +69,15 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
-import java.io.InputStreamReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.RandomAccessFile;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -91,7 +94,7 @@
     private BluetoothPan mPan;
     private boolean mIsAirplaneSensitive;
     private boolean mIsAirplaneToggleable;
-    private int mBluetoothState;
+    private BluetoothAdapterStateMachine mBluetoothState;
     private boolean mRestart = false;  // need to call enable() after disable()
     private boolean mIsDiscovering;
     private int[] mAdapterSdpHandles;
@@ -101,6 +104,8 @@
     private final BluetoothBondState mBondState;  // local cache of bondings
     private final IBatteryStats mBatteryStats;
     private final Context mContext;
+    private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker =
+        Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>());
 
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
@@ -111,9 +116,11 @@
     private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
     private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
 
-    private static final int MESSAGE_FINISH_DISABLE = 1;
-    private static final int MESSAGE_UUID_INTENT = 2;
-    private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3;
+    private static final int MESSAGE_UUID_INTENT = 1;
+    private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
+
+    private static final int RFCOMM_RECORD_REAPER = 10;
+    private static final int STATE_CHANGE_REAPER = 11;
 
     // The time (in millisecs) to delay the pairing attempt after the first
     // auto pairing attempt fails. We use an exponential delay with
@@ -206,7 +213,6 @@
             disableNative();
         }
 
-        mBluetoothState = BluetoothAdapter.STATE_OFF;
         mIsDiscovering = false;
 
         mBondState = new BluetoothBondState(context, this);
@@ -306,7 +312,9 @@
 
     public synchronized void initAfterRegistration() {
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
+        mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
+        mBluetoothState.start();
+        mEventLoop = mBluetoothState.getBluetoothEventLoop();
     }
 
     public synchronized void initAfterA2dpRegistration() {
@@ -329,16 +337,16 @@
     }
 
     private boolean isEnabledInternal() {
-        return mBluetoothState == BluetoothAdapter.STATE_ON;
+        return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
     }
 
     public int getBluetoothState() {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return mBluetoothState;
+        return getBluetoothStateInternal();
     }
 
     int getBluetoothStateInternal() {
-        return mBluetoothState;
+        return mBluetoothState.getBluetoothAdapterState();
     }
 
     /**
@@ -356,7 +364,9 @@
     public synchronized boolean disable(boolean saveSetting) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
 
-        switch (mBluetoothState) {
+        int adapterState = getBluetoothStateInternal();
+
+        switch (adapterState) {
         case BluetoothAdapter.STATE_OFF:
             return true;
         case BluetoothAdapter.STATE_ON:
@@ -364,27 +374,12 @@
         default:
             return false;
         }
-        if (mEnableThread != null && mEnableThread.isAlive()) {
-            return false;
-        }
 
-        setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF);
-
-        if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
-        setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
-                BluetoothPanProfileHandler.NAP_BRIDGE);
-
-        // Allow 3 seconds for profiles to gracefully disconnect
-        // TODO: Introduce a callback mechanism so that each profile can notify
-        // BluetoothService when it is done shutting down
-        disconnectDevices();
-
-        mHandler.sendMessageDelayed(
-                mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
+        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
         return true;
     }
 
-    private synchronized void disconnectDevices() {
+    synchronized void disconnectDevices() {
         // Disconnect devices handled by BluetoothService.
         for (BluetoothDevice device: getConnectedInputDevices()) {
             disconnectInputDevice(device);
@@ -395,14 +390,11 @@
         }
     }
 
-    private synchronized void finishDisable(boolean saveSetting) {
-        if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) {
-            return;
-        }
-        mEventLoop.stop();
-        tearDownNativeDataNative();
-        disableNative();
-
+    /**
+     * The Bluetooth has been turned off, but hot. Do bonding, profile,
+     * and internal cleanup
+     */
+    synchronized void finishDisable() {
         // mark in progress bondings as cancelled
         for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
             mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
@@ -430,12 +422,6 @@
         mAdapterUuids = null;
         mAdapterSdpHandles = null;
 
-        if (saveSetting) {
-            persistBluetoothOnSetting(false);
-        }
-
-        setBluetoothState(BluetoothAdapter.STATE_OFF);
-
         // Log bluetooth off to battery stats.
         long ident = Binder.clearCallingIdentity();
         try {
@@ -451,6 +437,18 @@
         }
     }
 
+    /**
+     * power off Bluetooth
+     */
+    synchronized void shutoffBluetooth() {
+        tearDownNativeDataNative();
+        disableNative();
+        if (mRestart) {
+            mRestart = false;
+            enable();
+        }
+    }
+
     /** Bring up BT and persist BT on in settings */
     public boolean enable() {
         return enable(true);
@@ -471,21 +469,29 @@
         if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
             return false;
         }
-        if (mBluetoothState != BluetoothAdapter.STATE_OFF) {
+        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
+        return true;
+    }
+
+    /**
+     * Turn on Bluetooth Module, Load firmware, and do all the preparation
+     * needed to get the Bluetooth Module ready but keep it not discoverable
+     * and not connectable.
+     */
+    /* package */ synchronized boolean prepareBluetooth() {
+        if (!setupNativeDataNative()) {
             return false;
         }
-        if (mEnableThread != null && mEnableThread.isAlive()) {
-            return false;
-        }
-        setBluetoothState(BluetoothAdapter.STATE_TURNING_ON);
-        mEnableThread = new EnableThread(saveSetting);
-        mEnableThread.start();
+        mIsDiscovering = false;
+
+        switchConnectable(false);
+        updateSdpRecords();
         return true;
     }
 
     /** Forcibly restart Bluetooth if it is on */
     /* package */ synchronized void restart() {
-        if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
             return;
         }
         mRestart = true;
@@ -494,30 +500,10 @@
         }
     }
 
-    private synchronized void setBluetoothState(int state) {
-        if (state == mBluetoothState) {
-            return;
-        }
-
-        if (DBG) Log.d(TAG, "Bluetooth state " + mBluetoothState + " -> " + state);
-
-        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState);
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
-        mBluetoothState = state;
-
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-            case MESSAGE_FINISH_DISABLE:
-                finishDisable(msg.arg1 != 0);
-                break;
             case MESSAGE_UUID_INTENT:
                 String address = (String)msg.obj;
                 if (address != null) {
@@ -527,74 +513,24 @@
                 break;
             case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
                 address = (String)msg.obj;
-                if (address != null) {
+                if (address == null) return;
+                int attempt = mBondState.getAttempt(address);
+
+                // Try only if attemps are in progress and cap it 2 attempts
+                // The 2 attempts cap is a fail safe if the stack returns
+                // an incorrect error code for bonding failures and if the pin
+                // is entered wrongly twice we should abort.
+                if (attempt > 0 && attempt <= 2) {
+                    mBondState.attempt(address);
                     createBond(address);
                     return;
                 }
+                if (attempt > 0) mBondState.clearPinAttempts(address);
                 break;
             }
         }
     };
 
-    private EnableThread mEnableThread;
-
-    private class EnableThread extends Thread {
-        private final boolean mSaveSetting;
-        public EnableThread(boolean saveSetting) {
-            mSaveSetting = saveSetting;
-        }
-        public void run() {
-            boolean res = (enableNative() == 0);
-            if (res) {
-                int retryCount = 2;
-                boolean running = false;
-                while ((retryCount-- > 0) && !running) {
-                    mEventLoop.start();
-                    // it may take a moment for the other thread to do its
-                    // thing.  Check periodically for a while.
-                    int pollCount = 5;
-                    while ((pollCount-- > 0) && !running) {
-                        if (mEventLoop.isEventLoopRunning()) {
-                            running = true;
-                            break;
-                        }
-                        try {
-                            Thread.sleep(100);
-                        } catch (InterruptedException e) {}
-                    }
-                }
-                if (!running) {
-                    Log.e(TAG, "bt EnableThread giving up");
-                    res = false;
-                    disableNative();
-                }
-            }
-
-            if (res) {
-                if (!setupNativeDataNative()) {
-                    return;
-                }
-                if (mSaveSetting) {
-                    persistBluetoothOnSetting(true);
-                }
-
-                mIsDiscovering = false;
-                mBondState.readAutoPairingData();
-                mBondState.initBondState();
-                initProfileState();
-
-                // This should be the last step of the the enable thread.
-                // Because this adds SDP records which asynchronously
-                // broadcasts the Bluetooth On State in updateBluetoothState.
-                // So we want all internal state setup before this.
-                updateSdpRecords();
-            } else {
-                setBluetoothState(BluetoothAdapter.STATE_OFF);
-            }
-            mEnableThread = null;
-        }
-    }
-
     private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
         //Register SDP records.
         int[] svcIdentifiers = new int[uuids.size()];
@@ -641,38 +577,37 @@
      * for adapter comes in with UUID property.
      * @param uuidsThe uuids of adapter as reported by Bluez.
      */
-    synchronized void updateBluetoothState(String uuids) {
-        if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) {
-            ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
+    /*package*/ synchronized void updateBluetoothState(String uuids) {
+        ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
 
-            if (mAdapterUuids != null &&
-                    BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
-                setBluetoothState(BluetoothAdapter.STATE_ON);
-                autoConnect();
-                String[] propVal = {"Pairable", getProperty("Pairable")};
-                mEventLoop.onPropertyChanged(propVal);
-
-                // Log bluetooth on to battery stats.
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    mBatteryStats.noteBluetoothOn();
-                } catch (RemoteException e) {
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-
-                if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
-                    disable(false);
-                }
-            }
+        if (mAdapterUuids != null &&
+            BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
+            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
         }
     }
 
-    private void persistBluetoothOnSetting(boolean bluetoothOn) {
-        long origCallerIdentityToken = Binder.clearCallingIdentity();
-        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
-                bluetoothOn ? 1 : 0);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);
+    /**
+     * This method is called immediately after Bluetooth module is turned on.
+     * It starts auto-connection and places bluetooth on sign onto the battery
+     * stats
+     */
+    /*package*/ void runBluetooth() {
+        mIsDiscovering = false;
+        mBondState.readAutoPairingData();
+        mBondState.initBondState();
+        initProfileState();
+
+        autoConnect();
+
+        // Log bluetooth on to battery stats.
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteBluetoothOn();
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     /*package*/ synchronized boolean attemptAutoPair(String address) {
@@ -741,7 +676,6 @@
                     BluetoothDevice.BOND_NONE, result);
             return;
         }
-        mBondState.attempt(address);
     }
 
     /*package*/ BluetoothDevice getRemoteDevice(String address) {
@@ -810,6 +744,26 @@
     public synchronized boolean setScanMode(int mode, int duration) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
                                                 "Need WRITE_SECURE_SETTINGS permission");
+        return setScanMode(mode, duration, true);
+    }
+
+    /**
+     * @param on true set the local Bluetooth module to be connectable
+     *                but not dicoverable
+     *           false set the local Bluetooth module to be not connectable
+     *                 and not dicoverable
+     */
+    /*package*/ synchronized void switchConnectable(boolean on) {
+        if (on) {
+            // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
+            setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
+        } else {
+            // 0 is a dummy value, does not apply for SCAN_MODE_NONE
+            setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
+        }
+    }
+
+    private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
         boolean pairable;
         boolean discoverable;
 
@@ -831,9 +785,15 @@
             Log.w(TAG, "Requested invalid scan mode " + mode);
             return false;
         }
-        setPropertyBoolean("Pairable", pairable);
-        setPropertyBoolean("Discoverable", discoverable);
 
+        if (allowOnlyInOnState) {
+            setPropertyBoolean("Pairable", pairable);
+            setPropertyBoolean("Discoverable", discoverable);
+        } else {
+            // allowed to set the property through native layer directly
+            setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0);
+            setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0);
+        }
         return true;
     }
 
@@ -1514,7 +1474,7 @@
         int pid = Binder.getCallingPid();
         mServiceRecordToPid.put(new Integer(handle), new Integer(pid));
         try {
-            b.linkToDeath(new Reaper(handle, pid), 0);
+            b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0);
         } catch (RemoteException e) {}
         return handle;
     }
@@ -1537,20 +1497,85 @@
     }
 
     private class Reaper implements IBinder.DeathRecipient {
-        int pid;
-        int handle;
-        Reaper(int handle, int pid) {
-            this.pid = pid;
-            this.handle = handle;
+        int mPid;
+        int mHandle;
+        int mType;
+
+        Reaper(int handle, int pid, int type) {
+            mPid = pid;
+            mHandle = handle;
+            mType = type;
         }
+
+        Reaper(int pid, int type) {
+            mPid = pid;
+            mType = type;
+        }
+
+        @Override
         public void binderDied() {
             synchronized (BluetoothService.this) {
-                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
-                checkAndRemoveRecord(handle, pid);
+                if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType);
+                if (mType == RFCOMM_RECORD_REAPER) {
+                    checkAndRemoveRecord(mHandle, mPid);
+                } else if (mType == STATE_CHANGE_REAPER) {
+                    mStateChangeTracker.remove(mPid);
+                }
             }
         }
     }
 
+
+    @Override
+    public boolean changeApplicationBluetoothState(boolean on,
+            IBluetoothStateChangeCallback callback, IBinder binder) {
+        int pid = Binder.getCallingPid();
+        //mStateChangeTracker is a synchronized map
+        if (!mStateChangeTracker.containsKey(pid)) {
+            if (on) {
+                mStateChangeTracker.put(pid, callback);
+            } else {
+                return false;
+            }
+        } else if (!on) {
+            mStateChangeTracker.remove(pid);
+        }
+
+        if (binder != null) {
+            try {
+                binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0);
+            } catch (RemoteException e) {
+                return false;
+            }
+        }
+
+        int type;
+        if (on) {
+            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON;
+        } else {
+            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF;
+        }
+
+        mBluetoothState.sendMessage(type, callback);
+        return true;
+    }
+
+    boolean isApplicationStateChangeTrackerEmpty() {
+        return mStateChangeTracker.isEmpty();
+    }
+
+    void clearApplicationStateChangeTracker() {
+        mStateChangeTracker.clear();
+    }
+
+    Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() {
+        return mStateChangeTracker.values();
+    }
+
+    int getNumberOfApplicationStateChangeTrackers() {
+        return mStateChangeTracker.size();
+    }
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -1561,14 +1586,10 @@
                 ContentResolver resolver = context.getContentResolver();
                 // Query the airplane mode from Settings.System just to make sure that
                 // some random app is not sending this intent and disabling bluetooth
-                boolean enabled = !isAirplaneModeOn();
-                // If bluetooth is currently expected to be on, then enable or disable bluetooth
-                if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
-                    if (enabled) {
-                        enable(false);
-                    } else {
-                        disable(false);
-                    }
+                if (isAirplaneModeOn()) {
+                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
+                } else {
+                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
                 }
             } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
                 int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -1642,8 +1663,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        dumpBluetoothState(pw);
-        if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
             return;
         }
 
@@ -1832,25 +1852,6 @@
         }
     }
 
-    private void dumpBluetoothState(PrintWriter pw) {
-        switch(mBluetoothState) {
-        case BluetoothAdapter.STATE_OFF:
-            pw.println("Bluetooth OFF\n");
-            break;
-        case BluetoothAdapter.STATE_TURNING_ON:
-            pw.println("Bluetooth TURNING ON\n");
-            break;
-        case BluetoothAdapter.STATE_TURNING_OFF:
-            pw.println("Bluetooth TURNING OFF\n");
-            break;
-        case BluetoothAdapter.STATE_ON:
-            pw.println("Bluetooth ON\n");
-            break;
-        default:
-            pw.println("Bluetooth UNKNOWN STATE " + mBluetoothState);
-        }
-    }
-
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -2277,11 +2278,11 @@
         return false;
     }
 
-    BluetoothDeviceProfileState addProfileState(String address) {
+    BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) {
         BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
         if (state != null) return state;
 
-        state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService);
+        state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
         mDeviceProfileState.put(address, state);
         state.start();
         return state;
@@ -2311,7 +2312,7 @@
         }
         for (String path : bonds) {
             String address = getAddressFromObjectPath(path);
-            BluetoothDeviceProfileState state = addProfileState(address);
+            BluetoothDeviceProfileState state = addProfileState(address, false);
         }
     }
 
@@ -2381,7 +2382,7 @@
     public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
                                                         int prevState) {
         // Since this is a binder call check if Bluetooth is on still
-        if (mBluetoothState == BluetoothAdapter.STATE_OFF) return;
+        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
 
         if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
             if (!validateProfileConnectionState(state) ||
@@ -2397,6 +2398,10 @@
 
             mAdapterConnectionState = state;
 
+            if (state == BluetoothProfile.STATE_DISCONNECTED) {
+                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
+            }
+
             Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
             intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
@@ -2590,8 +2595,8 @@
     /*package*/ native String getAdapterPathNative();
 
     private native int isEnabledNative();
-    private native int enableNative();
-    private native int disableNative();
+    /*package*/ native int enableNative();
+    /*package*/ native int disableNative();
 
     /*package*/ native Object[] getAdapterPropertiesNative();
     private native Object[] getDevicePropertiesNative(String objectPath);
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
new file mode 100644
index 0000000..270f512
--- /dev/null
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.service.textservice;
+
+import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * SpellCheckerService provides an abstract base class for a spell checker.
+ * This class combines a service to the system with the spell checker service interface that
+ * spell checker must implement.
+ */
+public abstract class SpellCheckerService extends Service {
+    private static final String TAG = SpellCheckerService.class.getSimpleName();
+    public static final String SERVICE_INTERFACE =
+            "android.service.textservice.SpellCheckerService";
+
+    private final SpellCheckerServiceBinder mBinder = new SpellCheckerServiceBinder(this);
+
+    /**
+     * Get suggestions for specified text in TextInfo.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     * @param textInfo the text metadata
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param locale the locale for getting suggestions
+     * @return SuggestionInfo which contains suggestions for textInfo
+     */
+    public abstract SuggestionsInfo getSuggestions(
+            TextInfo textInfo, int suggestionsLimit, String locale);
+
+    /**
+     * A batch process of onGetSuggestions.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     * @param textInfos an array of the text metadata
+     * @param locale the locale for getting suggestions
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param sequentialWords true if textInfos can be treated as sequential words.
+     * @return an array of SuggestionInfo of onGetSuggestions
+     */
+    public SuggestionsInfo[] getSuggestionsMultiple(
+            TextInfo[] textInfos, String locale, int suggestionsLimit, boolean sequentialWords) {
+        final int length = textInfos.length;
+        final SuggestionsInfo[] retval = new SuggestionsInfo[length];
+        for (int i = 0; i < length; ++i) {
+            retval[i] = getSuggestions(textInfos[i], suggestionsLimit, locale);
+            retval[i].setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence());
+        }
+        return retval;
+    }
+
+    /**
+     * Request to abort all tasks executed in SpellChecker.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     */
+    public void cancel() {}
+
+    /**
+     * Implement to return the implementation of the internal spell checker
+     * service interface. Subclasses should not override.
+     */
+    @Override
+    public final IBinder onBind(final Intent intent) {
+        return mBinder;
+    }
+
+    private static class SpellCheckerSessionImpl extends ISpellCheckerSession.Stub {
+        private final WeakReference<SpellCheckerService> mInternalServiceRef;
+        private final String mLocale;
+        private final ISpellCheckerSessionListener mListener;
+
+        public SpellCheckerSessionImpl(
+                SpellCheckerService service, String locale, ISpellCheckerSessionListener listener) {
+            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
+            mLocale = locale;
+            mListener = listener;
+        }
+
+        @Override
+        public void getSuggestionsMultiple(
+                TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return;
+            try {
+                mListener.onGetSuggestions(
+                        service.getSuggestionsMultiple(textInfos, mLocale,
+                                suggestionsLimit, sequentialWords));
+            } catch (RemoteException e) {
+            }
+        }
+
+        @Override
+        public void cancel() {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return;
+            service.cancel();
+        }
+    }
+
+    private static class SpellCheckerServiceBinder extends ISpellCheckerService.Stub {
+        private final WeakReference<SpellCheckerService> mInternalServiceRef;
+
+        public SpellCheckerServiceBinder(SpellCheckerService service) {
+            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
+        }
+
+        @Override
+        public ISpellCheckerSession getISpellCheckerSession(
+                String locale, ISpellCheckerSessionListener listener) {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return null;
+            return new SpellCheckerSessionImpl(service, locale, listener);
+        }
+    }
+}
diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/service/textservice/SpellCheckerSession.java
new file mode 100644
index 0000000..400454d
--- /dev/null
+++ b/core/java/android/service/textservice/SpellCheckerSession.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Queue;
+
+/**
+ * The SpellCheckerSession interface provides the per client functionality of SpellCheckerService.
+ */
+public class SpellCheckerSession {
+    private static final String TAG = SpellCheckerSession.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1;
+
+    private final InternalListener mInternalListener;
+    private final ITextServicesManager mTextServicesManager;
+    private final SpellCheckerInfo mSpellCheckerInfo;
+    private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
+
+    private boolean mIsUsed;
+    private SpellCheckerSessionListener mSpellCheckerSessionListener;
+
+    /** Handler that will execute the main tasks */
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_GET_SUGGESTION_MULTIPLE:
+                    handleOnGetSuggestionsMultiple((SuggestionsInfo[]) msg.obj);
+                    break;
+            }
+        }
+    };
+
+    /**
+     * Constructor
+     * @hide
+     */
+    public SpellCheckerSession(
+            SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener) {
+        if (info == null || listener == null || tsm == null) {
+            throw new NullPointerException();
+        }
+        mSpellCheckerInfo = info;
+        mSpellCheckerSessionListenerImpl = new SpellCheckerSessionListenerImpl(mHandler);
+        mInternalListener = new InternalListener();
+        mTextServicesManager = tsm;
+        mIsUsed = true;
+        mSpellCheckerSessionListener = listener;
+    }
+
+    /**
+     * @return true if the connection to a text service of this session is disconnected and not
+     * alive.
+     */
+    public boolean isSessionDisconnected() {
+        return mSpellCheckerSessionListenerImpl.isDisconnected();
+    }
+
+    /**
+     * Get the spell checker service info this spell checker session has.
+     * @return SpellCheckerInfo for the specified locale.
+     */
+    public SpellCheckerInfo getSpellChecker() {
+        return mSpellCheckerInfo;
+    }
+
+    /**
+     * Finish this session and allow TextServicesManagerService to disconnect the bound spell
+     * checker.
+     */
+    public void close() {
+        mIsUsed = false;
+        try {
+            mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl);
+        } catch (RemoteException e) {
+            // do nothing
+        }
+    }
+
+    /**
+     * Get candidate strings for a substring of the specified text.
+     * @param textInfo text metadata for a spell checker
+     * @param suggestionsLimit the number of limit of suggestions returned
+     */
+    public void getSuggestions(TextInfo textInfo, int suggestionsLimit) {
+        getSuggestions(new TextInfo[] {textInfo}, suggestionsLimit, false);
+    }
+
+    /**
+     * A batch process of getSuggestions
+     * @param textInfos an array of text metadata for a spell checker
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param sequentialWords true if textInfos can be treated as sequential words.
+     */
+    public void getSuggestions(
+            TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+        // TODO: Handle multiple words suggestions by using WordBreakIterator
+        mSpellCheckerSessionListenerImpl.getSuggestionsMultiple(
+                textInfos, suggestionsLimit, sequentialWords);
+    }
+
+    private void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionInfos) {
+        mSpellCheckerSessionListener.onGetSuggestions(suggestionInfos);
+    }
+
+    private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub {
+        private static final int TASK_CANCEL = 1;
+        private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2;
+        private final Queue<SpellCheckerParams> mPendingTasks =
+                new LinkedList<SpellCheckerParams>();
+        private final Handler mHandler;
+
+        private boolean mOpened;
+        private ISpellCheckerSession mISpellCheckerSession;
+
+        public SpellCheckerSessionListenerImpl(Handler handler) {
+            mOpened = false;
+            mHandler = handler;
+        }
+
+        private static class SpellCheckerParams {
+            public final int mWhat;
+            public final TextInfo[] mTextInfos;
+            public final int mSuggestionsLimit;
+            public final boolean mSequentialWords;
+            public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit,
+                    boolean sequentialWords) {
+                mWhat = what;
+                mTextInfos = textInfos;
+                mSuggestionsLimit = suggestionsLimit;
+                mSequentialWords = sequentialWords;
+            }
+        }
+
+        private void processTask(SpellCheckerParams scp) {
+            switch (scp.mWhat) {
+                case TASK_CANCEL:
+                    processCancel();
+                    break;
+                case TASK_GET_SUGGESTIONS_MULTIPLE:
+                    processGetSuggestionsMultiple(scp);
+                    break;
+            }
+        }
+
+        public synchronized void onServiceConnected(ISpellCheckerSession session) {
+            mISpellCheckerSession = session;
+            mOpened = true;
+            if (DBG)
+                Log.d(TAG, "onServiceConnected - Success");
+            while (!mPendingTasks.isEmpty()) {
+                processTask(mPendingTasks.poll());
+            }
+        }
+
+        public void getSuggestionsMultiple(
+                TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+            processOrEnqueueTask(
+                    new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos,
+                            suggestionsLimit, sequentialWords));
+        }
+
+        public boolean isDisconnected() {
+            return mOpened && mISpellCheckerSession == null;
+        }
+
+        public boolean checkOpenConnection() {
+            if (mISpellCheckerSession != null) {
+                return true;
+            }
+            Log.e(TAG, "not connected to the spellchecker service.");
+            return false;
+        }
+
+        private void processOrEnqueueTask(SpellCheckerParams scp) {
+            if (mISpellCheckerSession == null) {
+                mPendingTasks.offer(scp);
+            } else {
+                processTask(scp);
+            }
+        }
+
+        private void processCancel() {
+            if (!checkOpenConnection()) {
+                return;
+            }
+            try {
+                mISpellCheckerSession.cancel();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to cancel " + e);
+            }
+        }
+
+        private void processGetSuggestionsMultiple(SpellCheckerParams scp) {
+            if (!checkOpenConnection()) {
+                return;
+            }
+            try {
+                mISpellCheckerSession.getSuggestionsMultiple(
+                        scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to get suggestions " + e);
+            }
+        }
+
+        @Override
+        public void onGetSuggestions(SuggestionsInfo[] results) {
+            mHandler.sendMessage(Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE, results));
+        }
+    }
+
+    /**
+     * Callback for getting results from text services
+     */
+    public interface SpellCheckerSessionListener {
+        /**
+         * Callback for "getSuggestions"
+         * @param results an array of results of getSuggestions
+         */
+        public void onGetSuggestions(SuggestionsInfo[] results);
+    }
+
+    private class InternalListener extends ITextServicesSessionListener.Stub {
+        @Override
+        public void onServiceConnected(ISpellCheckerSession session) {
+            mSpellCheckerSessionListenerImpl.onServiceConnected(session);
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        if (mIsUsed) {
+            Log.e(TAG, "SpellCheckerSession was not finished properly." +
+                    "You should call finishShession() when you finished to use a spell checker.");
+            close();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public ITextServicesSessionListener getTextServicesSessionListener() {
+        return mInternalListener;
+    }
+
+    /**
+     * @hide
+     */
+    public ISpellCheckerSessionListener getSpellCheckerSessionListener() {
+        return mSpellCheckerSessionListenerImpl;
+    }
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 8fc8b9d..c51ba2a 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -51,7 +51,7 @@
 import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
@@ -650,7 +650,7 @@
             mWindowToken = wrapper.mWindowToken;
             mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
-            mSession = ViewAncestor.getWindowSession(getMainLooper());
+            mSession = ViewRootImpl.getWindowSession(getMainLooper());
             
             mWindow.setSession(mSession);
             
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 1210941..89b6f32 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -17,6 +17,7 @@
 
 import android.media.AudioFormat;
 import android.media.AudioTrack;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.Iterator;
@@ -25,14 +26,14 @@
 
 class AudioPlaybackHandler {
     private static final String TAG = "TTS.AudioPlaybackHandler";
+    private static final boolean DBG_THREADING = false;
     private static final boolean DBG = false;
 
     private static final int MIN_AUDIO_BUFFER_SIZE = 8192;
 
     private static final int SYNTHESIS_START = 1;
     private static final int SYNTHESIS_DATA_AVAILABLE = 2;
-    private static final int SYNTHESIS_COMPLETE_DATA_AVAILABLE = 3;
-    private static final int SYNTHESIS_DONE = 4;
+    private static final int SYNTHESIS_DONE = 3;
 
     private static final int PLAY_AUDIO = 5;
     private static final int PLAY_SILENCE = 6;
@@ -65,74 +66,105 @@
      * Stops all synthesis for a given {@code token}. If the current token
      * is currently being processed, an effort will be made to stop it but
      * that is not guaranteed.
+     *
+     * NOTE: This assumes that all other messages in the queue with {@code token}
+     * have been removed already.
+     *
+     * NOTE: Must be called synchronized on {@code AudioPlaybackHandler.this}.
      */
-    synchronized public void stop(MessageParams token) {
+    private void stop(MessageParams token) {
         if (token == null) {
             return;
         }
 
-        removeMessages(token);
+        if (DBG) Log.d(TAG, "Stopping token : " + 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.
+                // The audio track is thread safe in this regard. The current
+                // handleSynthesisDataAvailable call will return soon after this
+                // call.
                 current.stop();
             }
+            // This is safe because PlaybackSynthesisCallback#stop would have
+            // been called before this method, and will no longer enqueue any
+            // audio for this token.
+            //
+            // (Even if it did, all it would result in is a warning message).
             mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY));
-        } else  {
-            final MessageParams current = getCurrentParams();
-
-            if (current != null) {
-                if (token.getType() == MessageParams.TYPE_AUDIO) {
-                    ((AudioMessageParams) current).getPlayer().stop();
-                } else if (token.getType() == MessageParams.TYPE_SILENCE) {
-                    ((SilenceMessageParams) current).getConditionVariable().open();
-                }
-            }
+        } else if (token.getType() == MessageParams.TYPE_AUDIO) {
+            ((AudioMessageParams) token).getPlayer().stop();
+            // No cleanup required for audio messages.
+        } else if (token.getType() == MessageParams.TYPE_SILENCE) {
+            ((SilenceMessageParams) token).getConditionVariable().open();
+            // No cleanup required for silence messages.
         }
     }
 
+    // -----------------------------------------------------
+    // Methods that add and remove elements from the queue. These do not
+    // need to be synchronized strictly speaking, but they make the behaviour
+    // a lot more predictable. (though it would still be correct without
+    // synchronization).
+    // -----------------------------------------------------
+
     synchronized public void removePlaybackItems(String callingApp) {
+        if (DBG_THREADING) Log.d(TAG, "Removing all callback items for : " + callingApp);
         removeMessages(callingApp);
-        stop(getCurrentParams());
+
+        final MessageParams current = getCurrentParams();
+        if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
+            stop(current);
+        }
     }
 
     synchronized public void removeAllItems() {
+        if (DBG_THREADING) Log.d(TAG, "Removing all items");
         removeAllMessages();
         stop(getCurrentParams());
     }
 
     /**
+     * @return false iff the queue is empty and no queue item is currently
+     *        being handled, true otherwise.
+     */
+    public boolean isSpeaking() {
+        return (mQueue.peek() != null) || (mCurrentParams != null);
+    }
+
+    /**
      * Shut down the audio playback thread.
      */
     synchronized public void quit() {
+        removeAllMessages();
         stop(getCurrentParams());
         mQueue.add(new ListEntry(SHUTDOWN, null, HIGH_PRIORITY));
     }
 
-    void enqueueSynthesisStart(SynthesisMessageParams token) {
+    synchronized void enqueueSynthesisStart(SynthesisMessageParams token) {
+        if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis start : " + token);
         mQueue.add(new ListEntry(SYNTHESIS_START, token));
     }
 
-    void enqueueSynthesisDataAvailable(SynthesisMessageParams token) {
+    synchronized void enqueueSynthesisDataAvailable(SynthesisMessageParams token) {
+        if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis data available : " + token);
         mQueue.add(new ListEntry(SYNTHESIS_DATA_AVAILABLE, token));
     }
 
-    void enqueueSynthesisCompleteDataAvailable(SynthesisMessageParams token) {
-        mQueue.add(new ListEntry(SYNTHESIS_COMPLETE_DATA_AVAILABLE, token));
-    }
-
-    void enqueueSynthesisDone(SynthesisMessageParams token) {
+    synchronized void enqueueSynthesisDone(SynthesisMessageParams token) {
+        if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis done : " + token);
         mQueue.add(new ListEntry(SYNTHESIS_DONE, token));
     }
 
-    void enqueueAudio(AudioMessageParams token) {
+    synchronized void enqueueAudio(AudioMessageParams token) {
+        if (DBG_THREADING) Log.d(TAG, "Enqueuing audio : " + token);
         mQueue.add(new ListEntry(PLAY_AUDIO, token));
     }
 
-    void enqueueSilence(SilenceMessageParams token) {
+    synchronized void enqueueSilence(SilenceMessageParams token) {
+        if (DBG_THREADING) Log.d(TAG, "Enqueuing silence : " + token);
         mQueue.add(new ListEntry(PLAY_SILENCE, token));
     }
 
@@ -177,26 +209,6 @@
     }
 
     /*
-     * Remove all messages from the queue that contain the supplied token.
-     * Note that the Iterator is thread safe, and other methods can safely
-     * continue adding to the queue at this point.
-     */
-    synchronized private void removeMessages(MessageParams token) {
-        if (token == null) {
-            return;
-        }
-
-        Iterator<ListEntry> it = mQueue.iterator();
-
-        while (it.hasNext()) {
-            final ListEntry current = it.next();
-            if (current.mMessage == token) {
-                it.remove();
-            }
-        }
-    }
-
-    /*
      * Atomically clear the queue of all messages.
      */
     synchronized private void removeAllMessages() {
@@ -260,6 +272,13 @@
     }
 
     private void setCurrentParams(MessageParams p) {
+        if (DBG_THREADING) {
+            if (p != null) {
+                Log.d(TAG, "Started handling :" + p);
+            } else {
+                Log.d(TAG, "End handling : " + mCurrentParams);
+            }
+        }
         mCurrentParams = p;
     }
 
@@ -280,8 +299,6 @@
             handleSynthesisDataAvailable(msg);
         } else if (entry.mWhat == SYNTHESIS_DONE) {
             handleSynthesisDone(msg);
-        } else if (entry.mWhat == SYNTHESIS_COMPLETE_DATA_AVAILABLE) {
-            handleSynthesisCompleteDataAvailable(msg);
         } else if (entry.mWhat == PLAY_AUDIO) {
             handleAudio(msg);
         } else if (entry.mWhat == PLAY_SILENCE) {
@@ -339,9 +356,7 @@
         mLastSynthesisRequest = param;
 
         // Create the audio track.
-        final AudioTrack audioTrack = createStreamingAudioTrack(
-                param.mStreamType, param.mSampleRateInHz, param.mAudioFormat,
-                param.mChannelCount, param.mVolume, param.mPan);
+        final AudioTrack audioTrack = createStreamingAudioTrack(param);
 
         if (DBG) Log.d(TAG, "Created audio track [" + audioTrack.hashCode() + "]");
 
@@ -352,7 +367,7 @@
     private void handleSynthesisDataAvailable(MessageParams msg) {
         final SynthesisMessageParams param = (SynthesisMessageParams) msg;
         if (param.getAudioTrack() == null) {
-            Log.w(TAG, "Error : null audio track in handleDataAvailable.");
+            Log.w(TAG, "Error : null audio track in handleDataAvailable : " + param);
             return;
         }
 
@@ -388,126 +403,101 @@
         param.mLogger.onPlaybackStart();
     }
 
+    // Wait for the audio track to stop playing, and then release its resources.
     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();
-    }
 
-    // Wait for the audio track to stop playing, and then release it's resources.
-    private void handleSynthesisDone(SynthesisMessageParams params) {
         if (DBG) Log.d(TAG, "handleSynthesisDone()");
         final AudioTrack audioTrack = params.getAudioTrack();
 
-        try {
-            if (audioTrack != null) {
-                if (DBG) Log.d(TAG, "Waiting for audio track to complete : " +
-                        audioTrack.hashCode());
-                blockUntilDone(params);
-                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 {
-            params.setAudioTrack(null);
-            params.getDispatcher().dispatchUtteranceCompleted();
-            mLastSynthesisRequest = null;
+        if (audioTrack == null) {
+            return;
         }
+
+        if (params.mBytesWritten < params.mAudioBufferSize) {
+            audioTrack.stop();
+        }
+
+        if (DBG) Log.d(TAG, "Waiting for audio track to complete : " +
+                audioTrack.hashCode());
+        blockUntilDone(params);
+        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. Make sure release() and the call
+        // that set the audio track to null are performed atomically.
+        synchronized (this) {
+            // Never allow the audioTrack to be observed in a state where
+            // it is released but non null. The only case this might happen
+            // is in the various stopFoo methods that call AudioTrack#stop from
+            // different threads, but they are synchronized on AudioPlayBackHandler#this
+            // too.
+            audioTrack.release();
+            params.setAudioTrack(null);
+        }
+        params.getDispatcher().dispatchUtteranceCompleted();
+        mLastSynthesisRequest = null;
+        params.mLogger.onWriteData();
     }
 
+    /**
+     * The minimum increment of time to wait for an audiotrack to finish
+     * playing.
+     */
+    private static final long MIN_SLEEP_TIME_MS = 20;
+
     private static void blockUntilDone(SynthesisMessageParams params) {
         if (params.mAudioTrack == null || params.mBytesWritten <= 0) {
             return;
         }
 
-        final AudioTrack track = params.mAudioTrack;
+        final AudioTrack audioTrack = params.mAudioTrack;
         final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat);
         final int lengthInBytes = params.mBytesWritten;
+        final int lengthInFrames = lengthInBytes / bytesPerFrame;
 
-        blockUntilDone(track, bytesPerFrame, lengthInBytes);
-    }
-
-    private void handleSynthesisCompleteDataAvailable(MessageParams msg) {
-        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);
-        int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(params.mAudioFormat);
-
-        SynthesisMessageParams.ListEntry entry = params.getNextBuffer();
-
-        if (entry == null) {
-            Log.w(TAG, "completeDataAvailable : No buffers available to play.");
-            return;
-        }
-
-        final AudioTrack audioTrack = new AudioTrack(params.mStreamType, params.mSampleRateInHz,
-                channelConfig, params.mAudioFormat, entry.mLength, AudioTrack.MODE_STATIC);
-
-        // So that handleDone can access this correctly.
-        params.mAudioTrack = audioTrack;
-
-        try {
-            audioTrack.write(entry.mBytes, entry.mOffset, entry.mLength);
-            setupVolume(audioTrack, params.mVolume, params.mPan);
-            audioTrack.play();
-            blockUntilDone(audioTrack, bytesPerFrame, entry.mLength);
-            if (DBG) Log.d(TAG, "Wrote data to audio track successfully : " + entry.mLength);
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "Playback error", ex);
-        } finally {
-            handleSynthesisDone(msg);
-        }
-    }
-
-
-    private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame,
-            int lengthInBytes) {
-        int lengthInFrames = lengthInBytes / bytesPerFrame;
         int currentPosition = 0;
         while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {
             if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
                 break;
             }
 
-            long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) /
+            final long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) /
                     audioTrack.getSampleRate();
 
-            if (DBG) Log.d(TAG, "About to sleep for : " + estimatedTimeMs + " ms," +
-                    " Playback position : " + currentPosition);
+            final long sleepTimeMs = Math.max(estimatedTimeMs, MIN_SLEEP_TIME_MS);
+
+            if (DBG) Log.d(TAG, "About to sleep for : " + sleepTimeMs + " ms," +
+                    " Playback position : " + currentPosition + ", Length in frames : "
+                    + lengthInFrames);
             try {
-                Thread.sleep(estimatedTimeMs);
+                Thread.sleep(sleepTimeMs);
             } catch (InterruptedException ie) {
                 break;
             }
         }
     }
 
-    private static AudioTrack createStreamingAudioTrack(int streamType, int sampleRateInHz,
-            int audioFormat, int channelCount, float volume, float pan) {
-        int channelConfig = getChannelConfig(channelCount);
+    private static AudioTrack createStreamingAudioTrack(SynthesisMessageParams params) {
+        final int channelConfig = getChannelConfig(params.mChannelCount);
+        final int sampleRateInHz = params.mSampleRateInHz;
+        final int audioFormat = params.mAudioFormat;
 
         int minBufferSizeInBytes
                 = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
         int bufferSizeInBytes = Math.max(MIN_AUDIO_BUFFER_SIZE, minBufferSizeInBytes);
 
-        AudioTrack audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig,
+        AudioTrack audioTrack = new AudioTrack(params.mStreamType, sampleRateInHz, channelConfig,
                 audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM);
         if (audioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
             Log.w(TAG, "Unable to create audio track.");
             audioTrack.release();
             return null;
         }
+        params.mAudioBufferSize = bufferSizeInBytes;
 
-        setupVolume(audioTrack, volume, pan);
+        setupVolume(audioTrack, params.mVolume, params.mPan);
         return audioTrack;
     }
 
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 4f4b3fb..5808919 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -187,37 +187,6 @@
         }
     }
 
-    @Override
-    public int completeAudioAvailable(int sampleRateInHz, int audioFormat, int channelCount,
-            byte[] buffer, int offset, int length) {
-        synchronized (mStateLock) {
-            if (mStopped) {
-                if (DBG) Log.d(TAG, "Request has been aborted.");
-                return TextToSpeech.ERROR;
-            }
-        }
-        FileOutputStream out = null;
-        try {
-            out = new FileOutputStream(mFileName);
-            out.write(makeWavHeader(sampleRateInHz, audioFormat, channelCount, length));
-            out.write(buffer, offset, length);
-            mDone = true;
-            return TextToSpeech.SUCCESS;
-        } catch (IOException ex) {
-            Log.e(TAG, "Failed to write to " + mFileName + ": " + ex);
-            mFileName.delete();
-            return TextToSpeech.ERROR;
-        } finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-            } catch (IOException ex) {
-                Log.e(TAG, "Failed to close " + mFileName + ": " + ex);
-            }
-        }
-    }
-
     private byte[] makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
             int dataLength) {
         // TODO: is AudioFormat.ENCODING_DEFAULT always the same as ENCODING_PCM_16BIT?
diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java
index 4c1b6d2..e7d6da3 100644
--- a/core/java/android/speech/tts/MessageParams.java
+++ b/core/java/android/speech/tts/MessageParams.java
@@ -38,5 +38,10 @@
         return mCallingApp;
     }
 
+    @Override
+    public String toString() {
+        return "MessageParams[" + hashCode() + "]";
+    }
+
     abstract int getType();
 }
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index 38030a6..7dbf1ac 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -53,8 +53,7 @@
 
     // Handler associated with a thread that plays back audio requests.
     private final AudioPlaybackHandler mAudioTrackHandler;
-    // A request "token", which will be non null after start() or
-    // completeAudioAvailable() have been called.
+    // A request "token", which will be non null after start() has been called.
     private SynthesisMessageParams mToken = null;
     // Whether this request has been stopped. This is useful for keeping
     // track whether stop() has been called before start(). In all other cases,
@@ -91,12 +90,10 @@
                 Log.w(TAG, "stop() called twice");
                 return;
             }
+
             // mToken will be null if the engine encounters
             // an error before it called start().
-            if (mToken != null) {
-                mAudioTrackHandler.stop(mToken);
-                mToken = null;
-            } else {
+            if (mToken == null) {
                 // In all other cases, mAudioTrackHandler.stop() will
                 // result in onComplete being called.
                 mLogger.onWriteData();
@@ -159,7 +156,7 @@
         }
 
         synchronized (mStateLock) {
-            if (mToken == null) {
+            if (mToken == null || mStopped) {
                 return TextToSpeech.ERROR;
             }
 
@@ -206,35 +203,4 @@
         stop();
     }
 
-    @Override
-    public int completeAudioAvailable(int sampleRateInHz, int audioFormat, int channelCount,
-            byte[] buffer, int offset, int length) {
-        int channelConfig = AudioPlaybackHandler.getChannelConfig(channelCount);
-        if (channelConfig == 0) {
-            Log.e(TAG, "Unsupported number of channels :" + channelCount);
-            return TextToSpeech.ERROR;
-        }
-
-        int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(audioFormat);
-        if (bytesPerFrame < 0) {
-            Log.e(TAG, "Unsupported audio format :" + audioFormat);
-            return TextToSpeech.ERROR;
-        }
-
-        synchronized (mStateLock) {
-            if (mStopped) {
-                return TextToSpeech.ERROR;
-            }
-            SynthesisMessageParams params = new SynthesisMessageParams(
-                    mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
-                    mDispatcher, mCallingApp, mLogger);
-            params.addBuffer(buffer, offset, length);
-
-            mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
-            mToken = params;
-        }
-
-        return TextToSpeech.SUCCESS;
-    }
-
 }
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index 1b80e40..d70c371d 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -22,19 +22,16 @@
  * {@link #start}, then {@link #audioAvailable} until all audio has been provided, then finally
  * {@link #done}.
  *
- * Alternatively, the engine can provide all the audio at once, by using
- * {@link #completeAudioAvailable}.
  *
  * {@link #error} can be called at any stage in the synthesis process to
- * indicate that an error has occured, but if the call is made after a call
- * to {@link #done} or {@link #completeAudioAvailable} it might be discarded.
+ * indicate that an error has occurred, but if the call is made after a call
+ * to {@link #done}, it might be discarded.
  */
 public interface SynthesisCallback {
     /**
      * @return the maximum number of bytes that the TTS engine can pass in a single call of
-     *         {@link #audioAvailable}. This does not apply to {@link #completeAudioAvailable}.
-     *         Calls to {@link #audioAvailable} with data lengths larger than this
-     *         value will not succeed.
+     *         {@link #audioAvailable}. Calls to {@link #audioAvailable} with data lengths
+     *         larger than this value will not succeed.
      */
     public int getMaxBufferSize();
 
@@ -69,23 +66,6 @@
     public int audioAvailable(byte[] buffer, int offset, int length);
 
     /**
-     * The service can call this method instead of using {@link #start}, {@link #audioAvailable}
-     * and {@link #done} if all the audio data is available in a single buffer.
-     *
-     * @param sampleRateInHz Sample rate in HZ of the generated audio.
-     * @param audioFormat Audio format of the generated audio. Must be one of
-     *         the ENCODING_ constants defined in {@link android.media.AudioFormat}.
-     * @param channelCount The number of channels. Must be {@code 1} or {@code 2}.
-     * @param buffer The generated audio data. This method will not hold on to {@code buffer},
-     *         so the caller is free to modify it after this method returns.
-     * @param offset The offset into {@code buffer} where the audio data starts.
-     * @param length The number of bytes of audio data in {@code buffer}.
-     * @return {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
-     */
-    public int completeAudioAvailable(int sampleRateInHz, int audioFormat,
-            int channelCount, byte[] buffer, int offset, int length);
-
-    /**
      * The service should call this method when all the synthesized audio for a request has
      * been passed to {@link #audioAvailable}.
      *
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index ffe70e2..7da5daa 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -35,6 +35,7 @@
     volatile AudioTrack mAudioTrack;
     // Not volatile, accessed only from the synthesis thread.
     int mBytesWritten;
+    int mAudioBufferSize;
 
     private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
 
@@ -55,6 +56,7 @@
         // initially null.
         mAudioTrack = null;
         mBytesWritten = 0;
+        mAudioBufferSize = 0;
     }
 
     @Override
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 8e4725f..5126e48 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -109,6 +109,11 @@
     /**
      * Broadcast Action: The TextToSpeech synthesizer has completed processing
      * of all the text in the speech queue.
+     *
+     * Note that this notifies callers when the <b>engine</b> has finished has
+     * processing text data. Audio playback might not have completed (or even started)
+     * at this point. If you wish to be notified when this happens, see
+     * {@link OnUtteranceCompletedListener}.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
@@ -181,7 +186,7 @@
          *
          * @hide
          * @deprecated No longer in use, the default engine is determined by
-         *         the sort order defined in {@link EngineInfoComparator}. Note that
+         *         the sort order defined in {@link TtsEngines}. Note that
          *         this doesn't "break" anything because there is no guarantee that
          *         the engine specified below is installed on a given build, let
          *         alone be the default.
@@ -504,36 +509,39 @@
     }
 
     private int initTts() {
-        String defaultEngine = getDefaultEngine();
-        String engine = defaultEngine;
-        if (mEnginesHelper.isEngineInstalled(mRequestedEngine)) {
-            engine = mRequestedEngine;
+        // Step 1: Try connecting to the engine that was requested.
+        if (mRequestedEngine != null && mEnginesHelper.isEngineInstalled(mRequestedEngine)) {
+            if (connectToEngine(mRequestedEngine)) {
+                mCurrentEngine = mRequestedEngine;
+                return SUCCESS;
+            }
         }
 
-        // Try requested engine
-        if (connectToEngine(engine)) {
-            mCurrentEngine = engine;
-            return SUCCESS;
-        }
-
-        // Fall back to user's default engine if different from the already tested one
-        if (!engine.equals(defaultEngine)) {
+        // Step 2: Try connecting to the user's default engine.
+        final String defaultEngine = getDefaultEngine();
+        if (defaultEngine != null && !defaultEngine.equals(mRequestedEngine)) {
             if (connectToEngine(defaultEngine)) {
-                mCurrentEngine = engine;
+                mCurrentEngine = defaultEngine;
                 return SUCCESS;
             }
         }
 
+        // Step 3: Try connecting to the highest ranked engine in the
+        // system.
         final String highestRanked = mEnginesHelper.getHighestRankedEngineName();
-        // Fall back to the hardcoded default if different from the two above
-        if (!defaultEngine.equals(highestRanked)
-                && !engine.equals(highestRanked)) {
+        if (highestRanked != null && !highestRanked.equals(mRequestedEngine) &&
+                !highestRanked.equals(defaultEngine)) {
             if (connectToEngine(highestRanked)) {
-                mCurrentEngine = engine;
+                mCurrentEngine = highestRanked;
                 return SUCCESS;
             }
         }
 
+        // NOTE: The API currently does not allow the caller to query whether
+        // they are actually connected to any engine. This might fail for various
+        // reasons like if the user disables all her TTS engines.
+
+        mCurrentEngine = null;
         dispatchOnInit(ERROR);
         return ERROR;
     }
@@ -573,6 +581,14 @@
                 service.setCallback(getPackageName(), null);
                 service.stop(getPackageName());
                 mServiceConnection.disconnect();
+                // Context#unbindService does not result in a call to
+                // ServiceConnection#onServiceDisconnected. As a result, the
+                // service ends up being destroyed (if there are no other open
+                // connections to it) but the process lives on and the
+                // ServiceConnection continues to refer to the destroyed service.
+                //
+                // This leads to tons of log spam about SynthThread being dead.
+                mServiceConnection = null;
                 mCurrentEngine = null;
                 return null;
             }
@@ -793,7 +809,10 @@
     }
 
     /**
-     * Checks whether the TTS engine is busy speaking.
+     * Checks whether the TTS engine is busy speaking. Note that a speech item is
+     * considered complete once it's audio data has been sent to the audio mixer, or
+     * written to a file. There might be a finite lag between this point, and when
+     * the audio hardware completes playback.
      *
      * @return {@code true} if the TTS engine is speaking.
      */
@@ -963,7 +982,7 @@
     /**
      * Synthesizes the given text to a file using the specified parameters.
      *
-     * @param text Thetext that should be synthesized
+     * @param text The text that should be synthesized
      * @param params Parameters for the request. Can be null.
      *            Supported parameter names:
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
@@ -1073,7 +1092,9 @@
      *
      * @deprecated This doesn't inform callers when the TTS engine has been
      *        initialized. {@link #TextToSpeech(Context, OnInitListener, String)}
-     *        can be used with the appropriate engine name.
+     *        can be used with the appropriate engine name. Also, there is no
+     *        guarantee that the engine specified will be loaded. If it isn't
+     *        installed or disabled, the user / system wide defaults will apply.
      *
      * @param enginePackageName The package name for the synthesis engine (e.g. "com.svox.pico")
      *
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 010c155..b4e8ab4 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -227,7 +227,7 @@
         private boolean mFirstIdle = true;
 
         public SynthThread() {
-            super(SYNTH_THREAD_NAME, android.os.Process.THREAD_PRIORITY_AUDIO);
+            super(SYNTH_THREAD_NAME, android.os.Process.THREAD_PRIORITY_DEFAULT);
         }
 
         @Override
@@ -282,6 +282,8 @@
             if (current != null) {
                 current.stop();
             }
+
+            // The AudioPlaybackHandler will be destroyed by the caller.
         }
 
         /**
@@ -337,6 +339,8 @@
             }
 
             removeCallbacksAndMessages(callingApp);
+            // This stops writing data to the file / or publishing
+            // items to the audio playback handler.
             SpeechItem current = setCurrentSpeechItem(null);
             if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
                 current.stop();
@@ -628,9 +632,7 @@
 
         @Override
         protected void stopImpl() {
-            if (mToken != null) {
-                mAudioPlaybackHandler.stop(mToken);
-            }
+            // Do nothing.
         }
     }
 
@@ -657,9 +659,7 @@
 
         @Override
         protected void stopImpl() {
-            if (mToken != null) {
-                mAudioPlaybackHandler.stop(mToken);
-            }
+            // Do nothing.
         }
     }
 
@@ -719,7 +719,7 @@
         }
 
         public boolean isSpeaking() {
-            return mSynthHandler.isSpeaking();
+            return mSynthHandler.isSpeaking() || mAudioPlaybackHandler.isSpeaking();
         }
 
         public int stop(String callingApp) {
@@ -767,10 +767,6 @@
             mCallbacks.setCallback(packageName, cb);
         }
 
-        private boolean isDefault(String lang, String country, String variant) {
-            return Locale.getDefault().equals(new Locale(lang, country, variant));
-        }
-
         private String intern(String in) {
             // The input parameter will be non null.
             return in.intern();
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 757a8c3..5a244f1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -226,7 +226,17 @@
      */
     public static Metrics isBoring(CharSequence text,
                                    TextPaint paint) {
-        return isBoring(text, paint, null);
+        return isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, null);
+    }
+
+    /**
+     * Returns null if not boring; the width, ascent, and descent if boring.
+     * @hide
+     */
+    public static Metrics isBoring(CharSequence text,
+                                   TextPaint paint,
+                                   TextDirectionHeuristic textDir) {
+        return isBoring(text, paint, textDir, null);
     }
 
     /**
@@ -235,6 +245,17 @@
      * if boring.
      */
     public static Metrics isBoring(CharSequence text, TextPaint paint, Metrics metrics) {
+        return isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, metrics);
+    }
+
+    /**
+     * Returns null if not boring; the width, ascent, and descent in the
+     * provided Metrics object (or a new one if the provided one was null)
+     * if boring.
+     * @hide
+     */
+    public static Metrics isBoring(CharSequence text, TextPaint paint,
+            TextDirectionHeuristic textDir, Metrics metrics) {
         char[] temp = TextUtils.obtain(500);
         int length = text.length();
         boolean boring = true;
@@ -258,6 +279,11 @@
                     break outer;
                 }
             }
+
+            if (textDir.isRtl(temp, 0, n)) {
+               boring = false;
+               break outer;
+            }
         }
 
         TextUtils.recycle(temp);
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index f196b34..cb96969 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -75,12 +75,31 @@
                          float spacingmult, float spacingadd,
                          boolean includepad,
                          TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
-        super((ellipsize == null) 
-                ? display 
-                : (display instanceof Spanned) 
-                    ? new SpannedEllipsizer(display) 
+        this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+    }
+
+    /**
+     * Make a layout for the transformed text (password transformation
+     * being the primary example of a transformation)
+     * that will be updated as the base text is changed.
+     * If ellipsize is non-null, the Layout will ellipsize the text
+     * down to ellipsizedWidth.
+     * *
+     * *@hide
+     */
+    public DynamicLayout(CharSequence base, CharSequence display,
+                         TextPaint paint,
+                         int width, Alignment align, TextDirectionHeuristic textDir,
+                         float spacingmult, float spacingadd,
+                         boolean includepad,
+                         TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+        super((ellipsize == null)
+                ? display
+                : (display instanceof Spanned)
+                    ? new SpannedEllipsizer(display)
                     : new Ellipsizer(display),
-              paint, width, align, spacingmult, spacingadd);
+              paint, width, align, textDir, spacingmult, spacingadd);
 
         mBase = base;
         mDisplay = display;
@@ -259,7 +278,7 @@
             reflowed = new StaticLayout(true);
 
         reflowed.generate(text, where, where + after,
-                getPaint(), getWidth(), getAlignment(),
+                getPaint(), getWidth(), getAlignment(), getTextDirectionHeuristic(),
                 getSpacingMultiplier(), getSpacingAdd(),
                 false, true, mEllipsizedWidth, mEllipsizeAt);
         int n = reflowed.getLineCount();
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index aae9ccf..eabeef0 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -16,8 +16,6 @@
 
 package android.text;
 
-import com.android.internal.util.ArrayUtils;
-
 import android.emoji.EmojiFactory;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -32,6 +30,8 @@
 import android.text.style.ReplacementSpan;
 import android.text.style.TabStopSpan;
 
+import com.android.internal.util.ArrayUtils;
+
 import java.util.Arrays;
 
 /**
@@ -113,6 +113,29 @@
     protected Layout(CharSequence text, TextPaint paint,
                      int width, Alignment align,
                      float spacingMult, float spacingAdd) {
+        this(text, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                spacingMult, spacingAdd);
+    }
+
+    /**
+     * Subclasses of Layout use this constructor to set the display text,
+     * width, and other standard properties.
+     * @param text the text to render
+     * @param paint the default paint for the layout.  Styles can override
+     * various attributes of the paint.
+     * @param width the wrapping width for the text.
+     * @param align whether to left, right, or center the text.  Styles can
+     * override the alignment.
+     * @param spacingMult factor by which to scale the font size to get the
+     * default line spacing
+     * @param spacingAdd amount to add to the default line spacing
+     *
+     * @hide
+     */
+    protected Layout(CharSequence text, TextPaint paint,
+                     int width, Alignment align, TextDirectionHeuristic textDir,
+                     float spacingMult, float spacingAdd) {
+
         if (width < 0)
             throw new IllegalArgumentException("Layout: " + width + " < 0");
 
@@ -133,6 +156,7 @@
         mSpacingMult = spacingMult;
         mSpacingAdd = spacingAdd;
         mSpannedText = text instanceof Spanned;
+        mTextDir = textDir;
     }
 
     /**
@@ -531,6 +555,14 @@
     }
 
     /**
+     * Return the heuristic used to determine paragraph text direction.
+     * @hide
+     */
+    public final TextDirectionHeuristic getTextDirectionHeuristic() {
+        return mTextDir;
+    }
+
+    /**
      * Return the number of lines of text in this layout.
      */
     public abstract int getLineCount();
@@ -1419,7 +1451,7 @@
         MeasuredText mt = MeasuredText.obtain();
         TextLine tl = TextLine.obtain();
         try {
-            mt.setPara(text, start, end, DIR_REQUEST_LTR);
+            mt.setPara(text, start, end, TextDirectionHeuristics.LTR);
             Directions directions;
             int dir;
             if (mt.mEasy) {
@@ -1769,6 +1801,7 @@
     private float mSpacingAdd;
     private static final Rect sTempRect = new Rect();
     private boolean mSpannedText;
+    private TextDirectionHeuristic mTextDir;
 
     public static final int DIR_LEFT_TO_RIGHT = 1;
     public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index a81be09..2920ac5 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -85,7 +85,7 @@
      * Analyzes text for bidirectional runs.  Allocates working buffers.
      */
     /* package */
-    void setPara(CharSequence text, int start, int end, int bidiRequest) {
+    void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) {
         mText = text;
         mTextStart = start;
 
@@ -115,13 +115,29 @@
             }
         }
 
-        if (TextUtils.doesNotNeedBidi(mChars, 0, len)) {
+        if ((textDir == TextDirectionHeuristics.LTR ||
+                textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR ||
+                textDir == TextDirectionHeuristics.ANYRTL_LTR) &&
+                TextUtils.doesNotNeedBidi(mChars, 0, len)) {
             mDir = Layout.DIR_LEFT_TO_RIGHT;
             mEasy = true;
         } else {
             if (mLevels == null || mLevels.length < len) {
                 mLevels = new byte[ArrayUtils.idealByteArraySize(len)];
             }
+            int bidiRequest;
+            if (textDir == TextDirectionHeuristics.LTR) {
+                bidiRequest = Layout.DIR_REQUEST_LTR;
+            } else if (textDir == TextDirectionHeuristics.RTL) {
+                bidiRequest = Layout.DIR_REQUEST_RTL;
+            } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR) {
+                bidiRequest = Layout.DIR_REQUEST_DEFAULT_LTR;
+            } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_RTL) {
+                bidiRequest = Layout.DIR_REQUEST_DEFAULT_RTL;
+            } else {
+                boolean isRtl = textDir.isRtl(mChars, 0, len);
+                bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR;
+            }
             mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false);
             mEasy = false;
         }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 9e48eff..f7b9502 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -16,8 +16,6 @@
 
 package android.text;
 
-import com.android.internal.util.ArrayUtils;
-
 import android.graphics.Bitmap;
 import android.graphics.Paint;
 import android.text.style.LeadingMarginSpan;
@@ -26,6 +24,8 @@
 import android.text.style.MetricAffectingSpan;
 import android.text.style.TabStopSpan;
 
+import com.android.internal.util.ArrayUtils;
+
 /**
  * StaticLayout is a Layout for text that will not be edited after it
  * is laid out.  Use {@link DynamicLayout} for text that may change.
@@ -46,6 +46,17 @@
              spacingmult, spacingadd, includepad);
     }
 
+    /**
+     * @hide
+     */
+    public StaticLayout(CharSequence source, TextPaint paint,
+            int width, Alignment align, TextDirectionHeuristic textDir,
+            float spacingmult, float spacingadd,
+            boolean includepad) {
+        this(source, 0, source.length(), paint, width, align, textDir,
+                spacingmult, spacingadd, includepad);
+    }
+
     public StaticLayout(CharSequence source, int bufstart, int bufend,
                         TextPaint paint, int outerwidth,
                         Alignment align,
@@ -55,9 +66,35 @@
              spacingmult, spacingadd, includepad, null, 0);
     }
 
+    /**
+     * @hide
+     */
+    public StaticLayout(CharSequence source, int bufstart, int bufend,
+            TextPaint paint, int outerwidth,
+            Alignment align, TextDirectionHeuristic textDir,
+            float spacingmult, float spacingadd,
+            boolean includepad) {
+        this(source, bufstart, bufend, paint, outerwidth, align, textDir,
+                spacingmult, spacingadd, includepad, null, 0);
+}
+
+    public StaticLayout(CharSequence source, int bufstart, int bufend,
+            TextPaint paint, int outerwidth,
+            Alignment align,
+            float spacingmult, float spacingadd,
+            boolean includepad,
+            TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+        this(source, bufstart, bufend, paint, outerwidth, align,
+                TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+    }
+
+    /**
+     * @hide
+     */
     public StaticLayout(CharSequence source, int bufstart, int bufend,
                         TextPaint paint, int outerwidth,
-                        Alignment align,
+                        Alignment align, TextDirectionHeuristic textDir,
                         float spacingmult, float spacingadd,
                         boolean includepad,
                         TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
@@ -66,7 +103,7 @@
                 : (source instanceof Spanned)
                     ? new SpannedEllipsizer(source)
                     : new Ellipsizer(source),
-              paint, outerwidth, align, spacingmult, spacingadd);
+              paint, outerwidth, align, textDir, spacingmult, spacingadd);
 
         /*
          * This is annoying, but we can't refer to the layout until
@@ -96,7 +133,7 @@
 
         mMeasured = MeasuredText.obtain();
 
-        generate(source, bufstart, bufend, paint, outerwidth, align,
+        generate(source, bufstart, bufend, paint, outerwidth, align, textDir,
                  spacingmult, spacingadd, includepad, includepad,
                  ellipsizedWidth, ellipsize);
 
@@ -116,7 +153,7 @@
 
     /* package */ void generate(CharSequence source, int bufStart, int bufEnd,
                         TextPaint paint, int outerWidth,
-                        Alignment align,
+                        Alignment align, TextDirectionHeuristic textDir,
                         float spacingmult, float spacingadd,
                         boolean includepad, boolean trackpad,
                         float ellipsizedWidth, TextUtils.TruncateAt ellipsize) {
@@ -157,7 +194,7 @@
                     LeadingMarginSpan lms = sp[i];
                     firstWidth -= sp[i].getLeadingMargin(true);
                     restWidth -= sp[i].getLeadingMargin(false);
-                    
+
                     // LeadingMarginSpan2 is odd.  The count affects all
                     // leading margin spans, not just this particular one,
                     // and start from the top of the span, not the top of the
@@ -195,7 +232,7 @@
                 }
             }
 
-            measured.setPara(source, paraStart, paraEnd, DIR_REQUEST_DEFAULT_LTR);
+            measured.setPara(source, paraStart, paraEnd, textDir);
             char[] chs = measured.mChars;
             float[] widths = measured.mWidths;
             byte[] chdirs = measured.mLevels;
diff --git a/core/java/android/text/TextDirectionHeuristic.java b/core/java/android/text/TextDirectionHeuristic.java
new file mode 100644
index 0000000..130f879
--- /dev/null
+++ b/core/java/android/text/TextDirectionHeuristic.java
@@ -0,0 +1,13 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package android.text;
+
+/**
+ * Interface for objects that guess at the paragraph direction by examining text.
+ *
+ * @hide
+ */
+public interface TextDirectionHeuristic {
+    /** @hide */ boolean isRtl(CharSequence text, int start, int end);
+    /** @hide */ boolean isRtl(char[] text, int start, int count);
+}
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
new file mode 100644
index 0000000..5f9ffc5
--- /dev/null
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -0,0 +1,310 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package android.text;
+
+
+/**
+ * Some objects that implement TextDirectionHeuristic.
+ * @hide
+ */
+public class TextDirectionHeuristics {
+
+    /** Always decides that the direction is left to right. */
+    public static final TextDirectionHeuristic LTR =
+        new TextDirectionHeuristicInternal(null /* no algorithm */, false);
+
+    /** Always decides that the direction is right to left. */
+    public static final TextDirectionHeuristic RTL =
+        new TextDirectionHeuristicInternal(null /* no algorithm */, true);
+
+    /**
+     * Determines the direction based on the first strong directional character,
+     * including bidi format chars, falling back to left to right if it
+     * finds none.  This is the default behavior of the Unicode Bidirectional
+     * Algorithm.
+     */
+    public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
+        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);
+
+    /**
+     * Determines the direction based on the first strong directional character,
+     * including bidi format chars, falling back to right to left if it
+     * finds none.  This is similar to the default behavior of the Unicode
+     * Bidirectional Algorithm, just with different fallback behavior.
+     */
+    public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
+        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
+
+    /**
+     * If the text contains any strong right to left non-format character, determines
+     * that the direction is right to left, falling back to left to right if it
+     * finds none.
+     */
+    public static final TextDirectionHeuristic ANYRTL_LTR =
+        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
+
+    /**
+     * If the text contains any strong left to right non-format character, determines
+     * that the direction is left to right, falling back to right to left if it
+     * finds none.
+     */
+    public static final TextDirectionHeuristic ANYLTR_RTL =
+        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_LTR, true);
+
+    /**
+     * Examines only the strong directional non-format characters, and if either
+     * left to right or right to left characters are 60% or more of this total,
+     * determines that the direction follows the majority of characters.  Falls
+     * back to left to right if neither direction meets this threshold.
+     */
+    public static final TextDirectionHeuristic CHARCOUNT_LTR =
+        new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, false);
+
+    /**
+     * Examines only the strong directional non-format characters, and if either
+     * left to right or right to left characters are 60% or more of this total,
+     * determines that the direction follows the majority of characters.  Falls
+     * back to right to left if neither direction meets this threshold.
+     */
+    public static final TextDirectionHeuristic CHARCOUNT_RTL =
+        new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
+
+    private static enum TriState {
+        TRUE, FALSE, UNKNOWN;
+    }
+
+    /**
+     * Computes the text direction based on an algorithm.  Subclasses implement
+     * {@link #defaultIsRtl} to handle cases where the algorithm cannot determine the
+     * direction from the text alone.
+     * @hide
+     */
+    public static abstract class TextDirectionHeuristicImpl implements TextDirectionHeuristic {
+        private final TextDirectionAlgorithm mAlgorithm;
+
+        public TextDirectionHeuristicImpl(TextDirectionAlgorithm algorithm) {
+            mAlgorithm = algorithm;
+        }
+
+        /**
+         * Return true if the default text direction is rtl.
+         */
+        abstract protected boolean defaultIsRtl();
+
+        @Override
+        public boolean isRtl(CharSequence text, int start, int end) {
+            if (text == null || start < 0 || end < start || text.length() < end) {
+                throw new IllegalArgumentException();
+            }
+            if (mAlgorithm == null) {
+                return defaultIsRtl();
+            }
+            text = text.subSequence(start, end);
+            char[] chars = text.toString().toCharArray();
+            return doCheck(chars, 0, chars.length);
+        }
+
+        @Override
+        public boolean isRtl(char[] chars, int start, int count) {
+            if (chars == null || start < 0 || count < 0 || chars.length - count < start) {
+                throw new IllegalArgumentException();
+            }
+            if (mAlgorithm == null) {
+                return defaultIsRtl();
+            }
+            return doCheck(chars, start, count);
+        }
+
+        private boolean doCheck(char[] chars, int start, int count) {
+            switch(mAlgorithm.checkRtl(chars, start, count)) {
+                case TRUE:
+                    return true;
+                case FALSE:
+                    return false;
+                default:
+                    return defaultIsRtl();
+            }
+        }
+    }
+
+    private static class TextDirectionHeuristicInternal extends TextDirectionHeuristicImpl {
+        private final boolean mDefaultIsRtl;
+
+        private TextDirectionHeuristicInternal(TextDirectionAlgorithm algorithm,
+                boolean defaultIsRtl) {
+            super(algorithm);
+            mDefaultIsRtl = defaultIsRtl;
+        }
+
+        @Override
+        protected boolean defaultIsRtl() {
+            return mDefaultIsRtl;
+        }
+    }
+
+    private static TriState isRtlText(int directionality) {
+        switch (directionality) {
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+                return TriState.FALSE;
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+                return TriState.TRUE;
+            default:
+                return TriState.UNKNOWN;
+        }
+    }
+
+    private static TriState isRtlTextOrFormat(int directionality) {
+        switch (directionality) {
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+                return TriState.FALSE;
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+                return TriState.TRUE;
+            default:
+                return TriState.UNKNOWN;
+        }
+    }
+
+    /**
+     * Interface for an algorithm to guess the direction of a paragraph of text.
+     *
+     * @hide
+     */
+    public static interface TextDirectionAlgorithm {
+        /**
+         * Returns whether the range of text is RTL according to the algorithm.
+         *
+         * @hide
+         */
+        TriState checkRtl(char[] text, int start, int count);
+    }
+
+    /**
+     * Algorithm that uses the first strong directional character to determine
+     * the paragraph direction.  This is the standard Unicode Bidirectional
+     * algorithm.
+     *
+     * @hide
+     */
+    public static class FirstStrong implements TextDirectionAlgorithm {
+        @Override
+        public TriState checkRtl(char[] text, int start, int count) {
+            TriState result = TriState.UNKNOWN;
+            for (int i = start, e = start + count; i < e && result == TriState.UNKNOWN; ++i) {
+                result = isRtlTextOrFormat(Character.getDirectionality(text[i]));
+            }
+            return result;
+        }
+
+        private FirstStrong() {
+        }
+
+        public static final FirstStrong INSTANCE = new FirstStrong();
+    }
+
+    /**
+     * Algorithm that uses the presence of any strong directional non-format
+     * character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
+     * direction of text.
+     *
+     * @hide
+     */
+    public static class AnyStrong implements TextDirectionAlgorithm {
+        private final boolean mLookForRtl;
+
+        @Override
+        public TriState checkRtl(char[] text, int start, int count) {
+            boolean haveUnlookedFor = false;
+            for (int i = start, e = start + count; i < e; ++i) {
+                switch (isRtlText(Character.getDirectionality(text[i]))) {
+                    case TRUE:
+                        if (mLookForRtl) {
+                            return TriState.TRUE;
+                        }
+                        haveUnlookedFor = true;
+                        break;
+                    case FALSE:
+                        if (!mLookForRtl) {
+                            return TriState.FALSE;
+                        }
+                        haveUnlookedFor = true;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            if (haveUnlookedFor) {
+                return mLookForRtl ? TriState.FALSE : TriState.TRUE;
+            }
+            return TriState.UNKNOWN;
+        }
+
+        private AnyStrong(boolean lookForRtl) {
+            this.mLookForRtl = lookForRtl;
+        }
+
+        public static final AnyStrong INSTANCE_RTL = new AnyStrong(true);
+        public static final AnyStrong INSTANCE_LTR = new AnyStrong(false);
+    }
+
+    /**
+     * Algorithm that uses the relative proportion of strong directional
+     * characters (excluding LRE, LRO, RLE, RLO) to determine the direction
+     * of the paragraph, if the proportion exceeds a given threshold.
+     *
+     * @hide
+     */
+    public static class CharCount implements TextDirectionAlgorithm {
+        private final float mThreshold;
+
+        @Override
+        public TriState checkRtl(char[] text, int start, int count) {
+            int countLtr = 0;
+            int countRtl = 0;
+            for(int i = start, e = start + count; i < e; ++i) {
+                switch (isRtlText(Character.getDirectionality(text[i]))) {
+                    case TRUE:
+                        ++countLtr;
+                        break;
+                    case FALSE:
+                        ++countRtl;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            int limit = (int)((countLtr + countRtl) * mThreshold);
+            if (limit > 0) {
+                if (countLtr > limit) {
+                    return TriState.FALSE;
+                }
+                if (countRtl > limit) {
+                    return TriState.TRUE;
+                }
+            }
+            return TriState.UNKNOWN;
+        }
+
+        private CharCount(float threshold) {
+            mThreshold = threshold;
+        }
+
+        public static CharCount withThreshold(float threshold) {
+            if (threshold < 0 || threshold > 1) {
+                throw new IllegalArgumentException();
+            }
+            if (threshold == DEFAULT_THRESHOLD) {
+                return INSTANCE_DEFAULT;
+            }
+            return new CharCount(threshold);
+        }
+
+        public static final float DEFAULT_THRESHOLD = 0.6f;
+        public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
+    }
+}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6741059..29c9853 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -16,9 +16,6 @@
 
 package android.text;
 
-import com.android.internal.R;
-import com.android.internal.util.ArrayUtils;
-
 import android.content.res.Resources;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -45,6 +42,9 @@
 import android.text.style.UnderlineSpan;
 import android.util.Printer;
 
+import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
+
 import java.lang.reflect.Array;
 import java.util.Iterator;
 import java.util.regex.Pattern;
@@ -1001,13 +1001,37 @@
      * will be padded with zero-width spaces to preserve the original
      * length and offsets instead of truncating.
      * If <code>callback</code> is non-null, it will be called to
-     * report the start and end of the ellipsized range.
+     * report the start and end of the ellipsized range.  TextDirection
+     * is determined by the first strong directional character.
      */
     public static CharSequence ellipsize(CharSequence text,
                                          TextPaint paint,
                                          float avail, TruncateAt where,
                                          boolean preserveLength,
                                          EllipsizeCallback callback) {
+        return ellipsize(text, paint, avail, where, preserveLength, callback,
+                TextDirectionHeuristics.FIRSTSTRONG_LTR);
+    }
+
+    /**
+     * Returns the original text if it fits in the specified width
+     * given the properties of the specified Paint,
+     * or, if it does not fit, a copy with ellipsis character added
+     * at the specified edge or center.
+     * If <code>preserveLength</code> is specified, the returned copy
+     * will be padded with zero-width spaces to preserve the original
+     * length and offsets instead of truncating.
+     * If <code>callback</code> is non-null, it will be called to
+     * report the start and end of the ellipsized range.
+     *
+     * @hide
+     */
+    public static CharSequence ellipsize(CharSequence text,
+            TextPaint paint,
+            float avail, TruncateAt where,
+            boolean preserveLength,
+            EllipsizeCallback callback,
+            TextDirectionHeuristic textDir) {
         if (sEllipsis == null) {
             Resources r = Resources.getSystem();
             sEllipsis = r.getString(R.string.ellipsis);
@@ -1017,8 +1041,7 @@
 
         MeasuredText mt = MeasuredText.obtain();
         try {
-            float width = setPara(mt, paint, text, 0, text.length(),
-                    Layout.DIR_REQUEST_DEFAULT_LTR);
+            float width = setPara(mt, paint, text, 0, text.length(), textDir);
 
             if (width <= avail) {
                 if (callback != null) {
@@ -1108,11 +1131,20 @@
                                               TextPaint p, float avail,
                                               String oneMore,
                                               String more) {
+        return commaEllipsize(text, p, avail, oneMore, more,
+                TextDirectionHeuristics.FIRSTSTRONG_LTR);
+    }
+
+    /**
+     * @hide
+     */
+    public static CharSequence commaEllipsize(CharSequence text, TextPaint p,
+         float avail, String oneMore, String more, TextDirectionHeuristic textDir) {
 
         MeasuredText mt = MeasuredText.obtain();
         try {
             int len = text.length();
-            float width = setPara(mt, p, text, 0, len, Layout.DIR_REQUEST_DEFAULT_LTR);
+            float width = setPara(mt, p, text, 0, len, textDir);
             if (width <= avail) {
                 return text;
             }
@@ -1135,9 +1167,6 @@
             int count = 0;
             float[] widths = mt.mWidths;
 
-            int request = mt.mDir == 1 ? Layout.DIR_REQUEST_LTR :
-                Layout.DIR_REQUEST_RTL;
-
             MeasuredText tempMt = MeasuredText.obtain();
             for (int i = 0; i < len; i++) {
                 w += widths[i];
@@ -1155,7 +1184,7 @@
                     }
 
                     // XXX this is probably ok, but need to look at it more
-                    tempMt.setPara(format, 0, format.length(), request);
+                    tempMt.setPara(format, 0, format.length(), textDir);
                     float moreWid = tempMt.addStyleRun(p, tempMt.mLen, null);
 
                     if (w + moreWid <= avail) {
@@ -1175,9 +1204,9 @@
     }
 
     private static float setPara(MeasuredText mt, TextPaint paint,
-            CharSequence text, int start, int end, int bidiRequest) {
+            CharSequence text, int start, int end, TextDirectionHeuristic textDir) {
 
-        mt.setPara(text, start, end, bidiRequest);
+        mt.setPara(text, start, end, textDir);
 
         float width;
         Spanned sp = text instanceof Spanned ? (Spanned) text : null;
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index c6ffe58..5926db3 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -281,10 +281,29 @@
     }
 
     /**
-     * return a negative number if a is less than b, a positive number if a is
-     * greater than b, and 0 if they are equal.
+     * Compare two {@code Time} objects and return a negative number if {@code
+     * a} is less than {@code b}, a positive number if {@code a} is greater than
+     * {@code b}, or 0 if they are equal.
+     *
+     * @param a first {@code Time} instance to compare
+     * @param b second {@code Time} instance to compare
+     * @throws NullPointerException if either argument is {@code null}
+     * @throws IllegalArgumentException if {@link #allDay} is true but {@code
+     *             hour}, {@code minute}, and {@code second} are not 0.
+     * @return a negative result if {@code a} is earlier, a positive result if
+     *         {@code a} is earlier, or 0 if they are equal.
      */
-    native public static int compare(Time a, Time b);
+    public static int compare(Time a, Time b) {
+        if (a == null) {
+            throw new NullPointerException("a == null");
+        } else if (b == null) {
+            throw new NullPointerException("b == null");
+        }
+
+        return nativeCompare(a, b);
+    }
+
+    private static native int nativeCompare(Time a, Time b);
 
     /**
      * Print the current value given the format string provided. See man
diff --git a/core/java/android/util/Config.java b/core/java/android/util/Config.java
new file mode 100644
index 0000000..70dc9aa
--- /dev/null
+++ b/core/java/android/util/Config.java
@@ -0,0 +1,56 @@
+/*
+ * 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.util;
+
+/**
+ * @deprecated This class is not useful, it just returns the same value for
+ * all constants, and has always done this.  Do not use it.
+ */
+@Deprecated
+public final class Config {
+    /** @hide */ public Config() {}
+
+    /**
+     * @deprecated Always false.
+     */
+    @Deprecated
+    public static final boolean DEBUG = false;
+
+    /**
+     * @deprecated Always true.
+     */
+    @Deprecated
+    public static final boolean RELEASE = true;
+
+    /**
+     * @deprecated Always false.
+     */
+    @Deprecated
+    public static final boolean PROFILE = false;
+
+    /**
+     * @deprecated Always false.
+     */
+    @Deprecated
+    public static final boolean LOGV = false;
+
+    /**
+     * @deprecated Always true.
+     */
+    @Deprecated
+    public static final boolean LOGD = true;
+}
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index 132b595..f2a86c9 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -196,6 +196,12 @@
     private int pos = 0;
     private int limit = 0;
 
+    /*
+     * The offset of the first character in the buffer.
+     */
+    private int bufferStartLine = 1;
+    private int bufferStartColumn = 1;
+
     private final List<JsonScope> stack = new ArrayList<JsonScope>();
     {
         push(JsonScope.EMPTY_DOCUMENT);
@@ -711,6 +717,16 @@
      * false.
      */
     private boolean fillBuffer(int minimum) throws IOException {
+        // Before clobbering the old characters, update where buffer starts
+        for (int i = 0; i < pos; i++) {
+            if (buffer[i] == '\n') {
+                bufferStartLine++;
+                bufferStartColumn = 1;
+            } else {
+                bufferStartColumn++;
+            }
+        }
+
         if (limit != pos) {
             limit -= pos;
             System.arraycopy(buffer, pos, buffer, 0, limit);
@@ -722,6 +738,14 @@
         int total;
         while ((total = in.read(buffer, limit, buffer.length - limit)) != -1) {
             limit += total;
+
+            // if this is the first read, consume an optional byte order mark (BOM) if it exists
+                if (bufferStartLine == 1 && bufferStartColumn == 1
+                        && limit > 0 && buffer[0] == '\ufeff') {
+                pos++;
+                bufferStartColumn--;
+            }
+
             if (limit >= minimum) {
                 return true;
             }
@@ -729,6 +753,28 @@
         return false;
     }
 
+    private int getLineNumber() {
+        int result = bufferStartLine;
+        for (int i = 0; i < pos; i++) {
+            if (buffer[i] == '\n') {
+                result++;
+            }
+        }
+        return result;
+    }
+
+    private int getColumnNumber() {
+        int result = bufferStartColumn;
+        for (int i = 0; i < pos; i++) {
+            if (buffer[i] == '\n') {
+                result = 1;
+            } else {
+                result++;
+            }
+        }
+        return result;
+    }
+
     private int nextNonWhitespace() throws IOException {
         while (pos < limit || fillBuffer(1)) {
             int c = buffer[pos++];
@@ -806,7 +852,7 @@
 
     private boolean skipTo(String toFind) throws IOException {
         outer:
-        for (; pos + toFind.length() < limit || fillBuffer(toFind.length()); pos++) {
+        for (; pos + toFind.length() <= limit || fillBuffer(toFind.length()); pos++) {
             for (int c = 0; c < toFind.length(); c++) {
                 if (buffer[pos + c] != toFind.charAt(c)) {
                     continue outer;
@@ -1107,7 +1153,8 @@
      * with this reader's content.
      */
     private IOException syntaxError(String message) throws IOException {
-        throw new MalformedJsonException(message + " near " + getSnippet());
+        throw new MalformedJsonException(message
+                + " at line " + getLineNumber() + " column " + getColumnNumber());
     }
 
     private CharSequence getSnippet() {
diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java
index 47e84c5..c1e6e40 100644
--- a/core/java/android/util/JsonWriter.java
+++ b/core/java/android/util/JsonWriter.java
@@ -407,6 +407,11 @@
              * quotation marks except for the characters that must be escaped:
              * quotation mark, reverse solidus, and the control characters
              * (U+0000 through U+001F)."
+             *
+             * We also escape '\u2028' and '\u2029', which JavaScript interprets
+             * as newline characters. This prevents eval() from failing with a
+             * syntax error.
+             * http://code.google.com/p/google-gson/issues/detail?id=341
              */
             switch (c) {
                 case '"':
@@ -435,6 +440,11 @@
                     out.write("\\f");
                     break;
 
+                case '\u2028':
+                case '\u2029':
+                    out.write(String.format("\\u%04x", (int) c));
+                    break;
+
                 default:
                     if (c <= 0x1F) {
                         out.write(String.format("\\u%04x", (int) c));
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 3bcd266..152827d 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -25,9 +25,9 @@
 public class Patterns {
     /**
      *  Regular expression to match all IANA top-level domains.
-     *  List accurate as of 2010/05/06.  List taken from:
+     *  List accurate as of 2011/07/18.  List taken from:
      *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-     *  This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py
+     *  This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
      */
     public static final String TOP_LEVEL_DOMAIN_STR =
         "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
@@ -53,7 +53,7 @@
         + "|u[agksyz]"
         + "|v[aceginu]"
         + "|w[fs]"
-        + "|(xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)"
+        + "|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)"
         + "|y[et]"
         + "|z[amw])";
 
@@ -65,9 +65,9 @@
 
     /**
      *  Regular expression to match all IANA top-level domains for WEB_URL.
-     *  List accurate as of 2010/05/06.  List taken from:
+     *  List accurate as of 2011/07/18.  List taken from:
      *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-     *  This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py
+     *  This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
      */
     public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL =
         "(?:"
@@ -94,7 +94,7 @@
         + "|u[agksyz]"
         + "|v[aceginu]"
         + "|w[fs]"
-        + "|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)"
+        + "|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)"
         + "|y[et]"
         + "|z[amw]))";
 
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7fc43b9..7cf4579 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -23,10 +23,14 @@
  * there can be gaps in the indices.  It is intended to be more efficient
  * than using a HashMap to map Integers to Objects.
  */
-public class SparseArray<E> {
+public class SparseArray<E> implements Cloneable {
     private static final Object DELETED = new Object();
     private boolean mGarbage = false;
 
+    private int[] mKeys;
+    private Object[] mValues;
+    private int mSize;
+
     /**
      * Creates a new SparseArray containing no mappings.
      */
@@ -47,6 +51,20 @@
         mSize = 0;
     }
 
+    @Override
+    @SuppressWarnings("unchecked")
+    public SparseArray<E> clone() {
+        SparseArray<E> clone = null;
+        try {
+            clone = (SparseArray<E>) super.clone();
+            clone.mKeys = mKeys.clone();
+            clone.mValues = mValues.clone();
+        } catch (CloneNotSupportedException cnse) {
+            /* ignore */
+        }
+        return clone;
+    }
+
     /**
      * Gets the Object mapped from the specified key, or <code>null</code>
      * if no such mapping has been made.
@@ -59,6 +77,7 @@
      * Gets the Object mapped from the specified key, or the specified Object
      * if no such mapping has been made.
      */
+    @SuppressWarnings("unchecked")
     public E get(int key, E valueIfKeyNotFound) {
         int i = binarySearch(mKeys, 0, mSize, key);
 
@@ -209,6 +228,7 @@
      * the value from the <code>index</code>th key-value mapping that this
      * SparseArray stores.  
      */
+    @SuppressWarnings("unchecked")
     public E valueAt(int index) {
         if (mGarbage) {
             gc();
@@ -331,20 +351,4 @@
         else
             return ~high;
     }
-
-    private void checkIntegrity() {
-        for (int i = 1; i < mSize; i++) {
-            if (mKeys[i] <= mKeys[i - 1]) {
-                for (int j = 0; j < mSize; j++) {
-                    Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
-                }
-
-                throw new RuntimeException();
-            }
-        }
-    }
-
-    private int[] mKeys;
-    private Object[] mValues;
-    private int mSize;
 }
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index f7799de..76c47c6 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -24,7 +24,7 @@
  * there can be gaps in the indices.  It is intended to be more efficient
  * than using a HashMap to map Integers to Booleans.
  */
-public class SparseBooleanArray {
+public class SparseBooleanArray implements Cloneable {
     /**
      * Creates a new SparseBooleanArray containing no mappings.
      */
@@ -45,6 +45,19 @@
         mSize = 0;
     }
 
+    @Override
+    public SparseBooleanArray clone() {
+        SparseBooleanArray clone = null;
+        try {
+            clone = (SparseBooleanArray) super.clone();
+            clone.mKeys = mKeys.clone();
+            clone.mValues = mValues.clone();
+        } catch (CloneNotSupportedException cnse) {
+            /* ignore */
+        }
+        return clone;
+    }
+
     /**
      * Gets the boolean mapped from the specified key, or <code>false</code>
      * if no such mapping has been made.
@@ -227,18 +240,6 @@
             return ~high;
     }
 
-    private void checkIntegrity() {
-        for (int i = 1; i < mSize; i++) {
-            if (mKeys[i] <= mKeys[i - 1]) {
-                for (int j = 0; j < mSize; j++) {
-                    Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
-                }
-
-                throw new RuntimeException();
-            }
-        }
-    }
-
     private int[] mKeys;
     private boolean[] mValues;
     private int mSize;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 9ab3b53..8d11177 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -23,7 +23,12 @@
  * there can be gaps in the indices.  It is intended to be more efficient
  * than using a HashMap to map Integers to Integers.
  */
-public class SparseIntArray {
+public class SparseIntArray implements Cloneable {
+
+    private int[] mKeys;
+    private int[] mValues;
+    private int mSize;
+
     /**
      * Creates a new SparseIntArray containing no mappings.
      */
@@ -44,6 +49,19 @@
         mSize = 0;
     }
 
+    @Override
+    public SparseIntArray clone() {
+        SparseIntArray clone = null;
+        try {
+            clone = (SparseIntArray) super.clone();
+            clone.mKeys = mKeys.clone();
+            clone.mValues = mValues.clone();
+        } catch (CloneNotSupportedException cnse) {
+            /* ignore */
+        }
+        return clone;
+    }
+
     /**
      * Gets the int mapped from the specified key, or <code>0</code>
      * if no such mapping has been made.
@@ -232,20 +250,4 @@
         else
             return ~high;
     }
-
-    private void checkIntegrity() {
-        for (int i = 1; i < mSize; i++) {
-            if (mKeys[i] <= mKeys[i - 1]) {
-                for (int j = 0; j < mSize; j++) {
-                    Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
-                }
-
-                throw new RuntimeException();
-            }
-        }
-    }
-
-    private int[] mKeys;
-    private int[] mValues;
-    private int mSize;
 }
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index bfafa98..e954983 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -23,6 +23,36 @@
  * Examples of good action modes include selection modes, search, content editing, etc.
  */
 public abstract class ActionMode {
+    private Object mTag;
+
+    /**
+     * Set a tag object associated with this ActionMode.
+     *
+     * <p>Like the tag available to views, this allows applications to associate arbitrary
+     * data with an ActionMode for later reference.
+     *
+     * @param tag Tag to associate with this ActionMode
+     *
+     * @see #getTag()
+     */
+    public void setTag(Object tag) {
+        mTag = tag;
+    }
+
+    /**
+     * Retrieve the tag object associated with this ActionMode.
+     *
+     * <p>Like the tag available to views, this allows applications to associate arbitrary
+     * data with an ActionMode for later reference.
+     *
+     * @return Tag associated with this ActionMode
+     *
+     * @see #setTag(Object)
+     */
+    public Object getTag() {
+        return mTag;
+    }
+
     /**
      * Set the title of the action mode. This method will have no visible effect if
      * a custom view has been set.
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index 47f7358..5601dc5 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -28,7 +28,9 @@
  * {@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.
+ * selected and none of the menu item callbacks has handled the selection. For this
+ * case the provider can also optionally provide a sub-menu for accomplishing the
+ * task at hand.
  * </p>
  * <p>
  * There are two ways for using an action provider for creating and handling of action views:
diff --git a/core/java/android/view/CollapsibleActionView.java b/core/java/android/view/CollapsibleActionView.java
new file mode 100644
index 0000000..ab2365e
--- /dev/null
+++ b/core/java/android/view/CollapsibleActionView.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.view.MenuItem.OnActionExpandListener;
+
+/**
+ * When a {@link View} implements this interface it will receive callbacks
+ * when expanded or collapsed as an action view alongside the optional,
+ * app-specified callbacks to {@link OnActionExpandListener}.
+ *
+ * <p>See {@link MenuItem} for more information about action views.
+ * See {@link android.app.ActionBar} for more information about the action bar.
+ */
+public interface CollapsibleActionView {
+    /**
+     * Called when this view is expanded as an action view.
+     * See {@link MenuItem#expandActionView()}.
+     */
+    public void onActionViewExpanded();
+
+    /**
+     * Called when this view is collapsed as an action view.
+     * See {@link MenuItem#collapseActionView()}.
+     */
+    public void onActionViewCollapsed();
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 2be5a49..d9efe0c 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -25,16 +25,18 @@
 import android.util.DisplayMetrics;
 import android.util.Slog;
 
+/**
+ * Provides information about the display size and density.
+ */
 public class Display {
     static final String TAG = "Display";
     static final boolean DEBUG_COMPAT = false;
 
     /**
-     * Specify the default Display
+     * The default Display id.
      */
     public static final int DEFAULT_DISPLAY = 0;
 
-    
     /**
      * Use {@link android.view.WindowManager#getDefaultDisplay()
      * WindowManager.getDefaultDisplay()} to create a Display object.
@@ -55,16 +57,6 @@
         init(display);
     }
 
-    /** @hide */
-    public static void setCompatibilityInfo(CompatibilityInfo compatInfo) {
-        if (compatInfo != null && (compatInfo.isScalingRequired()
-                || !compatInfo.supportsScreen())) {
-            sCompatibilityInfo = compatInfo;
-        } else {
-            sCompatibilityInfo = null;
-        }
-    }
-    
     /**
      * Returns the index of this display.  This is currently undefined; do
      * not use.
@@ -80,25 +72,29 @@
     native static int getDisplayCount();
     
     /**
-     * Returns the raw size of the display, in pixels.  Note that this
-     * should <em>not</em> generally be used for computing layouts, since
-     * a device will typically have screen decoration (such as a status bar)
+     * Gets the size of the display, in pixels.
+     * <p>
+     * Note that this value should <em>not</em> be used for computing layouts,
+     * since a device will typically have screen decoration (such as a status bar)
      * along the edges of the display that reduce the amount of application
-     * space available from the raw size returned here.  This value is
-     * adjusted for you based on the current rotation of the display.
+     * space available from the size returned here.  Layouts should instead use
+     * the window size.
+     * </p><p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The size returned by this method does not necessarily represent the
+     * actual raw size (native resolution) of the display.  The returned size may
+     * be adjusted to exclude certain system decor elements that are always visible.
+     * It may also be scaled to provide compatibility with older applications that
+     * were originally designed for smaller displays.
+     * </p>
+     *
+     * @param outSize A {@link Point} object to receive the size information.
      */
     public void getSize(Point outSize) {
         getSizeInternal(outSize, true);
     }
 
-    /**
-     * Returns the raw size of the display, in pixels.  Note that this
-     * should <em>not</em> generally be used for computing layouts, since
-     * a device will typically have screen decoration (such as a status bar)
-     * along the edges of the display that reduce the amount of application
-     * space available from the raw size returned here.  This value is
-     * adjusted for you based on the current rotation of the display.
-     */
     private void getSizeInternal(Point outSize, boolean doCompat) {
         try {
             IWindowManager wm = getWindowManager();
@@ -118,7 +114,8 @@
             } else {
                 // This is just for boot-strapping, initializing the
                 // system process before the window manager is up.
-                outSize.y = getRealHeight();
+                outSize.x = getRawWidth();
+                outSize.y = getRawHeight();
             }
             if (DEBUG_COMPAT && doCompat) Slog.v(TAG, "Returning display size: " + outSize);
         } catch (RemoteException e) {
@@ -127,7 +124,10 @@
     }
     
     /**
-     * This is just easier for some parts of the framework.
+     * Gets the size of the display as a rectangle, in pixels.
+     *
+     * @param outSize A {@link Rect} object to receive the size information.
+     * @see #getSize(Point)
      */
     public void getRectSize(Rect outSize) {
         synchronized (mTmpPoint) {
@@ -181,14 +181,49 @@
         }
     }
 
-    /** @hide Returns the actual screen size, not including any decor. */
-    native public int getRealWidth();
-    /** @hide Returns the actual screen size, not including any decor. */
-    native public int getRealHeight();
+    /**
+     * Gets the real size of the display without subtracting any window decor or
+     * applying any compatibility scale factors.
+     * <p>
+     * The real size may be smaller than the raw size when the window manager
+     * is emulating a smaller display (using adb shell am display-size).
+     * </p><p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p>
+     * @hide
+     */
+    public void getRealSize(Point outSize) {
+        try {
+            IWindowManager wm = getWindowManager();
+            if (wm != null) {
+                wm.getRealDisplaySize(outSize);
+            } else {
+                // This is just for boot-strapping, initializing the
+                // system process before the window manager is up.
+                outSize.x = getRawWidth();
+                outSize.y = getRawHeight();
+            }
+        } catch (RemoteException e) {
+            Slog.w("Display", "Unable to get real display size", e);
+        }
+    }
 
-    /** @hide special for when we are faking the screen size. */
+    /**
+     * Gets the raw width of the display, in pixels.
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p>
+     * @hide
+     */
     native public int getRawWidth();
-    /** @hide special for when we are faking the screen size. */
+
+    /**
+     * Gets the raw height of the display, in pixels.
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p>
+     * @hide
+     */
     native public int getRawHeight();
     
     /**
@@ -234,17 +269,24 @@
     }
     
     /**
-     * Initialize a DisplayMetrics object from this display's data.
-     * 
-     * @param outMetrics
+     * Gets display metrics that describe the size and density of this display.
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The size returned by this method does not necessarily represent the
+     * actual raw size (native resolution) of the display.  The returned size may
+     * be adjusted to exclude certain system decor elements that are always visible.
+     * It may also be scaled to provide compatibility with older applications that
+     * were originally designed for smaller displays.
+     * </p>
+     *
+     * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
      */
     public void getMetrics(DisplayMetrics outMetrics) {
         synchronized (mTmpPoint) {
             getSizeInternal(mTmpPoint, false);
-            outMetrics.widthPixels = mTmpPoint.x;
-            outMetrics.heightPixels = mTmpPoint.y;
+            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
         }
-        getNonSizeMetrics(outMetrics);
 
         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
         if (ci != null) {
@@ -256,22 +298,44 @@
     }
 
     /**
-     * Initialize a DisplayMetrics object from this display's data.
-     *
-     * @param outMetrics
+     * Gets display metrics based on the real size of this display.
      * @hide
      */
     public void getRealMetrics(DisplayMetrics outMetrics) {
-        outMetrics.widthPixels = getRealWidth();
-        outMetrics.heightPixels = getRealHeight();
-        getNonSizeMetrics(outMetrics);
+        synchronized (mTmpPoint) {
+            getRealSize(mTmpPoint);
+            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+        }
     }
 
-    private void getNonSizeMetrics(DisplayMetrics outMetrics) {
+    /**
+     * If the display is mirrored to an external HDMI display, returns the
+     * width of that display.
+     * @hide
+     */
+    public int getRawExternalWidth() {
+        return 1280;
+    }
+
+    /**
+     * If the display is mirrored to an external HDMI display, returns the
+     * height of that display.
+     * @hide
+     */
+    public int getRawExternalHeight() {
+        return 720;
+    }
+
+    /**
+     * Gets display metrics based on an explicit assumed display size.
+     * @hide
+     */
+    public void getMetricsWithSize(DisplayMetrics outMetrics,
+            int width, int height) {
         outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
 
-        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels;
-        outMetrics.noncompatHeightPixels = outMetrics.heightPixels;
+        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
+        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
 
         outMetrics.density = outMetrics.noncompatDensity = mDensity;
         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
@@ -314,8 +378,6 @@
     private static boolean sInitialized = false;
     private static IWindowManager sWindowManager;
 
-    private static volatile CompatibilityInfo sCompatibilityInfo;
-
     /**
      * Returns a display object which uses the metric's width/height instead.
      * @hide
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 4484d59..8f4ece0 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -41,15 +41,6 @@
     abstract void end();
 
     /**
-     * Indicates whether this display list can be replayed or not.
-     * 
-     * @return True if the display list can be replayed, false otherwise.
-     * 
-     * @see android.view.HardwareCanvas#drawDisplayList(DisplayList) 
-     */
-    abstract boolean isReady();
-
-    /**
      * Invalidates the display list, indicating that it should be repopulated
      * with new drawing commands prior to being used again. Calling this method
      * causes calls to {@link #isValid()} to return <code>false</code>.
@@ -63,4 +54,11 @@
      * @return boolean true if the display list is able to be replayed, false otherwise.
      */
     abstract boolean isValid();
+
+    /**
+     * Return the amount of memory used by this display list.
+     * 
+     * @return The size of this display list in bytes
+     */
+    abstract int getSize();
 }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 4987e2f..a7fe95d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -51,6 +51,7 @@
 
     // The native renderer will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
+    @SuppressWarnings({"unused", "FieldCanBeLocal"})
     private CanvasFinalizer mFinalizer;
 
     private int mWidth;
@@ -97,12 +98,8 @@
     protected GLES20Canvas(boolean record, boolean translucent) {
         mOpaque = !translucent;
 
-        setupRenderer(record);
-    }
-
-    protected void setupRenderer(boolean record) {
         if (record) {
-            mRenderer = nGetDisplayListRenderer(mRenderer);
+            mRenderer = nCreateDisplayListRenderer();
         } else {
             mRenderer = nCreateRenderer();
         }
@@ -114,43 +111,31 @@
         if (mRenderer == 0) {
             throw new IllegalStateException("Could not create GLES20Canvas renderer");
         } else {
-            mFinalizer = CanvasFinalizer.getFinalizer(mFinalizer, mRenderer);
+            mFinalizer = new CanvasFinalizer(mRenderer);
         }
     }
 
+    protected void resetDisplayListRenderer() {
+        nResetDisplayListRenderer(mRenderer);
+    }
+
     private static native int nCreateRenderer();
     private static native int nCreateLayerRenderer(int layer);
-    private static native int nGetDisplayListRenderer(int renderer);
+    private static native int nCreateDisplayListRenderer();
+    private static native void nResetDisplayListRenderer(int renderer);
     private static native void nDestroyRenderer(int renderer);
 
-    private static class CanvasFinalizer {
-        int mRenderer;
+    private static final class CanvasFinalizer {
+        private final int mRenderer;
 
-        // Factory method returns new instance if old one is null, or old instance
-        // otherwise, destroying native renderer along the way as necessary
-        static CanvasFinalizer getFinalizer(CanvasFinalizer oldFinalizer, int renderer) {
-            if (oldFinalizer == null) {
-                return new CanvasFinalizer(renderer);
-            }
-            oldFinalizer.replaceNativeObject(renderer);
-            return oldFinalizer;
-        }
-
-        private CanvasFinalizer(int renderer) {
+        public CanvasFinalizer(int renderer) {
             mRenderer = renderer;
         }
 
-        private void replaceNativeObject(int newRenderer) {
-            if (mRenderer != 0 && newRenderer != mRenderer) {
-                nDestroyRenderer(mRenderer);
-            }
-            mRenderer = newRenderer;
-        }
-
         @Override
         protected void finalize() throws Throwable {
             try {
-                replaceNativeObject(0);
+                nDestroyRenderer(mRenderer);
             } finally {
                 super.finalize();
             }
@@ -286,15 +271,58 @@
 
     private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
 
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Memory
+    ///////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Must match Caches::FlushMode values
+     * 
+     * @see #flushCaches(int) 
+     */
+    public static final int FLUSH_CACHES_LAYERS = 0;
+    
+    /**
+     * Must match Caches::FlushMode values
+     * 
+     * @see #flushCaches(int) 
+     */
+    public static final int FLUSH_CACHES_MODERATE = 1;
+
+    /**
+     * Must match Caches::FlushMode values
+     * 
+     * @see #flushCaches(int) 
+     */
+    public static final int FLUSH_CACHES_FULL = 2;
+
+    /**
+     * Flush caches to reclaim as much memory as possible. The amount of memory
+     * to reclaim is indicate by the level parameter.
+     * 
+     * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
+     * {@link #FLUSH_CACHES_FULL}.
+     * 
+     * @param level Hint about the amount of memory to reclaim
+     * 
+     * @hide
+     */
+    public static void flushCaches(int level) {
+        nFlushCaches(level);
+    }
+
+    private static native void nFlushCaches(int level);
+
     ///////////////////////////////////////////////////////////////////////////
     // Display list
     ///////////////////////////////////////////////////////////////////////////
 
-    int getDisplayList() {
-        return nGetDisplayList(mRenderer);
+    int getDisplayList(int displayList) {
+        return nGetDisplayList(mRenderer, displayList);
     }
 
-    private static native int nGetDisplayList(int renderer);
+    private static native int nGetDisplayList(int renderer, int displayList);
     
     static void destroyDisplayList(int displayList) {
         nDestroyDisplayList(displayList);
@@ -302,10 +330,16 @@
 
     private static native void nDestroyDisplayList(int displayList);
 
+    static int getDisplayListSize(int displayList) {
+        return nGetDisplayListSize(displayList);
+    }
+
+    private static native int nGetDisplayListSize(int displayList);
+
     @Override
     public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) {
         return nDrawDisplayList(mRenderer,
-                ((GLES20DisplayList) displayList).mNativeDisplayList, width, height, dirty);
+                ((GLES20DisplayList) displayList).getNativeDisplayList(), width, height, dirty);
     }
 
     private static native boolean nDrawDisplayList(int renderer, int displayList,
@@ -313,7 +347,7 @@
 
     @Override
     void outputDisplayList(DisplayList displayList) {
-        nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+        nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
     }
 
     private static native void nOutputDisplayList(int renderer, int displayList);
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index aeff31f..4ca5e98 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,52 +16,50 @@
 
 package android.view;
 
-import java.lang.ref.WeakReference;
+import android.graphics.Bitmap;
+
+import java.util.ArrayList;
 
 /**
  * An implementation of display list for OpenGL ES 2.0.
  */
 class GLES20DisplayList extends DisplayList {
-    private GLES20Canvas mCanvas;
+    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
+    // as the DisplayList is alive.  The Bitmaps are populated by the GLES20RecordingCanvas.
+    final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
 
-    private boolean mStarted = false;
-    private boolean mRecorded = false;
-    private boolean mValid = false;
-
-    int mNativeDisplayList;
-    WeakReference<View> hostView;
+    private GLES20RecordingCanvas mCanvas;
+    private boolean mValid;
 
     // The native display list will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
-    @SuppressWarnings("unused")
     private DisplayListFinalizer mFinalizer;
 
-    public GLES20DisplayList(View view) {
-        hostView = new WeakReference<View>(view);
+    int getNativeDisplayList() {
+        if (!mValid || mFinalizer == null) {
+            throw new IllegalStateException("The display list is not valid.");
+        }
+        return mFinalizer.mNativeDisplayList;
     }
 
     @Override
     HardwareCanvas start() {
-        if (mStarted) {
+        if (mCanvas != null) {
             throw new IllegalStateException("Recording has already started");
         }
 
-        if (mCanvas != null) {
-            ((GLES20RecordingCanvas) mCanvas).reset();
-        } else {
-            mCanvas = new GLES20RecordingCanvas(true);
-        }
-        mStarted = true;
-        mRecorded = false;
-        mValid = true;
-
+        mValid = false;
+        mCanvas = GLES20RecordingCanvas.obtain(this);
+        mCanvas.start();
         return mCanvas;
     }
 
     @Override
     void invalidate() {
-        mStarted = false;
-        mRecorded = false;
+        if (mCanvas != null) {
+            mCanvas.recycle();
+            mCanvas = null;
+        }
         mValid = false;
     }
 
@@ -73,48 +71,34 @@
     @Override
     void end() {
         if (mCanvas != null) {
-            mStarted = false;
-            mRecorded = true;
-
-            mNativeDisplayList = mCanvas.getDisplayList();
-            mFinalizer = DisplayListFinalizer.getFinalizer(mFinalizer, mNativeDisplayList);
+            if (mFinalizer != null) {
+                mCanvas.end(mFinalizer.mNativeDisplayList);
+            } else {
+                mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
+            }
+            mCanvas.recycle();
+            mCanvas = null;
+            mValid = true;
         }
     }
 
     @Override
-    boolean isReady() {
-        return !mStarted && mRecorded;
+    int getSize() {
+        if (mFinalizer == null) return 0;
+        return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList);
     }
 
     private static class DisplayListFinalizer {
-        int mNativeDisplayList;
+        final int mNativeDisplayList;
 
-        // Factory method returns new instance if old one is null, or old instance
-        // otherwise, destroying native display list along the way as necessary
-        static DisplayListFinalizer getFinalizer(DisplayListFinalizer oldFinalizer,
-                int nativeDisplayList) {
-            if (oldFinalizer == null) {
-                return new DisplayListFinalizer(nativeDisplayList);
-            }
-            oldFinalizer.replaceNativeObject(nativeDisplayList);
-            return oldFinalizer;
-        }
-
-        private DisplayListFinalizer(int nativeDisplayList) {
+        public DisplayListFinalizer(int nativeDisplayList) {
             mNativeDisplayList = nativeDisplayList;
         }
 
-        private void replaceNativeObject(int newNativeDisplayList) {
-            if (mNativeDisplayList != 0 && mNativeDisplayList != newNativeDisplayList) {
-                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
-            }
-            mNativeDisplayList = newNativeDisplayList;
-        }
-
         @Override
         protected void finalize() throws Throwable {
             try {
-                replaceNativeObject(0);
+                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
             } finally {
                 super.finalize();
             }
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index ec94fe7..c987f48 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -24,8 +24,10 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Shader;
-
-import java.util.ArrayList;
+import android.util.Pool;
+import android.util.Poolable;
+import android.util.PoolableManager;
+import android.util.Pools;
 
 /**
  * An implementation of a GL canvas that records drawing operations.
@@ -33,62 +35,94 @@
  * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
  * the DisplayList is still holding a native reference to the memory.
  */
-class GLES20RecordingCanvas extends GLES20Canvas {
-    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
-    // as the DisplayList is alive.
-    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
-    private final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
+class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {
+    // The recording canvas pool should be large enough to handle a deeply nested
+    // view hierarchy because display lists are generated recursively.
+    private static final int POOL_LIMIT = 25;
 
-    GLES20RecordingCanvas(boolean translucent) {
-        super(true, translucent);
+    private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(
+            Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {
+                public GLES20RecordingCanvas newInstance() {
+                    return new GLES20RecordingCanvas();
+                }
+                @Override
+                public void onAcquired(GLES20RecordingCanvas element) {
+                }
+                @Override
+                public void onReleased(GLES20RecordingCanvas element) {
+                }
+            }, POOL_LIMIT));
+
+    private GLES20RecordingCanvas mNextPoolable;
+    private boolean mIsPooled;
+
+    private GLES20DisplayList mDisplayList;
+
+    private GLES20RecordingCanvas() {
+        super(true /*record*/, true /*translucent*/);
+    }
+
+    static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) {
+        GLES20RecordingCanvas canvas = sPool.acquire();
+        canvas.mDisplayList = displayList;
+        return canvas;
+    }
+
+    void recycle() {
+        mDisplayList = null;
+        resetDisplayListRenderer();
+        sPool.release(this);
+    }
+
+    void start() {
+        mDisplayList.mBitmaps.clear();
+    }
+
+    int end(int nativeDisplayList) {
+        return getDisplayList(nativeDisplayList);
     }
 
     private void recordShaderBitmap(Paint paint) {
         if (paint != null) {
             final Shader shader = paint.getShader();
             if (shader instanceof BitmapShader) {
-                mBitmaps.add(((BitmapShader) shader).mBitmap);
+                mDisplayList.mBitmaps.add(((BitmapShader) shader).mBitmap);
             }
         }
     }
 
-    void reset() {
-        mBitmaps.clear();
-        setupRenderer(true);
-    }
-
     @Override
     public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
         super.drawPatch(bitmap, chunks, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         super.drawBitmap(bitmap, left, top, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
         super.drawBitmap(bitmap, matrix, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
         super.drawBitmap(bitmap, src, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
         super.drawBitmap(bitmap, src, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
@@ -111,7 +145,7 @@
             int vertOffset, int[] colors, int colorOffset, Paint paint) {
         super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
                 paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
@@ -270,4 +304,24 @@
                 colorOffset, indices, indexOffset, indexCount, paint);
         recordShaderBitmap(paint);
     }
+
+    @Override
+    public GLES20RecordingCanvas getNextPoolable() {
+        return mNextPoolable;
+    }
+
+    @Override
+    public void setNextPoolable(GLES20RecordingCanvas element) {
+        mNextPoolable = element;
+    }
+
+    @Override
+    public boolean isPooled() {
+        return mIsPooled;
+    }
+
+    @Override
+    public void setPooled(boolean isPooled) {
+        mIsPooled = isPooled;
+    }
 }
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index 7adac1c..41f16e2 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -24,7 +24,6 @@
  * {@link Canvas} that can be used to render into an FBO using OpenGL.
  */
 class GLES20RenderLayer extends GLES20Layer {
-
     private int mLayerWidth;
     private int mLayerHeight;
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 011e44c..4e4923b 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -17,6 +17,7 @@
 
 package android.view;
 
+import android.content.ComponentCallbacks;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
@@ -32,6 +33,8 @@
 import javax.microedition.khronos.egl.EGLSurface;
 import javax.microedition.khronos.opengles.GL;
 
+import static javax.microedition.khronos.egl.EGL10.*;
+
 /**
  * Interface for rendering a ViewAncestor using hardware acceleration.
  * 
@@ -69,6 +72,15 @@
     static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
 
     /**
+     * System property used to debug EGL configuration choice.
+     * 
+     * Possible values:
+     * "choice", print the chosen configuration only
+     * "all", print all possible configurations
+     */
+    static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";    
+
+    /**
      * Turn on to draw dirty regions every other frame.
      */
     private static final boolean DEBUG_DIRTY_REGION = false;
@@ -128,6 +140,13 @@
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
+     * Destoys the layers used by the specified view hierarchy.
+     * 
+     * @param view The root of the view hierarchy
+     */
+    abstract void destroyLayers(View view);
+
+    /**
      * This method should be invoked whenever the current hardware renderer
      * context should be reset. 
      */
@@ -188,7 +207,7 @@
      * 
      * @return A new display list.
      */
-    abstract DisplayList createDisplayList(View v);
+    abstract DisplayList createDisplayList();
 
     /**
      * Creates a new hardware layer. A hardware layer built by calling this
@@ -263,6 +282,18 @@
     }
 
     /**
+     * Invoke this method when the system is running out of memory. This
+     * method will attempt to recover as much memory as possible, based on
+     * the specified hint.
+     * 
+     * @param level Hint about the amount of memory that should be trimmed,
+     *              see {@link android.content.ComponentCallbacks}
+     */
+    static void trimMemory(int level) {
+        Gl20Renderer.trimMemory(level);
+    }
+
+    /**
      * Indicates whether hardware acceleration is currently enabled.
      * 
      * @return True if hardware acceleration is in use, false otherwise.
@@ -312,12 +343,15 @@
         private static final int SURFACE_STATE_SUCCESS = 1;
         private static final int SURFACE_STATE_UPDATED = 2;
         
-        static EGLContext sEglContext;
         static EGL10 sEgl;
         static EGLDisplay sEglDisplay;
         static EGLConfig sEglConfig;
+        static final Object[] sEglLock = new Object[0];
 
-        private static Thread sEglThread;
+        static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>();
+
+        EGLContext mEglContext;
+        Thread mEglThread;
 
         EGLSurface mEglSurface;
         
@@ -342,7 +376,7 @@
         final boolean mTranslucent;
 
         private boolean mDestroyed;
-        
+
         private final Rect mRedrawClip = new Rect();
 
         GlRenderer(int glVersion, boolean translucent) {
@@ -373,33 +407,33 @@
          */
         static String getEGLErrorString(int error) {
             switch (error) {
-                case EGL10.EGL_SUCCESS:
+                case EGL_SUCCESS:
                     return "EGL_SUCCESS";
-                case EGL10.EGL_NOT_INITIALIZED:
+                case EGL_NOT_INITIALIZED:
                     return "EGL_NOT_INITIALIZED";
-                case EGL10.EGL_BAD_ACCESS:
+                case EGL_BAD_ACCESS:
                     return "EGL_BAD_ACCESS";
-                case EGL10.EGL_BAD_ALLOC:
+                case EGL_BAD_ALLOC:
                     return "EGL_BAD_ALLOC";
-                case EGL10.EGL_BAD_ATTRIBUTE:
+                case EGL_BAD_ATTRIBUTE:
                     return "EGL_BAD_ATTRIBUTE";
-                case EGL10.EGL_BAD_CONFIG:
+                case EGL_BAD_CONFIG:
                     return "EGL_BAD_CONFIG";
-                case EGL10.EGL_BAD_CONTEXT:
+                case EGL_BAD_CONTEXT:
                     return "EGL_BAD_CONTEXT";
-                case EGL10.EGL_BAD_CURRENT_SURFACE:
+                case EGL_BAD_CURRENT_SURFACE:
                     return "EGL_BAD_CURRENT_SURFACE";
-                case EGL10.EGL_BAD_DISPLAY:
+                case EGL_BAD_DISPLAY:
                     return "EGL_BAD_DISPLAY";
-                case EGL10.EGL_BAD_MATCH:
+                case EGL_BAD_MATCH:
                     return "EGL_BAD_MATCH";
-                case EGL10.EGL_BAD_NATIVE_PIXMAP:
+                case EGL_BAD_NATIVE_PIXMAP:
                     return "EGL_BAD_NATIVE_PIXMAP";
-                case EGL10.EGL_BAD_NATIVE_WINDOW:
+                case EGL_BAD_NATIVE_WINDOW:
                     return "EGL_BAD_NATIVE_WINDOW";
-                case EGL10.EGL_BAD_PARAMETER:
+                case EGL_BAD_PARAMETER:
                     return "EGL_BAD_PARAMETER";
-                case EGL10.EGL_BAD_SURFACE:
+                case EGL_BAD_SURFACE:
                     return "EGL_BAD_SURFACE";
                 case EGL11.EGL_CONTEXT_LOST:
                     return "EGL_CONTEXT_LOST";
@@ -416,7 +450,7 @@
         void checkEglErrors() {
             if (isEnabled()) {
                 int error = sEgl.eglGetError();
-                if (error != EGL10.EGL_SUCCESS) {
+                if (error != EGL_SUCCESS) {
                     // something bad has happened revert to
                     // normal rendering.
                     fallback(error != EGL11.EGL_CONTEXT_LOST);
@@ -444,7 +478,7 @@
 
                 if (mGl != null) {
                     int err = sEgl.eglGetError();
-                    if (err != EGL10.EGL_SUCCESS) {
+                    if (err != EGL_SUCCESS) {
                         destroy(true);
                         setRequested(false);
                     } else {
@@ -473,62 +507,111 @@
 
         abstract GLES20Canvas createCanvas();
 
+        abstract int[] getConfig(boolean dirtyRegions);
+
         void initializeEgl() {
-            if (sEglContext != null) return;
-
-            sEglThread = Thread.currentThread();
-            sEgl = (EGL10) EGLContext.getEGL();
-            
-            // Get to the default display.
-            sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-            
-            if (sEglDisplay == EGL10.EGL_NO_DISPLAY) {
-                throw new RuntimeException("eglGetDisplay failed "
-                        + getEGLErrorString(sEgl.eglGetError()));
-            }
-            
-            // We can now initialize EGL for that display
-            int[] version = new int[2];
-            if (!sEgl.eglInitialize(sEglDisplay, version)) {
-                throw new RuntimeException("eglInitialize failed " +
-                        getEGLErrorString(sEgl.eglGetError()));
-            }
-
-            sEglConfig = chooseEglConfig();
-            if (sEglConfig == null) {
-                // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-                if (sDirtyRegions) {
-                    sDirtyRegions = false;
+            synchronized (sEglLock) {
+                if (sEgl == null && sEglConfig == null) {
+                    sEgl = (EGL10) EGLContext.getEGL();
+                    
+                    // Get to the default display.
+                    sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                    
+                    if (sEglDisplay == EGL_NO_DISPLAY) {
+                        throw new RuntimeException("eglGetDisplay failed "
+                                + getEGLErrorString(sEgl.eglGetError()));
+                    }
+                    
+                    // We can now initialize EGL for that display
+                    int[] version = new int[2];
+                    if (!sEgl.eglInitialize(sEglDisplay, version)) {
+                        throw new RuntimeException("eglInitialize failed " +
+                                getEGLErrorString(sEgl.eglGetError()));
+                    }
+        
                     sEglConfig = chooseEglConfig();
                     if (sEglConfig == null) {
-                        throw new RuntimeException("eglConfig not initialized");
+                        // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
+                        if (sDirtyRegions) {
+                            sDirtyRegions = false;
+                            sEglConfig = chooseEglConfig();
+                            if (sEglConfig == null) {
+                                throw new RuntimeException("eglConfig not initialized");
+                            }
+                        } else {
+                            throw new RuntimeException("eglConfig not initialized");
+                        }
                     }
-                } else {
-                    throw new RuntimeException("eglConfig not initialized");
                 }
             }
-            
-            /*
-            * Create an EGL context. We want to do this as rarely as we can, because an
-            * EGL context is a somewhat heavy object.
-            */
-            sEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
+
+            mEglContext = sEglContextStorage.get();
+            mEglThread = Thread.currentThread();
+
+            if (mEglContext == null) {
+                mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
+                sEglContextStorage.set(mEglContext);
+            }
         }
 
         private EGLConfig chooseEglConfig() {
-            int[] configsCount = new int[1];
             EGLConfig[] configs = new EGLConfig[1];
+            int[] configsCount = new int[1];
             int[] configSpec = getConfig(sDirtyRegions);
+
+            // Debug
+            final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
+            if ("all".equalsIgnoreCase(debug)) {
+                sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
+
+                EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
+                sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
+                        configsCount[0], configsCount);
+
+                for (EGLConfig config : debugConfigs) {
+                    printConfig(config);
+                }
+            }
+
             if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
                 throw new IllegalArgumentException("eglChooseConfig failed " +
                         getEGLErrorString(sEgl.eglGetError()));
             } else if (configsCount[0] > 0) {
+                if ("choice".equalsIgnoreCase(debug)) {
+                    printConfig(configs[0]);
+                }
                 return configs[0];
             }
+
             return null;
         }
 
-        abstract int[] getConfig(boolean dirtyRegions);
+        private void printConfig(EGLConfig config) {
+            int[] value = new int[1];
+
+            Log.d(LOG_TAG, "EGL configuration " + config + ":");
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
+            Log.d(LOG_TAG, "  RED_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
+            Log.d(LOG_TAG, "  GREEN_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
+            Log.d(LOG_TAG, "  BLUE_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
+            Log.d(LOG_TAG, "  ALPHA_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
+            Log.d(LOG_TAG, "  DEPTH_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
+            Log.d(LOG_TAG, "  STENCIL_SIZE = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
+            Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
+        }
 
         GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
             // Check preconditions.
@@ -541,31 +624,20 @@
             if (sEglConfig == null) {
                 throw new RuntimeException("eglConfig not initialized");
             }
-            if (Thread.currentThread() != sEglThread) {
+            if (Thread.currentThread() != mEglThread) {
                 throw new IllegalStateException("HardwareRenderer cannot be used " 
                         + "from multiple threads");
             }
 
-            /*
-             *  The window size has changed, so we need to create a new
-             *  surface.
-             */
-            if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
-                /*
-                 * Unbind and destroy the old EGL surface, if
-                 * there is one.
-                 */
-                sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            }
+            // In case we need to destroy an existing surface
+            destroySurface();
 
             // Create an EGL surface we can render into.
             mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null);
 
-            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
                 int error = sEgl.eglGetError();
-                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+                if (error == EGL_BAD_NATIVE_WINDOW) {
                     Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
                     return null;
                 }
@@ -577,7 +649,7 @@
              * Before we can issue GL commands, we need to make sure
              * the context is current and bound to a surface.
              */
-            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
+            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                 throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
                         + getEGLErrorString(sEgl.eglGetError()));
             }
@@ -598,26 +670,17 @@
                 mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
             }
 
-            return sEglContext.getGL();
+            return mEglContext.getGL();
         }
 
         EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL10.EGL_NONE };
+            int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
 
-            return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT,
-                    mGlVersion != 0 ? attrib_list : null);            
+            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
+                    mGlVersion != 0 ? attribs : null);            
         }
 
         @Override
-        void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
-                SurfaceHolder holder) throws Surface.OutOfResourcesException {
-            if (isRequested()) {
-                checkEglErrors();
-                super.initializeIfNeeded(width, height, attachInfo, holder);
-            }
-        }
-        
-        @Override
         void destroy(boolean full) {
             if (full && mCanvas != null) {
                 mCanvas = null;
@@ -627,22 +690,27 @@
 
             mDestroyed = true;
 
-            sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
-                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+            destroySurface();
 
-            mEglSurface = null;
             mGl = null;
 
             setEnabled(false);
         }
 
+        void destroySurface() {
+            if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
+                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+                mEglSurface = null;
+            }
+        }
+
         @Override
         void invalidate() {
             // 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);
+            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
         }
         
         @Override
@@ -652,6 +720,7 @@
 
         @Override
         void setup(int width, int height) {
+            checkCurrent();
             mCanvas.setViewport(width, height);
         }
 
@@ -739,22 +808,22 @@
         }
 
         /**
-         * Ensures the currnet EGL context is the one we expect.
+         * Ensures the current EGL context is the one we expect.
          * 
          * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
          *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
          *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
          */
-        private int checkCurrent() {
-            if (sEglThread != Thread.currentThread()) {
+        int checkCurrent() {
+            if (mEglThread != Thread.currentThread()) {
                 throw new IllegalStateException("Hardware acceleration can only be used with a " +
-                        "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
+                        "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
                         "Current thread: " + Thread.currentThread());
             }
 
-            if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
-                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
-                if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
+            if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
+                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
+                if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                     fallback(true);
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
                             getEGLErrorString(sEgl.eglGetError()));
@@ -773,6 +842,9 @@
     static class Gl20Renderer extends GlRenderer {
         private GLES20Canvas mGlCanvas;
 
+        private static EGLSurface sPbuffer;
+        private static final Object[] sPbufferLock = new Object[0];
+
         Gl20Renderer(boolean translucent) {
             super(2, translucent);
         }
@@ -785,16 +857,16 @@
         @Override
         int[] getConfig(boolean dirtyRegions) {
             return new int[] {
-                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                    EGL10.EGL_RED_SIZE, 8,
-                    EGL10.EGL_GREEN_SIZE, 8,
-                    EGL10.EGL_BLUE_SIZE, 8,
-                    EGL10.EGL_ALPHA_SIZE, 8,
-                    EGL10.EGL_DEPTH_SIZE, 0,
-                    EGL10.EGL_STENCIL_SIZE, 0,
-                    EGL_SURFACE_TYPE, EGL10.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_DEPTH_SIZE, 0,
+                    EGL_STENCIL_SIZE, 0,
+                    EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
                             (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
-                    EGL10.EGL_NONE
+                    EGL_NONE
             };
         }
 
@@ -833,8 +905,8 @@
         }
 
         @Override
-        DisplayList createDisplayList(View v) {
-            return new GLES20DisplayList(v);
+        DisplayList createDisplayList() {
+            return new GLES20DisplayList();
         }
 
         @Override
@@ -852,11 +924,64 @@
             return ((GLES20TextureLayer) layer).getSurfaceTexture();
         }
 
+        @Override
+        void destroyLayers(View view) {
+            if (view != null && isEnabled()) {
+                checkCurrent();
+                destroyHardwareLayer(view);
+                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+            }
+        }
+
+        private void destroyHardwareLayer(View view) {
+            if (view.destroyLayer()) {
+                view.invalidate(true);
+            }
+            if (view instanceof ViewGroup) {
+                ViewGroup group = (ViewGroup) view;
+
+                int count = group.getChildCount();
+                for (int i = 0; i < count; i++) {
+                    destroyHardwareLayer(group.getChildAt(i));
+                }
+            }
+        }
+
         static HardwareRenderer create(boolean translucent) {
             if (GLES20Canvas.isAvailable()) {
                 return new Gl20Renderer(translucent);
             }
             return null;
         }
+
+        static void trimMemory(int level) {
+            if (sEgl == null || sEglConfig == null) return;
+
+            EGLContext eglContext = sEglContextStorage.get();
+            // We do not have OpenGL objects
+            if (eglContext == null) {
+                return;
+            } else {
+                synchronized (sPbufferLock) {
+                    // Create a temporary 1x1 pbuffer so we have a context
+                    // to clear our OpenGL objects
+                    if (sPbuffer == null) {
+                        sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
+                                EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
+                        });
+                    }
+                }
+                sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
+            }
+
+            switch (level) {
+                case ComponentCallbacks.TRIM_MEMORY_MODERATE:
+                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
+                    break;
+                case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
+                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
+                    break;
+            }
+        }
     }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index ad17edf..81cd798 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -55,6 +55,7 @@
     boolean inputMethodClientHasFocus(IInputMethodClient client);
     
     void getDisplaySize(out Point size);
+    void getRealDisplaySize(out Point size);
     int getMaximumSizeDimension();
 
     void setForcedDisplaySize(int longDimen, int shortDimen);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 88f59d4..da5c7b2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1123,7 +1123,10 @@
     }
 
     /**
-     * Button constant: Primary button (left mouse button, stylus tip).
+     * Button constant: Primary button (left mouse button).
+     *
+     * This button constant is not set in response to simple touches with a finger
+     * or stylus tip.  The user must actually push a button.
      *
      * @see #getButtonState
      */
@@ -1215,55 +1218,32 @@
     public static final int TOOL_TYPE_UNKNOWN = 0;
 
     /**
-     * Tool type constant: The tool is a finger directly touching the display.
-     *
-     * This is a <em>direct</em> positioning tool.
+     * Tool type constant: The tool is a finger.
      *
      * @see #getToolType
      */
     public static final int TOOL_TYPE_FINGER = 1;
 
     /**
-     * Tool type constant: The tool is a stylus directly touching the display
-     * or hovering slightly above it.
-     *
-     * This is a <em>direct</em> positioning tool.
+     * Tool type constant: The tool is a stylus.
      *
      * @see #getToolType
      */
     public static final int TOOL_TYPE_STYLUS = 2;
 
     /**
-     * Tool type constant: The tool is a mouse or trackpad that translates
-     * relative motions into cursor movements on the display.
-     *
-     * This is an <em>indirect</em> positioning tool.
+     * Tool type constant: The tool is a mouse or trackpad.
      *
      * @see #getToolType
      */
     public static final int TOOL_TYPE_MOUSE = 3;
 
     /**
-     * Tool type constant: The tool is a finger on a touch pad that is not
-     * directly attached to the display.  Finger movements on the touch pad
-     * may be translated into touches on the display, possibly with visual feedback.
-     *
-     * This is an <em>indirect</em> positioning tool.
+     * Tool type constant: The tool is an eraser or a stylus being used in an inverted posture.
      *
      * @see #getToolType
      */
-    public static final int TOOL_TYPE_INDIRECT_FINGER = 4;
-
-    /**
-     * Tool type constant: The tool is a stylus on a digitizer tablet that is not
-     * attached to the display.  Stylus movements on the digitizer may be translated
-     * into touches on the display, possibly with visual feedback.
-     *
-     * This is an <em>indirect</em> positioning tool.
-     *
-     * @see #getToolType
-     */
-    public static final int TOOL_TYPE_INDIRECT_STYLUS = 5;
+    public static final int TOOL_TYPE_ERASER = 4;
 
     // NOTE: If you add a new tool type here you must also add it to:
     //  native/include/android/input.h
@@ -1276,8 +1256,7 @@
         names.append(TOOL_TYPE_FINGER, "TOOL_TYPE_FINGER");
         names.append(TOOL_TYPE_STYLUS, "TOOL_TYPE_STYLUS");
         names.append(TOOL_TYPE_MOUSE, "TOOL_TYPE_MOUSE");
-        names.append(TOOL_TYPE_INDIRECT_FINGER, "TOOL_TYPE_INDIRECT_FINGER");
-        names.append(TOOL_TYPE_INDIRECT_STYLUS, "TOOL_TYPE_INDIRECT_STYLUS");
+        names.append(TOOL_TYPE_ERASER, "TOOL_TYPE_ERASER");
     }
 
     // Private value for history pos that obtains the current sample.
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index c913bb3..836867b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -161,6 +161,9 @@
      */
     public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001;
 
+    // The mSurfaceControl will only be present for Surfaces used by the window
+    // server or system processes. When this class is parceled we defer to the
+    // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface.
     @SuppressWarnings("unused")
     private int mSurfaceControl;
     @SuppressWarnings("unused")
@@ -202,6 +205,19 @@
     native private static void nativeClassInit();
     static { nativeClassInit(); }
 
+    /**
+     * Create Surface from a SurfaceTexture.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
+     * @hide
+     */
+    public Surface(SurfaceTexture surfaceTexture) {
+        if (DEBUG_RELEASE) {
+            mCreationStack = new Exception();
+        }
+        mCanvas = new CompatibleCanvas();
+        initFromSurfaceTexture(surfaceTexture);
+    }
     
     /**
      * create a surface
@@ -505,5 +521,7 @@
 
     private native void init(Parcel source);
 
+    private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
+
     private native int getIdentity();
 }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 764899f..cbdb38e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -426,7 +426,7 @@
         if (!mHaveFrame) {
             return;
         }
-        ViewAncestor viewRoot = (ViewAncestor) getRootView().getParent();
+        ViewRootImpl viewRoot = (ViewRootImpl) getRootView().getParent();
         if (viewRoot != null) {
             mTranslator = viewRoot.mTranslator;
         }
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index d656f31..96d6f09 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -107,6 +108,14 @@
 
     private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
 
+    private Canvas mCanvas;
+    private int mSaveCount;
+
+    private final Object[] mNativeWindowLock = new Object[0];
+    // Used from native code, do not write!
+    @SuppressWarnings({"UnusedDeclaration"})
+    private int mNativeWindow;
+
     /**
      * Creates a new TextureView.
      * 
@@ -190,7 +199,11 @@
                 mListener.onSurfaceTextureDestroyed(mSurface);
             }
 
-            mLayer.destroy();            
+            synchronized (mNativeWindowLock) {
+                nDestroyNativeWindow();
+            }
+
+            mLayer.destroy();
             mSurface = null;
             mLayer = null;
         }
@@ -274,6 +287,7 @@
             mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
             mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
+            nCreateNativeWindow(mSurface);            
 
             mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
                 @Override
@@ -431,6 +445,79 @@
     }
 
     /**
+     * <p>Start editing the pixels in the surface.  The returned Canvas can be used
+     * to draw into the surface's bitmap.  A null is returned if the surface has
+     * not been created or otherwise cannot be edited. You will usually need
+     * to implement
+     * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)}
+     * to find out when the Surface is available for use.</p>
+     * 
+     * <p>The content of the Surface is never preserved between unlockCanvas()
+     * and lockCanvas(), for this reason, every pixel within the Surface area
+     * must be written. The only exception to this rule is when a dirty
+     * rectangle is specified, in which case, non-dirty pixels will be
+     * preserved.</p>
+     * 
+     * @return A Canvas used to draw into the surface.
+     * 
+     * @see #lockCanvas(android.graphics.Rect) 
+     * @see #unlockCanvasAndPost(android.graphics.Canvas) 
+     */
+    public Canvas lockCanvas() {
+        return lockCanvas(null);
+    }
+
+    /**
+     * Just like {@link #lockCanvas()} but allows specification of a dirty
+     * rectangle. Every pixel within that rectangle must be written; however
+     * pixels outside the dirty rectangle will be preserved by the next call
+     * to lockCanvas().
+     * 
+     * @param dirty Area of the surface that will be modified.
+
+     * @return A Canvas used to draw into the surface.
+     * 
+     * @see #lockCanvas() 
+     * @see #unlockCanvasAndPost(android.graphics.Canvas) 
+     */
+    public Canvas lockCanvas(Rect dirty) {
+        if (!isAvailable()) return null;
+
+        if (mCanvas == null) {
+            mCanvas = new Canvas();
+        }
+
+        synchronized (mNativeWindowLock) {
+            nLockCanvas(mNativeWindow, mCanvas, dirty);
+        }
+        mSaveCount = mCanvas.save();
+
+        return mCanvas;
+    }
+
+    /**
+     * Finish editing pixels in the surface. After this call, the surface's
+     * current pixels will be shown on the screen, but its content is lost,
+     * in particular there is no guarantee that the content of the Surface
+     * will remain unchanged when lockCanvas() is called again.
+     * 
+     * @param canvas The Canvas previously returned by lockCanvas()
+     * 
+     * @see #lockCanvas()
+     * @see #lockCanvas(android.graphics.Rect) 
+     */
+    public void unlockCanvasAndPost(Canvas canvas) {
+        if (mCanvas != null && canvas == mCanvas) {
+            canvas.restoreToCount(mSaveCount);
+            mSaveCount = 0;
+
+            synchronized (mNativeWindowLock) {
+                nUnlockCanvasAndPost(mNativeWindow, mCanvas);
+            }
+        }
+    }
+
+    /**
      * Returns the {@link SurfaceTexture} used by this view. This method
      * may return null if the view is not attached to a window or if the surface
      * texture has not been initialized yet.
@@ -506,6 +593,12 @@
         public void onSurfaceTextureUpdated(SurfaceTexture surface);
     }
 
+    private native void nCreateNativeWindow(SurfaceTexture surface);
+    private native void nDestroyNativeWindow();
+
     private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture,
             int width, int height);
+
+    private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty);
+    private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 74dc100..296e6be 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,13 +16,6 @@
 
 package android.view;
 
-import android.util.FloatProperty;
-import android.util.LocaleUtil;
-import android.util.Property;
-import com.android.internal.R;
-import com.android.internal.util.Predicate;
-import com.android.internal.view.menu.MenuBuilder;
-
 import android.content.ClipData;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -53,11 +46,14 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.LocaleUtil;
 import android.util.Log;
 import android.util.Pool;
 import android.util.Poolable;
 import android.util.PoolableManager;
 import android.util.Pools;
+import android.util.Property;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -72,6 +68,10 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.ScrollBarDrawable;
 
+import com.android.internal.R;
+import com.android.internal.util.Predicate;
+import com.android.internal.view.menu.MenuBuilder;
+
 import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -607,8 +607,6 @@
  * @attr ref android.R.styleable#View_paddingLeft
  * @attr ref android.R.styleable#View_paddingRight
  * @attr ref android.R.styleable#View_paddingTop
- * @attr ref android.R.styleable#View_paddingStart
- * @attr ref android.R.styleable#View_paddingEnd
  * @attr ref android.R.styleable#View_saveEnabled
  * @attr ref android.R.styleable#View_rotation
  * @attr ref android.R.styleable#View_rotationX
@@ -674,19 +672,23 @@
     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
 
     /**
-     * This view is visible.  Use with {@link #setVisibility(int)}.
+     * This view is visible.
+     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+     * android:visibility}.
      */
     public static final int VISIBLE = 0x00000000;
 
     /**
      * This view is invisible, but it still takes up space for layout purposes.
-     * Use with {@link #setVisibility(int)}.
+     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+     * android:visibility}.
      */
     public static final int INVISIBLE = 0x00000004;
 
     /**
      * This view is invisible, and it doesn't take any space for layout
-     * purposes. Use with {@link #setVisibility(int)}.
+     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+     * android:visibility}.
      */
     public static final int GONE = 0x00000008;
 
@@ -2167,21 +2169,27 @@
 
     /**
      * Cache the paddingRight set by the user to append to the scrollbar's size.
+     *
+     * @hide
      */
     @ViewDebug.ExportedProperty(category = "padding")
-    int mUserPaddingRight;
+    protected int mUserPaddingRight;
 
     /**
      * Cache the paddingBottom set by the user to append to the scrollbar's size.
+     *
+     * @hide
      */
     @ViewDebug.ExportedProperty(category = "padding")
-    int mUserPaddingBottom;
+    protected int mUserPaddingBottom;
 
     /**
      * Cache the paddingLeft set by the user to append to the scrollbar's size.
+     *
+     * @hide
      */
     @ViewDebug.ExportedProperty(category = "padding")
-    int mUserPaddingLeft;
+    protected int mUserPaddingLeft;
 
     /**
      * Cache if the user padding is relative.
@@ -2290,8 +2298,8 @@
 
     private Bitmap mDrawingCache;
     private Bitmap mUnscaledDrawingCache;
-    private DisplayList mDisplayList;
     private HardwareLayer mHardwareLayer;
+    DisplayList mDisplayList;
 
     /**
      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -2493,12 +2501,6 @@
     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
      */
@@ -2507,7 +2509,7 @@
     /**
      * 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.
+     * paragraph direction is the view's resolved ayout direction.
      *
      * @hide
      */
@@ -2516,7 +2518,7 @@
     /**
      * 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.
+     * If there are neither, the paragraph direction is the view's resolved layout direction.
      *
      * @hide
      */
@@ -2560,7 +2562,6 @@
      * {@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"),
@@ -2568,21 +2569,25 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
     })
-    protected int mTextDirection = DEFAULT_TEXT_DIRECTION;
+    private 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}.
+     * The resolved text direction.  This needs resolution if the value is
+     * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if that is
+     * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
+     * chain of the view.
      *
      * {@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 mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+    private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -3902,6 +3907,7 @@
 
         int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
         getLocationOnScreen(locationOnScreen);
+        bounds.offsetTo(0, 0);
         bounds.offset(locationOnScreen[0], locationOnScreen[1]);
         info.setBoundsInScreen(bounds);
 
@@ -4279,6 +4285,36 @@
     }
 
     /**
+     * Set whether or not this view should account for system screen decorations
+     * such as the status bar and inset its content. This allows this view to be
+     * positioned in absolute screen coordinates and remain visible to the user.
+     *
+     * <p>This should only be used by top-level window decor views.
+     *
+     * @param fitSystemWindows true to inset content for system screen decorations, false for
+     *                         default behavior.
+     *
+     * @attr ref android.R.styleable#View_fitsSystemWindows
+     */
+    public void setFitsSystemWindows(boolean fitSystemWindows) {
+        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
+    }
+
+    /**
+     * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
+     * will account for system screen decorations such as the status bar and inset its
+     * content. This allows the view to be positioned in absolute screen coordinates
+     * and remain visible to the user.
+     *
+     * @return true if this view will adjust its content bounds for system screen decorations.
+     *
+     * @attr ref android.R.styleable#View_fitsSystemWindows
+     */
+    public boolean fitsSystemWindows() {
+        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
+    }
+
+    /**
      * Returns the visibility status for this view.
      *
      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -5040,9 +5076,9 @@
     }
 
     /** Gets the ViewAncestor, or null if not attached. */
-    /*package*/ ViewAncestor getViewAncestor() {
+    /*package*/ ViewRootImpl getViewRootImpl() {
         View root = getRootView();
-        return root != null ? (ViewAncestor)root.getParent() : null;
+        return root != null ? (ViewRootImpl)root.getParent() : null;
     }
 
     /**
@@ -5058,7 +5094,7 @@
     public final boolean requestFocusFromTouch() {
         // Leave touch mode if we need to
         if (isInTouchMode()) {
-            ViewAncestor viewRoot = getViewAncestor();
+            ViewRootImpl viewRoot = getViewRootImpl();
             if (viewRoot != null) {
                 viewRoot.ensureTouchMode(false);
             }
@@ -5650,7 +5686,7 @@
         if (mAttachInfo != null) {
             return mAttachInfo.mInTouchMode;
         } else {
-            return ViewAncestor.isInTouchMode();
+            return ViewRootImpl.isInTouchMode();
         }
     }
 
@@ -8251,7 +8287,7 @@
             handler = attachInfo.mHandler;
         } else {
             // Assume that post will succeed later
-            ViewAncestor.getRunQueue().post(action);
+            ViewRootImpl.getRunQueue().post(action);
             return true;
         }
 
@@ -8281,7 +8317,7 @@
             handler = attachInfo.mHandler;
         } else {
             // Assume that post will succeed later
-            ViewAncestor.getRunQueue().postDelayed(action, delayMillis);
+            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
             return true;
         }
 
@@ -8305,7 +8341,7 @@
             handler = attachInfo.mHandler;
         } else {
             // Assume that post will succeed later
-            ViewAncestor.getRunQueue().removeCallbacks(action);
+            ViewRootImpl.getRunQueue().removeCallbacks(action);
             return true;
         }
 
@@ -9066,11 +9102,20 @@
         // Set resolved depending on layout direction
         switch (getLayoutDirection()) {
             case LAYOUT_DIRECTION_INHERIT:
+                // We cannot do the resolution if there is no parent
+                if (mParent == null) return;
+
                 // If this is root view, no need to look at parent's layout dir.
-                if (mParent != null &&
-                        mParent instanceof ViewGroup &&
-                        ((ViewGroup) mParent).getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                if (mParent instanceof ViewGroup) {
+                    ViewGroup viewGroup = ((ViewGroup) mParent);
+
+                    // Check if the parent view group can resolve
+                    if (! viewGroup.canResolveLayoutDirection()) {
+                        return;
+                    }
+                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    }
                 }
                 break;
             case LAYOUT_DIRECTION_RTL:
@@ -9089,7 +9134,10 @@
         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
     }
 
-    private void resolvePadding() {
+    /**
+     * @hide
+     */
+    protected void resolvePadding() {
         // If the user specified the absolute padding (either with android:padding or
         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
         // use the default padding or the padding from the background drawable
@@ -9115,12 +9163,12 @@
                 // Start user padding override Left user padding. Otherwise, if Left user
                 // padding is not defined, use the default left padding. If Left user padding
                 // is defined, just use it.
-                if (mUserPaddingStart > 0) {
+                if (mUserPaddingStart >= 0) {
                     mUserPaddingLeft = mUserPaddingStart;
                 } else if (mUserPaddingLeft < 0) {
                     mUserPaddingLeft = mPaddingLeft;
                 }
-                if (mUserPaddingEnd > 0) {
+                if (mUserPaddingEnd >= 0) {
                     mUserPaddingRight = mUserPaddingEnd;
                 } else if (mUserPaddingRight < 0) {
                     mUserPaddingRight = mPaddingRight;
@@ -9132,6 +9180,15 @@
         recomputePadding();
     }
 
+    protected boolean canResolveLayoutDirection() {
+        switch (getLayoutDirection()) {
+            case LAYOUT_DIRECTION_INHERIT:
+                return (mParent != null);
+            default:
+                return true;
+        }
+    }
+
     /**
      * Reset the resolved layout direction.
      *
@@ -9173,10 +9230,7 @@
 
         destroyDrawingCache();
 
-        if (mHardwareLayer != null) {
-            mHardwareLayer.destroy();
-            mHardwareLayer = null;
-        }
+        destroyLayer();
 
         if (mDisplayList != null) {
             mDisplayList.invalidate();
@@ -9548,21 +9602,10 @@
         // Destroy any previous software drawing cache if needed
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
-                if (mHardwareLayer != null) {
-                    mHardwareLayer.destroy();
-                    mHardwareLayer = null;
-                }
+                destroyLayer();
                 // fall through - unaccelerated views may use software layer mechanism instead
             case LAYER_TYPE_SOFTWARE:
-                if (mDrawingCache != null) {
-                    mDrawingCache.recycle();
-                    mDrawingCache = null;
-                }
-
-                if (mUnscaledDrawingCache != null) {
-                    mUnscaledDrawingCache.recycle();
-                    mUnscaledDrawingCache = null;
-                }
+                destroyDrawingCache();
                 break;
             default:
                 break;
@@ -9688,6 +9731,15 @@
         return mHardwareLayer;
     }
 
+    boolean destroyLayer() {
+        if (mHardwareLayer != null) {
+            mHardwareLayer.destroy();
+            mHardwareLayer = null;
+            return true;
+        }
+        return false;
+    }
+
     /**
      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
@@ -9811,7 +9863,7 @@
             // we copy in child display lists into ours in drawChild()
             mRecreateDisplayList = true;
             if (mDisplayList == null) {
-                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(this);
+                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
                 // If we're creating a new display list, make sure our parent gets invalidated
                 // since they will need to recreate their display list to account for this
                 // new child display list.
@@ -10296,6 +10348,26 @@
     }
 
     /**
+     * @hide
+     * @param offsetRequired
+     */
+    protected int getFadeTop(boolean offsetRequired) {
+        int top = mPaddingTop;
+        if (offsetRequired) top += getTopPaddingOffset();
+        return top;
+    }
+    
+    /**
+     * @hide
+     * @param offsetRequired
+     */
+    protected int getFadeHeight(boolean offsetRequired) {
+        int padding = mPaddingTop;
+        if (offsetRequired) padding += getTopPaddingOffset();        
+        return mBottom - mTop - mPaddingBottom - padding;
+    }
+    
+    /**
      * <p>Indicates whether this view is attached to an hardware accelerated
      * window or not.</p>
      *
@@ -10406,18 +10478,16 @@
 
         // Step 2, save the canvas' layers
         int paddingLeft = mPaddingLeft;
-        int paddingTop = mPaddingTop;
 
         final boolean offsetRequired = isPaddingOffsetRequired();
         if (offsetRequired) {
             paddingLeft += getLeftPaddingOffset();
-            paddingTop += getTopPaddingOffset();
         }
 
         int left = mScrollX + paddingLeft;
         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
-        int top = mScrollY + paddingTop;
-        int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
+        int top = mScrollY + getFadeTop(offsetRequired);
+        int bottom = top + getFadeHeight(offsetRequired);
 
         if (offsetRequired) {
             right += getRightPaddingOffset();
@@ -10735,12 +10805,14 @@
             // Remember our drawn bit
             int drawn = mPrivateFlags & DRAWN;
 
-            // Invalidate our old position
-            invalidate(true);
-
-
             int oldWidth = mRight - mLeft;
             int oldHeight = mBottom - mTop;
+            int newWidth = right - left;
+            int newHeight = bottom - top;
+            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
+
+            // Invalidate our old position
+            invalidate(sizeChanged);
 
             mLeft = left;
             mTop = top;
@@ -10749,10 +10821,8 @@
 
             mPrivateFlags |= HAS_BOUNDS;
 
-            int newWidth = right - left;
-            int newHeight = bottom - top;
 
-            if (newWidth != oldWidth || newHeight != oldHeight) {
+            if (sizeChanged) {
                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mMatrixDirty = true;
@@ -10767,7 +10837,7 @@
                 // before this call to setFrame came in, thereby clearing
                 // the DRAWN bit.
                 mPrivateFlags |= DRAWN;
-                invalidate(true);
+                invalidate(sizeChanged);
                 // parent display list may need to be recreated based on a change in the bounds
                 // of any child
                 invalidateParentCaches();
@@ -11101,6 +11171,10 @@
      *        background
      */
     public void setBackgroundDrawable(Drawable d) {
+        if (d == mBGDrawable) {
+            return;
+        }
+
         boolean requestLayout = false;
 
         mBackgroundResource = 0;
@@ -11555,9 +11629,9 @@
             viewParent = view.mParent;
         }
 
-        if (viewParent instanceof ViewAncestor) {
+        if (viewParent instanceof ViewRootImpl) {
             // *cough*
-            final ViewAncestor vr = (ViewAncestor)viewParent;
+            final ViewRootImpl vr = (ViewRootImpl)viewParent;
             location[1] -= vr.mCurScrollY;
         }
     }
@@ -11984,12 +12058,13 @@
         mPrivateFlags |= FORCE_LAYOUT;
         mPrivateFlags |= INVALIDATED;
 
-        if (mLayoutParams != null && mParent != null) {
-            mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
-        }
-
-        if (mParent != null && !mParent.isLayoutRequested()) {
-            mParent.requestLayout();
+        if (mParent != null) {
+            if (mLayoutParams != null) {
+                mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
+            }
+            if (!mParent.isLayoutRequested()) {
+                mParent.requestLayout();
+            }
         }
     }
 
@@ -12684,7 +12759,7 @@
                     surface.unlockCanvasAndPost(canvas);
                 }
 
-                final ViewAncestor root = getViewAncestor();
+                final ViewRootImpl root = getViewRootImpl();
 
                 // Cache the local state object for delivery with DragEvents
                 root.setLocalDragState(myLocalState);
@@ -13048,43 +13123,41 @@
      *
      * @return the resolved text direction. Return one of:
      *
+     * {@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 getResolvedTextDirection() {
-        if (!isResolvedTextDirection()) {
+        if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
             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.
+     * Resolve the text direction.
      */
     protected void resolveTextDirection() {
+        if (mTextDirection != TEXT_DIRECTION_INHERIT) {
+            mResolvedTextDirection = mTextDirection;
+            return;
+        }
+        if (mParent != null && mParent instanceof ViewGroup) {
+            mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+            return;
+        }
+        mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
     }
 
     /**
-     * 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().
+     * Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection().
      */
     protected void resetResolvedTextDirection() {
-        mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+        mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
     }
 
     //
@@ -13893,7 +13966,7 @@
         Canvas mCanvas;
 
         /**
-         * A Handler supplied by a view's {@link android.view.ViewAncestor}. This
+         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
          * handler can be used to pump events in the UI events queue.
          */
         final Handler mHandler;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index f014070..96e550e 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -16,41 +16,51 @@
 
 package android.view;
 
-import android.util.Log;
-import android.util.DisplayMetrics;
-import android.content.res.Resources;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.os.Environment;
 import android.os.Debug;
+import android.os.Environment;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Printer;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
+import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.FileOutputStream;
-import java.io.DataOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.BufferedOutputStream;
 import java.io.OutputStream;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.lang.annotation.Target;
+import java.io.OutputStreamWriter;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.annotation.Target;
 import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Various debugging/tracing tools related to {@link View} and the view hierarchy.
@@ -106,13 +116,6 @@
     public static final boolean DEBUG_PROFILE_LAYOUT = false;
 
     /**
-     * Profiles real fps (times between draws) and displays the result.
-     *
-     * @hide
-     */
-    public static final boolean DEBUG_SHOW_FPS = false;
-
-    /**
      * Enables detailed logging of drag/drop operations.
      * @hide
      */
@@ -369,7 +372,7 @@
     }
 
     private static BufferedWriter sHierarchyTraces;
-    private static ViewAncestor sHierarhcyRoot;
+    private static ViewRootImpl sHierarhcyRoot;
     private static String sHierarchyTracePrefix;
 
     /**
@@ -396,6 +399,9 @@
     private static List<RecyclerTrace> sRecyclerTraces;
     private static String sRecyclerTracePrefix;
 
+    private static final ThreadLocal<LooperProfiler> sLooperProfilerStorage =
+            new ThreadLocal<LooperProfiler>();
+
     /**
      * Returns the number of instanciated Views.
      *
@@ -414,8 +420,243 @@
      *
      * @hide
      */
-    public static long getViewAncestorInstanceCount() {
-        return Debug.countInstancesOfClass(ViewAncestor.class);
+    public static long getViewRootImplCount() {
+        return Debug.countInstancesOfClass(ViewRootImpl.class);
+    }
+
+    /**
+     * Starts profiling the looper associated with the current thread.
+     * You must call {@link #stopLooperProfiling} to end profiling
+     * and obtain the traces. Both methods must be invoked on the
+     * same thread.
+     * 
+     * @hide
+     */
+    public static void startLooperProfiling(String path, FileDescriptor fileDescriptor) {
+        if (sLooperProfilerStorage.get() == null) {
+            LooperProfiler profiler = new LooperProfiler(path, fileDescriptor);
+            sLooperProfilerStorage.set(profiler);
+            Looper.myLooper().setMessageLogging(profiler);
+        }
+    }    
+
+    /**
+     * Stops profiling the looper associated with the current thread.
+     * 
+     * @see #startLooperProfiling(String, java.io.FileDescriptor) 
+     * 
+     * @hide
+     */
+    public static void stopLooperProfiling() {
+        LooperProfiler profiler = sLooperProfilerStorage.get();
+        if (profiler != null) {
+            sLooperProfilerStorage.remove();
+            Looper.myLooper().setMessageLogging(null);
+            profiler.save();
+        }
+    }
+
+    private static class LooperProfiler implements Looper.Profiler, Printer {
+        private static final String LOG_TAG = "LooperProfiler";
+
+        private static final int TRACE_VERSION_NUMBER = 3;
+        private static final int ACTION_EXIT_METHOD = 0x1;
+        private static final int HEADER_SIZE = 32;
+        private static final String HEADER_MAGIC = "SLOW";
+        private static final short HEADER_RECORD_SIZE = (short) 14;
+
+        private final long mTraceWallStart;
+        private final long mTraceThreadStart;
+        
+        private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512);
+
+        private final HashMap<String, Integer> mTraceNames = new HashMap<String, Integer>(32);
+        private int mTraceId = 0;
+
+        private final String mPath;
+        private ParcelFileDescriptor mFileDescriptor;
+
+        LooperProfiler(String path, FileDescriptor fileDescriptor) {
+            mPath = path;
+            try {
+                mFileDescriptor = ParcelFileDescriptor.dup(fileDescriptor);
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+                throw new RuntimeException(e);
+            }
+            mTraceWallStart = SystemClock.currentTimeMicro();
+            mTraceThreadStart = SystemClock.currentThreadTimeMicro();            
+        }
+
+        @Override
+        public void println(String x) {
+            // Ignore messages
+        }
+
+        @Override
+        public void profile(Message message, long wallStart, long wallTime,
+                long threadStart, long threadTime) {
+            Entry entry = new Entry();
+            entry.traceId = getTraceId(message);
+            entry.wallStart = wallStart;
+            entry.wallTime = wallTime;
+            entry.threadStart = threadStart;
+            entry.threadTime = threadTime;
+
+            mTraces.add(entry);
+        }
+
+        private int getTraceId(Message message) {
+            String name = message.getTarget().getMessageName(message);
+            Integer traceId = mTraceNames.get(name);
+            if (traceId == null) {
+                traceId = mTraceId++ << 4;
+                mTraceNames.put(name, traceId);
+            }
+            return traceId;
+        }
+
+        void save() {
+            // Don't block the UI thread
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    saveTraces();
+                }
+            }, "LooperProfiler[" + mPath + "]").start();
+        }
+
+        private void saveTraces() {
+            FileOutputStream fos = new FileOutputStream(mFileDescriptor.getFileDescriptor());
+            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
+
+            try {
+                writeHeader(out, mTraceWallStart, mTraceNames, mTraces);
+                out.flush();
+
+                writeTraces(fos, out.size(), mTraceWallStart, mTraceThreadStart, mTraces);
+
+                Log.d(LOG_TAG, "Looper traces ready: " + mPath);
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+            } finally {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+                }
+                try {
+                    mFileDescriptor.close();
+                } catch (IOException e) {
+                    Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+                }
+            }
+        }
+        
+        private static void writeTraces(FileOutputStream out, long offset, long wallStart,
+                long threadStart, ArrayList<Entry> entries) throws IOException {
+    
+            FileChannel channel = out.getChannel();
+    
+            // Header
+            ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE);
+            buffer.put(HEADER_MAGIC.getBytes());
+            buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
+            buffer.putShort((short) TRACE_VERSION_NUMBER);    // version
+            buffer.putShort((short) HEADER_SIZE);             // offset to data
+            buffer.putLong(wallStart);                        // start time in usec
+            buffer.putShort(HEADER_RECORD_SIZE);              // size of a record in bytes
+            // padding to 32 bytes
+            for (int i = 0; i < HEADER_SIZE - 18; i++) {
+                buffer.put((byte) 0);
+            }
+    
+            buffer.flip();
+            channel.position(offset).write(buffer);
+            
+            buffer = ByteBuffer.allocateDirect(14).order(ByteOrder.LITTLE_ENDIAN);
+            for (Entry entry : entries) {
+                buffer.putShort((short) 1);   // we simulate only one thread
+                buffer.putInt(entry.traceId); // entering method
+                buffer.putInt((int) (entry.threadStart - threadStart));
+                buffer.putInt((int) (entry.wallStart - wallStart));
+    
+                buffer.flip();
+                channel.write(buffer);
+                buffer.clear();
+    
+                buffer.putShort((short) 1);
+                buffer.putInt(entry.traceId | ACTION_EXIT_METHOD); // exiting method
+                buffer.putInt((int) (entry.threadStart + entry.threadTime - threadStart));
+                buffer.putInt((int) (entry.wallStart + entry.wallTime - wallStart));
+    
+                buffer.flip();
+                channel.write(buffer);
+                buffer.clear();
+            }
+    
+            channel.close();
+        }
+    
+        private static void writeHeader(DataOutputStream out, long start,
+                HashMap<String, Integer> names, ArrayList<Entry> entries) throws IOException {
+    
+            Entry last = entries.get(entries.size() - 1);
+            long wallTotal = (last.wallStart + last.wallTime) - start;
+    
+            startSection("version", out);
+            addValue(null, Integer.toString(TRACE_VERSION_NUMBER), out);
+            addValue("data-file-overflow", "false", out);
+            addValue("clock", "dual", out);
+            addValue("elapsed-time-usec", Long.toString(wallTotal), out);
+            addValue("num-method-calls", Integer.toString(entries.size()), out);
+            addValue("clock-call-overhead-nsec", "1", out);
+            addValue("vm", "dalvik", out);
+    
+            startSection("threads", out);
+            addThreadId(1, "main", out);
+    
+            startSection("methods", out);
+            addMethods(names, out);
+    
+            startSection("end", out);
+        }
+    
+        private static void addMethods(HashMap<String, Integer> names, DataOutputStream out)
+                throws IOException {
+    
+            for (Map.Entry<String, Integer> name : names.entrySet()) {
+                out.writeBytes(String.format("0x%08x\tEventQueue\t%s\t()V\tLooper\t-2\n",
+                        name.getValue(), name.getKey()));
+            }
+        }
+    
+        private static void addThreadId(int id, String name, DataOutputStream out)
+                throws IOException {
+
+            out.writeBytes(Integer.toString(id) + '\t' + name + '\n');
+        }
+    
+        private static void addValue(String name, String value, DataOutputStream out)
+                throws IOException {
+    
+            if (name != null) {
+                out.writeBytes(name + "=");
+            }
+            out.writeBytes(value + '\n');
+        }
+    
+        private static void startSection(String name, DataOutputStream out) throws IOException {
+            out.writeBytes("*" + name + '\n');
+        }
+
+        static class Entry {
+            int traceId;
+            long wallStart;
+            long wallTime;
+            long threadStart;
+            long threadTime;
+        }
     }
 
     /**
@@ -630,7 +871,7 @@
             return;
         }
 
-        sHierarhcyRoot = (ViewAncestor) view.getRootView().getParent();
+        sHierarhcyRoot = (ViewRootImpl) view.getRootView().getParent();
     }
 
     /**
@@ -982,7 +1223,7 @@
 
     private static void outputDisplayList(View root, String parameter) throws IOException {
         final View view = findView(root, parameter);
-        view.getViewAncestor().outputDisplayList(view);
+        view.getViewRootImpl().outputDisplayList(view);
     }
 
     private static void capture(View root, final OutputStream clientStream, String parameter)
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 752fd5a..697636e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -41,6 +41,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.LayoutAnimationController;
 import android.view.animation.Transformation;
+
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
 
@@ -787,7 +788,7 @@
         final View[] children = mChildren;
         for (int i = 0; i < childrenCount; i++) {
             View child = children[i];
-            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+            if ((child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
                 child.findViewsWithText(outViews, text);
             }
         }
@@ -842,7 +843,7 @@
      * @param child
      * @param visibility
      */
-    void onChildVisibilityChanged(View child, int visibility) {
+    protected void onChildVisibilityChanged(View child, int visibility) {
         if (mTransition != null) {
             if (visibility == VISIBLE) {
                 mTransition.showChild(this, child);
@@ -953,7 +954,7 @@
         final float tx = event.mX;
         final float ty = event.mY;
 
-        ViewAncestor root = getViewAncestor();
+        ViewRootImpl root = getViewRootImpl();
 
         // Dispatch down the view hierarchy
         switch (event.mAction) {
@@ -2147,9 +2148,12 @@
         onPopulateAccessibilityEvent(event);
         // Let our children have a shot in populating the event.
         for (int i = 0, count = getChildCount(); i < count; i++) {
-            boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event);
-            if (handled) {
-                return handled;
+            View child = getChildAt(i);
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+                boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event);
+                if (handled) {
+                    return handled;
+                }
             }
         }
         return false;
@@ -2158,6 +2162,9 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        if ((mPrivateFlags & IS_ROOT_NAMESPACE) != 0) {
+            return;
+        }
         for (int i = 0, count = mChildrenCount; i < count; i++) {
             View child = mChildren[i];
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
@@ -2850,7 +2857,7 @@
             // display lists to render, force an invalidate to allow the animation to
             // continue drawing another frame
             invalidate(true);
-            if (a instanceof AlphaAnimation) {
+            if (a.hasAlpha() && (child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
                 // alpha animations should cause the child to recreate its display list
                 child.invalidate(true);
             }
@@ -3182,6 +3189,24 @@
     }
 
     /**
+     * @hide
+     */
+    protected void onViewAdded(View child) {
+        if (mOnHierarchyChangeListener != null) {
+            mOnHierarchyChangeListener.onChildViewAdded(this, child);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    protected void onViewRemoved(View child) {
+        if (mOnHierarchyChangeListener != null) {
+            mOnHierarchyChangeListener.onChildViewRemoved(this, child);
+        }
+    }
+
+    /**
      * Adds a view during layout. This is useful if in your onLayout() method,
      * you need to add more views (as does the list view for example).
      *
@@ -3282,9 +3307,7 @@
             ai.mKeepScreenOn = lastKeepOn;
         }
 
-        if (mOnHierarchyChangeListener != null) {
-            mOnHierarchyChangeListener.onChildViewAdded(this, child);
-        }
+        onViewAdded(child);
 
         if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
             mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
@@ -3485,9 +3508,7 @@
            view.dispatchDetachedFromWindow();
         }
 
-        if (mOnHierarchyChangeListener != null) {
-            mOnHierarchyChangeListener.onChildViewRemoved(this, view);
-        }
+        onViewRemoved(view);
 
         needGlobalAttributesUpdate(false);
 
@@ -3532,8 +3553,6 @@
     }
 
     private void removeViewsInternal(int start, int count) {
-        final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener;
-        final boolean notifyListener = onHierarchyChangeListener != null;
         final View focused = mFocused;
         final boolean detach = mAttachInfo != null;
         View clearChildFocus = null;
@@ -3562,9 +3581,7 @@
 
             needGlobalAttributesUpdate(false);
 
-            if (notifyListener) {
-                onHierarchyChangeListener.onChildViewRemoved(this, view);
-            }
+            onViewRemoved(view);
         }
 
         removeFromArray(start, count);
@@ -3602,8 +3619,6 @@
         final View[] children = mChildren;
         mChildrenCount = 0;
 
-        final OnHierarchyChangeListener listener = mOnHierarchyChangeListener;
-        final boolean notify = listener != null;
         final View focused = mFocused;
         final boolean detach = mAttachInfo != null;
         View clearChildFocus = null;
@@ -3629,9 +3644,7 @@
                view.dispatchDetachedFromWindow();
             }
 
-            if (notify) {
-                listener.onChildViewRemoved(this, view);
-            }
+            onViewRemoved(view);
 
             view.mParent = null;
             children[i] = null;
@@ -3671,9 +3684,7 @@
             child.dispatchDetachedFromWindow();
         }
 
-        if (mOnHierarchyChangeListener != null) {
-            mOnHierarchyChangeListener.onChildViewRemoved(this, child);
-        }
+        onViewRemoved(child);
     }
 
     /**
@@ -3838,13 +3849,13 @@
                     if (drawAnimation) {
                         if (view != null) {
                             view.mPrivateFlags |= DRAW_ANIMATION;
-                        } else if (parent instanceof ViewAncestor) {
-                            ((ViewAncestor) parent).mIsAnimating = true;
+                        } else if (parent instanceof ViewRootImpl) {
+                            ((ViewRootImpl) parent).mIsAnimating = true;
                         }
                     }
 
-                    if (parent instanceof ViewAncestor) {
-                        ((ViewAncestor) parent).invalidate();
+                    if (parent instanceof ViewRootImpl) {
+                        ((ViewRootImpl) parent).invalidate();
                         parent = null;
                     } else if (view != null) {
                         if ((view.mPrivateFlags & DRAWN) == DRAWN ||
@@ -3901,8 +3912,8 @@
                     if (drawAnimation) {
                         if (view != null) {
                             view.mPrivateFlags |= DRAW_ANIMATION;
-                        } else if (parent instanceof ViewAncestor) {
-                            ((ViewAncestor) parent).mIsAnimating = true;
+                        } else if (parent instanceof ViewRootImpl) {
+                            ((ViewRootImpl) parent).mIsAnimating = true;
                         }
                     }
 
@@ -3959,7 +3970,8 @@
                 final int left = mLeft;
                 final int top = mTop;
 
-                if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+                if ((mGroupFlags & FLAG_CLIP_CHILDREN) != FLAG_CLIP_CHILDREN ||
+                        dirty.intersect(0, 0, mRight - left, mBottom - top) ||
                         (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
                     mPrivateFlags &= ~DRAWING_CACHE_VALID;
 
@@ -3977,8 +3989,12 @@
 
                 location[CHILD_LEFT_INDEX] = mLeft;
                 location[CHILD_TOP_INDEX] = mTop;
-
-                dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+                if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
+                    dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+                } else {
+                    // in case the dirty rect extends outside the bounds of this container
+                    dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
+                }
 
                 if (mLayerType != LAYER_TYPE_NONE) {
                     mLocalDirtyRect.union(dirty);
@@ -4425,7 +4441,7 @@
             // If this group is dirty, check that the parent is dirty as well
             if ((mPrivateFlags & DIRTY_MASK) != 0) {
                 final ViewParent parent = getParent();
-                if (parent != null && !(parent instanceof ViewAncestor)) {
+                if (parent != null && !(parent instanceof ViewRootImpl)) {
                     if ((((View) parent).mPrivateFlags & DIRTY_MASK) == 0) {
                         result = false;
                         android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
@@ -4994,7 +5010,7 @@
      * @hide
      */
     public void requestTransitionStart(LayoutTransition transition) {
-        ViewAncestor viewAncestor = getViewAncestor();
+        ViewRootImpl viewAncestor = getViewRootImpl();
         viewAncestor.requestTransitionStart(transition);
     }
 
@@ -5012,37 +5028,6 @@
         }
     }
 
-    /**
-     * 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();
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewRootImpl.java
similarity index 96%
rename from core/java/android/view/ViewAncestor.java
rename to core/java/android/view/ViewRootImpl.java
index 1dcbc26..9460fe5 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -80,6 +80,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -92,7 +93,7 @@
  * {@hide}
  */
 @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
-public final class ViewAncestor extends Handler implements ViewParent,
+public final class ViewRootImpl extends Handler implements ViewParent,
         View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
     private static final String TAG = "ViewAncestor";
     private static final boolean DBG = false;
@@ -303,7 +304,7 @@
         }
     }
     
-    public ViewAncestor(Context context) {
+    public ViewRootImpl(Context context) {
         super();
 
         if (MEASURE_LATENCY) {
@@ -540,6 +541,29 @@
         }
     }
 
+    private void destroyHardwareResources() {
+        if (mAttachInfo.mHardwareRenderer != null) {
+            if (mAttachInfo.mHardwareRenderer.isEnabled()) {
+                mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+            }
+            mAttachInfo.mHardwareRenderer.destroy(false);
+        }
+    }
+
+    void destroyHardwareLayers() {
+        if (mThread != Thread.currentThread()) {
+            if (mAttachInfo.mHardwareRenderer != null &&
+                    mAttachInfo.mHardwareRenderer.isEnabled()) {
+                HardwareRenderer.trimMemory(ComponentCallbacks.TRIM_MEMORY_MODERATE);
+            }
+        } else {
+            if (mAttachInfo.mHardwareRenderer != null &&
+                    mAttachInfo.mHardwareRenderer.isEnabled()) {
+                mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+            }
+        }
+    }
+
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
@@ -824,8 +848,10 @@
             if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                 // NOTE -- system code, won't try to do compat mode.
                 Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
-                desiredWindowWidth = disp.getRealWidth();
-                desiredWindowHeight = disp.getRealHeight();
+                Point size = new Point();
+                disp.getRealSize(size);
+                desiredWindowWidth = size.x;
+                desiredWindowHeight = size.y;
             } else {
                 DisplayMetrics packageMetrics =
                     mView.getContext().getResources().getDisplayMetrics();
@@ -868,9 +894,7 @@
             attachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
-                if (mAttachInfo.mHardwareRenderer != null) {
-                    mAttachInfo.mHardwareRenderer.destroy(false);
-                }                
+                destroyHardwareResources();
             }
             if (viewVisibility == View.GONE) {
                 // After making a window gone, we will count it as being
@@ -979,8 +1003,10 @@
                     if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                         // NOTE -- system code, won't try to do compat mode.
                         Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
-                        desiredWindowWidth = disp.getRealWidth();
-                        desiredWindowHeight = disp.getRealHeight();
+                        Point size = new Point();
+                        disp.getRealSize(size);
+                        desiredWindowWidth = size.x;
+                        desiredWindowHeight = size.y;
                     } else {
                         DisplayMetrics packageMetrics = res.getDisplayMetrics();
                         desiredWindowWidth = packageMetrics.widthPixels;
@@ -2209,6 +2235,62 @@
     public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT = 1023;
 
     @Override
+    public String getMessageName(Message message) {
+        switch (message.what) {
+            case DO_TRAVERSAL:
+                return "DO_TRAVERSAL";
+            case DIE:
+                return "DIE";
+            case RESIZED:
+                return "RESIZED";
+            case RESIZED_REPORT:
+                return "RESIZED_REPORT";
+            case WINDOW_FOCUS_CHANGED:
+                return "WINDOW_FOCUS_CHANGED";
+            case DISPATCH_KEY:
+                return "DISPATCH_KEY";
+            case DISPATCH_POINTER:
+                return "DISPATCH_POINTER";
+            case DISPATCH_TRACKBALL:
+                return "DISPATCH_TRACKBALL";
+            case DISPATCH_APP_VISIBILITY:
+                return "DISPATCH_APP_VISIBILITY";
+            case DISPATCH_GET_NEW_SURFACE:
+                return "DISPATCH_GET_NEW_SURFACE";
+            case FINISHED_EVENT:
+                return "FINISHED_EVENT";
+            case DISPATCH_KEY_FROM_IME:
+                return "DISPATCH_KEY_FROM_IME";
+            case FINISH_INPUT_CONNECTION:
+                return "FINISH_INPUT_CONNECTION";
+            case CHECK_FOCUS:
+                return "CHECK_FOCUS";
+            case CLOSE_SYSTEM_DIALOGS:
+                return "CLOSE_SYSTEM_DIALOGS";
+            case DISPATCH_DRAG_EVENT:
+                return "DISPATCH_DRAG_EVENT";
+            case DISPATCH_DRAG_LOCATION_EVENT:
+                return "DISPATCH_DRAG_LOCATION_EVENT";
+            case DISPATCH_SYSTEM_UI_VISIBILITY:
+                return "DISPATCH_SYSTEM_UI_VISIBILITY";
+            case DISPATCH_GENERIC_MOTION:
+                return "DISPATCH_GENERIC_MOTION";
+            case UPDATE_CONFIGURATION:
+                return "UPDATE_CONFIGURATION";
+            case DO_PERFORM_ACCESSIBILITY_ACTION:
+                return "DO_PERFORM_ACCESSIBILITY_ACTION";
+            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
+                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
+            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID:
+                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID";
+            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT:
+                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT";
+                                                                                                                                                                                                                                    
+        }
+        return super.getMessageName(message);
+    }
+
+    @Override
     public void handleMessage(Message msg) {
         switch (msg.what) {
         case View.AttachInfo.INVALIDATE_MSG:
@@ -2634,8 +2716,9 @@
             mInputEventDeliverTimeNanos = System.nanoTime();
         }
 
+        final boolean isTouchEvent = event.isTouchEvent();
         if (mInputEventConsistencyVerifier != null) {
-            if (event.isTouchEvent()) {
+            if (isTouchEvent) {
                 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
             } else {
                 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
@@ -2653,9 +2736,9 @@
             mTranslator.translateEventInScreenToAppWindow(event);
         }
 
-        // Enter touch mode on the down.
-        boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
-        if (isDown) {
+        // Enter touch mode on down or scroll.
+        final int action = event.getAction();
+        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
             ensureTouchMode(true);
         }
 
@@ -2668,8 +2751,10 @@
         }
 
         // Remember the touch position for possible drag-initiation.
-        mLastTouchPoint.x = event.getRawX();
-        mLastTouchPoint.y = event.getRawY();
+        if (isTouchEvent) {
+            mLastTouchPoint.x = event.getRawX();
+            mLastTouchPoint.y = event.getRawY();
+        }
 
         // Dispatch touch to view hierarchy.
         boolean handled = mView.dispatchPointerEvent(event);
@@ -2681,51 +2766,6 @@
             return;
         }
 
-        // Apply edge slop and try again, if appropriate.
-        final int edgeFlags = event.getEdgeFlags();
-        if (edgeFlags != 0 && mView instanceof ViewGroup) {
-            final int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
-            int direction = View.FOCUS_UP;
-            int x = (int)event.getX();
-            int y = (int)event.getY();
-            final int[] deltas = new int[2];
-
-            if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
-                direction = View.FOCUS_DOWN;
-                if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
-                    deltas[0] = edgeSlop;
-                    x += edgeSlop;
-                } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
-                    deltas[0] = -edgeSlop;
-                    x -= edgeSlop;
-                }
-            } else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
-                direction = View.FOCUS_UP;
-                if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
-                    deltas[0] = edgeSlop;
-                    x += edgeSlop;
-                } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
-                    deltas[0] = -edgeSlop;
-                    x -= edgeSlop;
-                }
-            } else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
-                direction = View.FOCUS_RIGHT;
-            } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
-                direction = View.FOCUS_LEFT;
-            }
-
-            View nearest = FocusFinder.getInstance().findNearestTouchable(
-                    ((ViewGroup) mView), x, y, direction, deltas);
-            if (nearest != null) {
-                event.offsetLocation(deltas[0], deltas[1]);
-                event.setEdgeFlags(0);
-                if (mView.dispatchPointerEvent(event)) {
-                    finishMotionEvent(event, sendDone, true);
-                    return;
-                }
-            }
-        }
-
         // Pointer event was unhandled.
         finishMotionEvent(event, sendDone, false);
     }
@@ -3470,6 +3510,31 @@
     public void debug() {
         mView.debug();
     }
+    
+    public void dumpGfxInfo(PrintWriter pw, int[] info) {
+        if (mView != null) {
+            getGfxInfo(mView, info);
+        } else {
+            info[0] = info[1] = 0;
+        }
+    }
+
+    private void getGfxInfo(View view, int[] info) {
+        DisplayList displayList = view.mDisplayList;
+        info[0]++;
+        if (displayList != null) {
+            info[1] += displayList.getSize();
+        }
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup) view;
+
+            int count = group.getChildCount();
+            for (int i = 0; i < count; i++) {
+                getGfxInfo(group.getChildAt(i), info);
+            }
+        }
+    }
 
     public void die(boolean immediate) {
         if (immediate) {
@@ -3793,14 +3858,14 @@
     }
     
     static class InputMethodCallback extends IInputMethodCallback.Stub {
-        private WeakReference<ViewAncestor> mViewAncestor;
+        private WeakReference<ViewRootImpl> mViewAncestor;
 
-        public InputMethodCallback(ViewAncestor viewAncestor) {
-            mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor);
+        public InputMethodCallback(ViewRootImpl viewAncestor) {
+            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
         }
 
         public void finishedEvent(int seq, boolean handled) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchFinishedEvent(seq, handled);
             }
@@ -3812,15 +3877,15 @@
     }
 
     static class W extends IWindow.Stub {
-        private final WeakReference<ViewAncestor> mViewAncestor;
+        private final WeakReference<ViewRootImpl> mViewAncestor;
 
-        W(ViewAncestor viewAncestor) {
-            mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor);
+        W(ViewRootImpl viewAncestor) {
+            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
         }
 
         public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets,
                 boolean reportDraw, Configuration newConfig) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw,
                         newConfig);
@@ -3828,21 +3893,21 @@
         }
 
         public void dispatchAppVisibility(boolean visible) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchAppVisibility(visible);
             }
         }
 
         public void dispatchGetNewSurface() {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchGetNewSurface();
             }
         }
 
         public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
             }
@@ -3858,7 +3923,7 @@
         }
 
         public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 final View view = viewAncestor.mView;
                 if (view != null) {
@@ -3889,7 +3954,7 @@
         }
         
         public void closeSystemDialogs(String reason) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchCloseSystemDialogs(reason);
             }
@@ -3917,14 +3982,14 @@
 
         /* Drag/drop */
         public void dispatchDragEvent(DragEvent event) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchDragEvent(event);
             }
         }
 
         public void dispatchSystemUiVisibilityChanged(int visibility) {
-            final ViewAncestor viewAncestor = mViewAncestor.get();
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchSystemUiVisibilityChanged(visibility);
             }
@@ -4255,7 +4320,7 @@
             if (!registered) {
                 mAttachInfo.mAccessibilityWindowId =
                     mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
-                            new AccessibilityInteractionConnection(ViewAncestor.this));
+                            new AccessibilityInteractionConnection(ViewRootImpl.this));
             }
         }
 
@@ -4275,10 +4340,10 @@
      */
     final class AccessibilityInteractionConnection
             extends IAccessibilityInteractionConnection.Stub {
-        private final WeakReference<ViewAncestor> mViewAncestor;
+        private final WeakReference<ViewRootImpl> mViewAncestor;
 
-        AccessibilityInteractionConnection(ViewAncestor viewAncestor) {
-            mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor);
+        AccessibilityInteractionConnection(ViewRootImpl viewAncestor) {
+            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
         }
 
         public void findAccessibilityNodeInfoByAccessibilityId(int accessibilityId,
@@ -4407,7 +4472,7 @@
             try {
                 FindByAccessibilitytIdPredicate predicate = mFindByAccessibilityIdPredicate;
                 predicate.init(accessibilityId);
-                View root = ViewAncestor.this.mView;
+                View root = ViewRootImpl.this.mView;
                 View target = root.findViewByPredicate(predicate);
                 if (target != null && target.isShown()) {
                     info = target.createAccessibilityNodeInfo();
@@ -4439,7 +4504,7 @@
 
             AccessibilityNodeInfo info = null;
             try {
-                View root = ViewAncestor.this.mView;
+                View root = ViewRootImpl.this.mView;
                 View target = root.findViewById(viewId);
                 if (target != null && target.isShown()) {
                     info = target.createAccessibilityNodeInfo();
@@ -4485,7 +4550,7 @@
                 if (accessibilityViewId != View.NO_ID) {
                     root = findViewByAccessibilityId(accessibilityViewId);
                 } else {
-                    root = ViewAncestor.this.mView;
+                    root = ViewRootImpl.this.mView;
                 }
 
                 if (root == null || !root.isShown()) {
@@ -4610,7 +4675,7 @@
         }
 
         private View findViewByAccessibilityId(int accessibilityId) {
-            View root = ViewAncestor.this.mView;
+            View root = ViewRootImpl.this.mView;
             if (root == null) {
                 return null;
             }
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 54e7c04..5ef4f3e 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,18 +16,19 @@
 
 package android.view;
 
-import java.util.HashMap;
-
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.os.IBinder;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
-import android.util.Slog;
-import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
 final class WindowLeaked extends AndroidRuntimeException {
     public WindowLeaked(String msg) {
         super(msg);
@@ -80,7 +81,7 @@
     public static final int ADD_PERMISSION_DENIED = -8;
 
     private View[] mViews;
-    private ViewAncestor[] mRoots;
+    private ViewRootImpl[] mRoots;
     private WindowManager.LayoutParams[] mParams;
 
     private final static Object sLock = new Object();
@@ -204,7 +205,7 @@
         final WindowManager.LayoutParams wparams
                 = (WindowManager.LayoutParams)params;
         
-        ViewAncestor root;
+        ViewRootImpl root;
         View panelParentView = null;
         
         synchronized (this) {
@@ -241,7 +242,7 @@
                 }
             }
             
-            root = new ViewAncestor(view.getContext());
+            root = new ViewRootImpl(view.getContext());
             root.mAddNesting = 1;
             if (cih == null) {
                 root.mCompatibilityInfo = new CompatibilityInfoHolder();
@@ -254,7 +255,7 @@
             if (mViews == null) {
                 index = 1;
                 mViews = new View[1];
-                mRoots = new ViewAncestor[1];
+                mRoots = new ViewRootImpl[1];
                 mParams = new WindowManager.LayoutParams[1];
             } else {
                 index = mViews.length + 1;
@@ -262,7 +263,7 @@
                 mViews = new View[index];
                 System.arraycopy(old, 0, mViews, 0, index-1);
                 old = mRoots;
-                mRoots = new ViewAncestor[index];
+                mRoots = new ViewRootImpl[index];
                 System.arraycopy(old, 0, mRoots, 0, index-1);
                 old = mParams;
                 mParams = new WindowManager.LayoutParams[index];
@@ -290,7 +291,7 @@
 
         synchronized (this) {
             int index = findViewLocked(view, true);
-            ViewAncestor root = mRoots[index];
+            ViewRootImpl root = mRoots[index];
             mParams[index] = wparams;
             root.setLayoutParams(wparams, false);
         }
@@ -312,7 +313,7 @@
     public void removeViewImmediate(View view) {
         synchronized (this) {
             int index = findViewLocked(view, true);
-            ViewAncestor root = mRoots[index];
+            ViewRootImpl root = mRoots[index];
             View curView = root.getView();
             
             root.mAddNesting = 0;
@@ -328,7 +329,7 @@
     }
     
     View removeViewLocked(int index) {
-        ViewAncestor root = mRoots[index];
+        ViewRootImpl root = mRoots[index];
         View view = root.getView();
         
         // Don't really remove until we have matched all calls to add().
@@ -356,7 +357,7 @@
         removeItem(tmpViews, mViews, index);
         mViews = tmpViews;
         
-        ViewAncestor[] tmpRoots = new ViewAncestor[count-1];
+        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
         removeItem(tmpRoots, mRoots, index);
         mRoots = tmpRoots;
         
@@ -383,7 +384,7 @@
                 //Log.i("foo", "@ " + i + " token " + mParams[i].token
                 //        + " view " + mRoots[i].getView());
                 if (token == null || mParams[i].token == token) {
-                    ViewAncestor root = mRoots[i];
+                    ViewRootImpl root = mRoots[i];
                     root.mAddNesting = 1;
                     
                     //Log.i("foo", "Force closing " + root);
@@ -394,7 +395,7 @@
                         leak.setStackTrace(root.getLocation().getStackTrace());
                         Log.e("WindowManager", leak.getMessage(), leak);
                     }
-                    
+
                     removeViewLocked(i);
                     i--;
                     count--;
@@ -402,7 +403,69 @@
             }
         }
     }
-    
+
+    /**
+     * @param level See {@link android.content.ComponentCallbacks}
+     */
+    public void trimMemory(int level) {
+        if (HardwareRenderer.isAvailable()) {
+            HardwareRenderer.trimMemory(level);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void trimLocalMemory() {
+        synchronized (this) {
+            if (mViews == null) return;
+            int count = mViews.length;
+            for (int i = 0; i < count; i++) {
+                mRoots[i].destroyHardwareLayers();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void dumpGfxInfo(FileDescriptor fd) {
+        FileOutputStream fout = new FileOutputStream(fd);
+        PrintWriter pw = new PrintWriter(fout);
+        try {
+            synchronized (this) {
+                if (mViews != null) {
+                    pw.println("View hierarchy:");
+
+                    final int count = mViews.length;
+
+                    int viewsCount = 0;
+                    int displayListsSize = 0;
+                    int[] info = new int[2];
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        root.dumpGfxInfo(pw, info);
+
+                        String name = root.getClass().getName() + '@' +
+                                Integer.toHexString(hashCode());                        
+                        pw.printf("  %s: %d views, %.2f kB (display lists)\n",
+                                name, info[0], info[1] / 1024.0f);
+
+                        viewsCount += info[0];
+                        displayListsSize += info[1];
+                    }
+
+                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
+                    pw.printf("Total Views:        %d\n", viewsCount);                    
+                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);                    
+                }
+            }
+        } finally {
+            pw.flush();
+        }        
+    }
+
     public void setStoppedState(IBinder token, boolean stopped) {
         synchronized (this) {
             if (mViews == null)
@@ -410,7 +473,7 @@
             int count = mViews.length;
             for (int i=0; i<count; i++) {
                 if (token == null || mParams[i].token == token) {
-                    ViewAncestor root = mRoots[i];
+                    ViewRootImpl root = mRoots[i];
                     root.setStopped(stopped);
                 }
             }
@@ -422,7 +485,7 @@
             int count = mViews.length;
             config = new Configuration(config);
             for (int i=0; i<count; i++) {
-                ViewAncestor root = mRoots[i];
+                ViewRootImpl root = mRoots[i];
                 root.requestUpdateConfiguration(config);
             }
         }
@@ -430,13 +493,13 @@
 
     public WindowManager.LayoutParams getRootViewLayoutParameter(View view) {
         ViewParent vp = view.getParent();
-        while (vp != null && !(vp instanceof ViewAncestor)) {
+        while (vp != null && !(vp instanceof ViewRootImpl)) {
             vp = vp.getParent();
         }
         
         if (vp == null) return null;
         
-        ViewAncestor vr = (ViewAncestor)vp;
+        ViewRootImpl vr = (ViewRootImpl)vp;
         
         int N = mRoots.length;
         for (int i = 0; i < N; ++i) {
@@ -456,8 +519,7 @@
         return new Display(Display.DEFAULT_DISPLAY, null);
     }
 
-    private static void removeItem(Object[] dst, Object[] src, int index)
-    {
+    private static void removeItem(Object[] dst, Object[] src, int index) {
         if (dst.length > 0) {
             if (index > 0) {
                 System.arraycopy(src, 0, dst, 0, index);
@@ -468,8 +530,7 @@
         }
     }
 
-    private int findViewLocked(View view, boolean required)
-    {
+    private int findViewLocked(View view, boolean required) {
         synchronized (this) {
             final int count = mViews != null ? mViews.length : 0;
             for (int i=0; i<count; i++) {
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index ac86769..9be2a67 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -552,7 +552,8 @@
 
     /**
      * Returns a cached instance if such is available or a new one is
-     * initialized with from the given <code>event</code>.
+     * created. The returned instance is initialized from the given
+     * <code>event</code>.
      *
      * @param event The other event.
      * @return An instance.
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 314b7ca..a80c2a7 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -67,11 +67,17 @@
 
     private static final String LOG_TAG = "AccessibilityManager";
 
+    /** @hide */
+    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
+
+    /** @hide */
+    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
+
     static final Object sInstanceSync = new Object();
 
     private static AccessibilityManager sInstance;
 
-    private static final int DO_SET_ENABLED = 10;
+    private static final int DO_SET_STATE = 10;
 
     final IAccessibilityManager mService;
 
@@ -79,6 +85,8 @@
 
     boolean mIsEnabled;
 
+    boolean mIsTouchExplorationEnabled;
+
     final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners =
         new CopyOnWriteArrayList<AccessibilityStateChangeListener>();
 
@@ -96,8 +104,8 @@
     }
 
     final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
-        public void setEnabled(boolean enabled) {
-            mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
+        public void setState(int state) {
+            mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget();
         }
     };
 
@@ -110,9 +118,8 @@
         @Override
         public void handleMessage(Message message) {
             switch (message.what) {
-                case DO_SET_ENABLED :
-                    final boolean isEnabled = (message.arg1 == 1);
-                    setAccessibilityState(isEnabled);
+                case DO_SET_STATE :
+                    setState(message.arg1);
                     return;
                 default :
                     Log.w(LOG_TAG, "Unknown message type: " + message.what);
@@ -149,8 +156,8 @@
         mService = service;
 
         try {
-            final boolean isEnabled = mService.addClient(mClient);
-            setAccessibilityState(isEnabled);
+            final int stateFlags = mService.addClient(mClient);
+            setState(stateFlags);
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
         }
@@ -168,6 +175,17 @@
     }
 
     /**
+     * Returns if the touch exploration in the system is enabled.
+     *
+     * @return True if touch exploration is enabled, false otherwise.
+     */
+    public boolean isTouchExplorationEnabled() {
+        synchronized (mHandler) {
+            return mIsTouchExplorationEnabled;
+        }
+    }
+
+    /**
      * Returns the client interface this instance registers in
      * the centralized accessibility manager service.
      *
@@ -316,6 +334,17 @@
     }
 
     /**
+     * Sets the current state.
+     *
+     * @param stateFlags The state flags.
+     */
+    private void setState(int stateFlags) {
+        final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+        setAccessibilityState(accessibilityEnabled);
+        mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
+    }
+
+    /**
      * Sets the enabled state.
      *
      * @param isEnabled The accessibility state.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 031c6ae..6469b35 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -120,7 +120,7 @@
     private CharSequence mText;
     private CharSequence mContentDescription;
 
-    private final SparseIntArray mChildAccessibilityIds = new SparseIntArray();
+    private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
     private int mActions;
 
     private IAccessibilityServiceConnection mConnection;
@@ -294,14 +294,14 @@
     }
 
     /**
-     * Gets the unique id identifying this node's parent.
+     * Gets the parent.
      * <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>
      *
-     * @return The node's patent id.
+     * @return The parent.
      */
     public AccessibilityNodeInfo getParent() {
         enforceSealed();
@@ -873,6 +873,20 @@
     }
 
     /**
+     * Returns a cached instance if such is available or a new one is
+     * create. The returned instance is initialized from the given
+     * <code>info</code>.
+     *
+     * @param info The other info.
+     * @return An instance.
+     */
+    public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
+        AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
+        infoClone.init(info);
+        return infoClone;
+    }
+
+    /**
      * Return an instance back to be reused.
      * <p>
      * <strong>Note:</strong> You must not touch the object after calling this function.
@@ -945,6 +959,28 @@
     }
 
     /**
+     * Initializes this instance from another one.
+     *
+     * @param other The other instance.
+     */
+    private void init(AccessibilityNodeInfo other) {
+        mSealed = other.mSealed;
+        mConnection = other.mConnection;
+        mAccessibilityViewId = other.mAccessibilityViewId;
+        mParentAccessibilityViewId = other.mParentAccessibilityViewId;
+        mAccessibilityWindowId = other.mAccessibilityWindowId;
+        mBoundsInParent.set(other.mBoundsInParent);
+        mBoundsInScreen.set(other.mBoundsInScreen);
+        mPackageName = other.mPackageName;
+        mClassName = other.mClassName;
+        mText = other.mText;
+        mContentDescription = other.mContentDescription;
+        mActions= other.mActions;
+        mBooleanProperties = other.mBooleanProperties;
+        mChildAccessibilityIds = other.mChildAccessibilityIds.clone();
+    }
+
+    /**
      * Creates a new instance from a {@link Parcel}.
      *
      * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
@@ -994,6 +1030,7 @@
         mConnection = null;
         mAccessibilityViewId = View.NO_ID;
         mParentAccessibilityViewId = View.NO_ID;
+        mAccessibilityWindowId = View.NO_ID;
         mChildAccessibilityIds.clear();
         mBoundsInParent.set(0, 0, 0, 0);
         mBoundsInScreen.set(0, 0, 0, 0);
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index f4d5e89..210106f 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -50,7 +50,7 @@
  */
 public class AccessibilityRecord {
 
-    private static final int INVALID_POSITION = -1;
+    private static final int UNDEFINED = -1;
 
     private static final int PROPERTY_CHECKED = 0x00000001;
     private static final int PROPERTY_ENABLED = 0x00000002;
@@ -68,15 +68,15 @@
 
     boolean mSealed;
     int mBooleanProperties;
-    int mCurrentItemIndex;
-    int mItemCount;
-    int mFromIndex;
-    int mToIndex;
-    int mScrollX;
-    int mScrollY;
+    int mCurrentItemIndex = UNDEFINED;
+    int mItemCount = UNDEFINED;
+    int mFromIndex = UNDEFINED;
+    int mToIndex = UNDEFINED;
+    int mScrollX = UNDEFINED;
+    int mScrollY = UNDEFINED;
 
-    int mAddedCount;
-    int mRemovedCount;
+    int mAddedCount= UNDEFINED;
+    int mRemovedCount = UNDEFINED;
     int mSourceViewId = View.NO_ID;
     int mSourceWindowId = View.NO_ID;
 
@@ -681,14 +681,14 @@
     void clear() {
         mSealed = false;
         mBooleanProperties = 0;
-        mCurrentItemIndex = INVALID_POSITION;
-        mItemCount = 0;
-        mFromIndex = 0;
-        mToIndex = 0;
-        mScrollX = 0;
-        mScrollY = 0;
-        mAddedCount = 0;
-        mRemovedCount = 0;
+        mCurrentItemIndex = UNDEFINED;
+        mItemCount = UNDEFINED;
+        mFromIndex = UNDEFINED;
+        mToIndex = UNDEFINED;
+        mScrollX = UNDEFINED;
+        mScrollY = UNDEFINED;
+        mAddedCount = UNDEFINED;
+        mRemovedCount = UNDEFINED;
         mClassName = null;
         mContentDescription = null;
         mBeforeText = null;
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index b14f02a..c621ff6 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -34,7 +34,7 @@
  */
 interface IAccessibilityManager {
 
-    boolean addClient(IAccessibilityManagerClient client);
+    int addClient(IAccessibilityManagerClient client);
 
     boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
 
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 1eb60fc..5e7e813 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -24,6 +24,5 @@
  */
 oneway interface IAccessibilityManagerClient {
 
-    void setEnabled(boolean enabled);
-
+    void setState(int stateFlags);
 }
diff --git a/core/java/android/view/animation/AlphaAnimation.java b/core/java/android/view/animation/AlphaAnimation.java
index 651fe45..c4d9afc 100644
--- a/core/java/android/view/animation/AlphaAnimation.java
+++ b/core/java/android/view/animation/AlphaAnimation.java
@@ -78,4 +78,12 @@
     public boolean willChangeBounds() {
         return false;
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean hasAlpha() {
+        return true;
+    }
 }
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 87c759c..b7dfabc 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -1001,6 +1001,15 @@
     }
 
     /**
+     * Return true if this animation changes the view's alpha property.
+     * 
+     * @hide
+     */
+    public boolean hasAlpha() {
+        return false;
+    }
+
+    /**
      * Utility class to parse a string description of a size.
      */
     protected static class Description {
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index 873ce53..4f2542b 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -43,6 +43,8 @@
     private static final int PROPERTY_CHANGE_BOUNDS_MASK      = 0x80;
 
     private int mFlags = 0;
+    private boolean mDirty;
+    private boolean mHasAlpha;
 
     private ArrayList<Animation> mAnimations = new ArrayList<Animation>();
 
@@ -138,6 +140,28 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public boolean hasAlpha() {
+        if (mDirty) {
+            mDirty = mHasAlpha = false;
+
+            final int count = mAnimations.size();
+            final ArrayList<Animation> animations = mAnimations;
+
+            for (int i = 0; i < count; i++) {
+                if (animations.get(i).hasAlpha()) {
+                    mHasAlpha = true;
+                    break;
+                }
+            }
+        }
+
+        return mHasAlpha;
+    }
+
+    /**
      * <p>Sets the duration of every child animation.</p>
      *
      * @param durationMillis the duration of the animation, in milliseconds, for
@@ -175,6 +199,8 @@
             mLastEnd = Math.max(mLastEnd, a.getStartOffset() + a.getDuration());
             mDuration = mLastEnd - mStartOffset;
         }
+
+        mDirty = true;
     }
     
     /**
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index abe3c2c..5ec1ec3 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -34,7 +34,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 
 class ComposingText implements NoCopySpan {
 }
@@ -502,7 +502,7 @@
                 }
             }
             if (h != null) {
-                h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME,
+                h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
                         event));
             }
         }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index a1a7281..da5baf8 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,6 +26,7 @@
 import com.android.internal.view.InputBindResult;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -42,7 +43,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -655,7 +656,7 @@
                 if (vh != null) {
                     // This will result in a call to reportFinishInputConnection()
                     // below.
-                    vh.sendMessage(vh.obtainMessage(ViewAncestor.FINISH_INPUT_CONNECTION,
+                    vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION,
                             mServedInputConnection));
                 }
             }
@@ -1112,9 +1113,9 @@
 
     void scheduleCheckFocusLocked(View view) {
         Handler vh = view.getHandler();
-        if (vh != null && !vh.hasMessages(ViewAncestor.CHECK_FOCUS)) {
+        if (vh != null && !vh.hasMessages(ViewRootImpl.CHECK_FOCUS)) {
             // This will result in a call to checkFocus() below.
-            vh.sendMessage(vh.obtainMessage(ViewAncestor.CHECK_FOCUS));
+            vh.sendMessage(vh.obtainMessage(ViewRootImpl.CHECK_FOCUS));
         }
     }
     
@@ -1580,16 +1581,16 @@
     }
 
     /**
-     * Set additional input method subtypes.
-     * @param imeToken Supplies the identifying token given to an input method.
+     * Set additional input method subtypes. Only a process which shares the same uid with the IME
+     * can add additional input method subtypes to the IME.
+     * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
      * @param subtypes subtypes will be added as additional subtypes of the current input method.
      * @return true if the additional input method subtypes are successfully added.
      */
-    public boolean setAdditionalInputMethodSubtypes(
-            IBinder imeToken, InputMethodSubtype[] subtypes) {
+    public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
         synchronized (mH) {
             try {
-                return mService.setAdditionalInputMethodSubtypes(imeToken, subtypes);
+                return mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
             } catch (RemoteException e) {
                 Log.w(TAG, "IME died: " + mCurId, e);
                 return false;
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/android/view/textservice/SpellCheckerInfo.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/android/view/textservice/SpellCheckerInfo.aidl
index eaf7bde..eb5dfcc 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/android/view/textservice/SpellCheckerInfo.aidl
@@ -14,19 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package android.view.textservice;
 
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+parcelable SpellCheckerInfo;
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
new file mode 100644
index 0000000..d88a39f
--- /dev/null
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.textservice;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class is used to specify meta information of an spell checker.
+ */
+public final class SpellCheckerInfo implements Parcelable {
+    private final ResolveInfo mService;
+    private final String mId;
+
+    /**
+     * Constructor.
+     * @hide
+     */
+    public SpellCheckerInfo(Context context, ResolveInfo service) {
+        mService = service;
+        ServiceInfo si = service.serviceInfo;
+        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+    }
+
+    /**
+     * Constructor.
+     * @hide
+     */
+    public SpellCheckerInfo(Parcel source) {
+        mId = source.readString();
+        mService = ResolveInfo.CREATOR.createFromParcel(source);
+    }
+
+    /**
+     * Return a unique ID for this spell checker.  The ID is generated from
+     * the package and class name implementing the method.
+     */
+    public String getId() {
+        return mId;
+    }
+
+
+    /**
+     * Return the component of the service that implements.
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(
+                mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Return the .apk package that implements this input method.
+     */
+    public String getPackageName() {
+        return mService.serviceInfo.packageName;
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        mService.writeToParcel(dest, flags);
+    }
+
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<SpellCheckerInfo> CREATOR
+            = new Parcelable.Creator<SpellCheckerInfo>() {
+        @Override
+        public SpellCheckerInfo createFromParcel(Parcel source) {
+            return new SpellCheckerInfo(source);
+        }
+
+        @Override
+        public SpellCheckerInfo[] newArray(int size) {
+            return new SpellCheckerInfo[size];
+        }
+    };
+
+    /**
+     * Load the user-displayed label for this spell checker.
+     *
+     * @param pm Supply a PackageManager used to load the spell checker's resources.
+     */
+    public CharSequence loadLabel(PackageManager pm) {
+        return mService.loadLabel(pm);
+    }
+
+    /**
+     * Load the user-displayed icon for this spell checker.
+     *
+     * @param pm Supply a PackageManager used to load the spell checker's resources.
+     */
+    public Drawable loadIcon(PackageManager pm) {
+        return mService.loadIcon(pm);
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/android/view/textservice/SuggestionsInfo.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/android/view/textservice/SuggestionsInfo.aidl
index eaf7bde..66e20d2 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/android/view/textservice/SuggestionsInfo.aidl
@@ -14,19 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package android.view.textservice;
 
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+parcelable SuggestionsInfo;
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
new file mode 100644
index 0000000..3332f1e
--- /dev/null
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.textservice;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains a metadata of suggestions from the text service
+ */
+public final class SuggestionsInfo implements Parcelable {
+    private static final String[] EMPTY = new String[0];
+
+    /**
+     * Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that the requested word was found
+     * in the dictionary in the text service.
+     */
+    public static final int RESULT_ATTR_IN_THE_DICTIONARY = 0x0001;
+    /**
+     * Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that the text service thinks the requested
+     * word looks a typo.
+     */
+    public static final int RESULT_ATTR_LOOKS_TYPO = 0x0002;
+    private final int mSuggestionsAttributes;
+    private final String[] mSuggestions;
+    private final boolean mSuggestionsAvailable;
+    private int mCookie;
+    private int mSequence;
+
+    /**
+     * Constructor.
+     * @param suggestionsAttributes from the text service
+     * @param suggestions from the text service
+     */
+    public SuggestionsInfo(int suggestionsAttributes, String[] suggestions) {
+        mSuggestionsAttributes = suggestionsAttributes;
+        if (suggestions == null) {
+            mSuggestions = EMPTY;
+            mSuggestionsAvailable = false;
+        } else {
+            mSuggestions = suggestions;
+            mSuggestionsAvailable = true;
+        }
+        mCookie = 0;
+        mSequence = 0;
+    }
+
+    /**
+     * Constructor.
+     * @param suggestionsAttributes from the text service
+     * @param suggestions from the text service
+     * @param cookie the cookie of the input TextInfo
+     * @param sequence the cookie of the input TextInfo
+     */
+    public SuggestionsInfo(
+            int suggestionsAttributes, String[] suggestions, int cookie, int sequence) {
+        if (suggestions == null) {
+            mSuggestions = EMPTY;
+            mSuggestionsAvailable = false;
+        } else {
+            mSuggestions = suggestions;
+            mSuggestionsAvailable = true;
+        }
+        mSuggestionsAttributes = suggestionsAttributes;
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    public SuggestionsInfo(Parcel source) {
+        mSuggestionsAttributes = source.readInt();
+        mSuggestions = source.readStringArray();
+        mCookie = source.readInt();
+        mSequence = source.readInt();
+        mSuggestionsAvailable = source.readInt() == 1;
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSuggestionsAttributes);
+        dest.writeStringArray(mSuggestions);
+        dest.writeInt(mCookie);
+        dest.writeInt(mSequence);
+        dest.writeInt(mSuggestionsAvailable ? 1 : 0);
+    }
+
+    /**
+     * Set the cookie and the sequence of SuggestionsInfo which are set to TextInfo from a client
+     * application
+     * @param cookie the cookie of an input TextInfo
+     * @param sequence the cookie of an input TextInfo
+     */
+    public void setCookieAndSequence(int cookie, int sequence) {
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    /**
+     * @return the cookie which may be set by a client application
+     */
+    public int getCookie() {
+        return mCookie;
+    }
+
+    /**
+     * @return the sequence which may be set by a client application
+     */
+    public int getSequence() {
+        return mSequence;
+    }
+
+    /**
+     * @return the attributes of suggestions. This includes whether the spell checker has the word
+     * in its dictionary or not and whether the spell checker has confident suggestions for the
+     * word or not.
+     */
+    public int getSuggestionsAttributes() {
+        return mSuggestionsAttributes;
+    }
+
+    /**
+     * @return the count of the suggestions. If there's no suggestions at all, this method returns
+     * -1. Even if this method returns 0, it doesn't necessarily mean that there are no suggestions
+     * for the requested word. For instance, the caller could have been asked to limit the maximum
+     * number of suggestions returned.
+     */
+    public int getSuggestionsCount() {
+        if (!mSuggestionsAvailable) {
+            return -1;
+        }
+        return mSuggestions.length;
+    }
+
+    /**
+     * @param i the id of suggestions
+     * @return the suggestion at the specified id
+     */
+    public String getSuggestionAt(int i) {
+        return mSuggestions[i];
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<SuggestionsInfo> CREATOR
+            = new Parcelable.Creator<SuggestionsInfo>() {
+        @Override
+        public SuggestionsInfo createFromParcel(Parcel source) {
+            return new SuggestionsInfo(source);
+        }
+
+        @Override
+        public SuggestionsInfo[] newArray(int size) {
+            return new SuggestionsInfo[size];
+        }
+    };
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/android/view/textservice/TextInfo.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/android/view/textservice/TextInfo.aidl
index eaf7bde..d231d76 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/android/view/textservice/TextInfo.aidl
@@ -14,19 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package android.view.textservice;
 
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+parcelable TextInfo;
diff --git a/core/java/android/view/textservice/TextInfo.java b/core/java/android/view/textservice/TextInfo.java
new file mode 100644
index 0000000..b534eb0
--- /dev/null
+++ b/core/java/android/view/textservice/TextInfo.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.textservice;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * This class contains a metadata of the input of TextService
+ */
+public final class TextInfo implements Parcelable {
+    private final String mText;
+    private final int mCookie;
+    private final int mSequence;
+
+    /**
+     * Constructor.
+     * @param text the text which will be input to TextService
+     */
+    public TextInfo(String text) {
+        this(text, 0, 0);
+    }
+
+    /**
+     * Constructor.
+     * @param text the text which will be input to TextService
+     * @param cookie the cookie for this TextInfo
+     * @param sequence the sequence number for this TextInfo
+     */
+    public TextInfo(String text, int cookie, int sequence) {
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException(text);
+        }
+        mText = text;
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    public TextInfo(Parcel source) {
+        mText = source.readString();
+        mCookie = source.readInt();
+        mSequence = source.readInt();
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mText);
+        dest.writeInt(mCookie);
+        dest.writeInt(mSequence);
+    }
+
+    /**
+     * @return the text which is an input of a text service
+     */
+    public String getText() {
+        return mText;
+    }
+
+    /**
+     * @return the cookie of TextInfo
+     */
+    public int getCookie() {
+        return mCookie;
+    }
+
+    /**
+     * @return the sequence of TextInfo
+     */
+    public int getSequence() {
+        return mSequence;
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<TextInfo> CREATOR
+            = new Parcelable.Creator<TextInfo>() {
+        @Override
+        public TextInfo createFromParcel(Parcel source) {
+            return new TextInfo(source);
+        }
+
+        @Override
+        public TextInfo[] newArray(int size) {
+            return new TextInfo[size];
+        }
+    };
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
new file mode 100644
index 0000000..ae253cf
--- /dev/null
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.textservice;
+
+import com.android.internal.textservice.ITextServicesManager;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.textservice.SpellCheckerSession;
+import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import android.util.Log;
+
+import java.util.Locale;
+
+/**
+ * System API to the overall text services, which arbitrates interaction between applications
+ * and text services. You can retrieve an instance of this interface with
+ * {@link Context#getSystemService(String) Context.getSystemService()}.
+ *
+ * The user can change the current text services in Settings. And also applications can specify
+ * the target text services.
+ */
+public final class TextServicesManager {
+    private static final String TAG = TextServicesManager.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private static TextServicesManager sInstance;
+    private static ITextServicesManager sService;
+
+    private TextServicesManager() {
+        if (sService == null) {
+            IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+            sService = ITextServicesManager.Stub.asInterface(b);
+        }
+    }
+
+    /**
+     * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
+     * @hide
+     */
+    public static TextServicesManager getInstance() {
+        synchronized (TextServicesManager.class) {
+            if (sInstance != null) {
+                return sInstance;
+            }
+            sInstance = new TextServicesManager();
+        }
+        return sInstance;
+    }
+
+    /**
+     * Get a spell checker session for the specified spell checker
+     * @param locale the locale for the spell checker
+     * @param listener a spell checker session lister for getting results from a spell checker.
+     * @param referToSpellCheckerLanguageSettings if true, the session for one of enabled
+     * languages in settings will be returned.
+     * @return the spell checker session of the spell checker
+     */
+    // TODO: Add a method to get enabled spell checkers.
+    // TODO: Handle referToSpellCheckerLanguageSettings
+    public SpellCheckerSession newSpellCheckerSession(Locale locale,
+            SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
+        if (listener == null) {
+            throw new NullPointerException();
+        }
+        // TODO: set a proper locale instead of the dummy locale
+        final String localeString = locale == null ? "en" : locale.toString();
+        final SpellCheckerInfo info;
+        try {
+            info = sService.getCurrentSpellChecker(localeString);
+        } catch (RemoteException e) {
+            return null;
+        }
+        if (info == null) {
+            return null;
+        }
+        final SpellCheckerSession session = new SpellCheckerSession(info, sService, listener);
+        try {
+            sService.getSpellCheckerService(info, localeString,
+                    session.getTextServicesSessionListener(),
+                    session.getSpellCheckerSessionListener());
+        } catch (RemoteException e) {
+            return null;
+        }
+        return session;
+    }
+
+    /**
+     * @hide
+     */
+    public SpellCheckerInfo[] getEnabledSpellCheckers() {
+        try {
+            final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers();
+            if (DBG) {
+                Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
+            }
+            return retval;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in getEnabledSpellCheckers: " + e);
+            return null;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public SpellCheckerInfo getCurrentSpellChecker() {
+        try {
+            // Passing null as a locale for ICS
+            return sService.getCurrentSpellChecker(null);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 5aa60f4..738bcb9 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -35,7 +35,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Surface;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 
 import junit.framework.Assert;
@@ -228,7 +228,7 @@
             sConfigCallback = new ConfigCallback(
                     (WindowManager) appContext.getSystemService(
                             Context.WINDOW_SERVICE));
-            ViewAncestor.addConfigCallback(sConfigCallback);
+            ViewRootImpl.addConfigCallback(sConfigCallback);
         }
         sConfigCallback.addHandler(this);
 
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 0294e3f..88583df 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -120,6 +120,7 @@
     private static final int AUTO_LOGIN                          = 140;
     private static final int CLIENT_CERT_REQUEST                 = 141;
     private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK     = 142;
+    private static final int SEARCHBOX_DISPATCH_COMPLETE_CALLBACK= 143;
 
     // Message triggered by the client to resume execution
     private static final int NOTIFY                              = 200;
@@ -821,6 +822,13 @@
                 searchBox.handleIsSupportedCallback(supported);
                 break;
             }
+            case SEARCHBOX_DISPATCH_COMPLETE_CALLBACK: {
+                SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
+                Boolean success = (Boolean) msg.obj;
+                searchBox.handleDispatchCompleteCallback(msg.getData().getString("function"),
+                        msg.getData().getInt("id"), success);
+                break;
+            }
         }
     }
 
@@ -1641,4 +1649,13 @@
         msg.obj = new Boolean(isSupported);
         sendMessage(msg);
     }
+
+    void onSearchboxDispatchCompleteCallback(String function, int id, boolean success) {
+        Message msg = obtainMessage(SEARCHBOX_DISPATCH_COMPLETE_CALLBACK);
+        msg.obj = Boolean.valueOf(success);
+        msg.getData().putString("function", function);
+        msg.getData().putInt("id", id);
+
+        sendMessage(msg);
+    }
 }
diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java
index 3cb5e24..a21d3ee 100644
--- a/core/java/android/webkit/DebugFlags.java
+++ b/core/java/android/webkit/DebugFlags.java
@@ -47,7 +47,7 @@
     public static final boolean WEB_VIEW_CORE = false;
     /*
      * Set to true to allow the WebTextView to draw on top of the web page in a
-     * different color so that you can see how the two line up.
+     * different color with no background so you can see how the two line up.
      */
     public static final boolean DRAW_WEBTEXTVIEW = false;
 }
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index bb4d192..620973e 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.io.InputStream;
@@ -38,7 +39,7 @@
 
     private static boolean initialized = false;
 
-    private static void checkIntialized() {
+    private static void checkInitialized() {
         if (!initialized) {
             throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class");
         }
@@ -63,7 +64,7 @@
      * @return String The application's database directory
      */
     private static synchronized String getDatabaseDirectory() {
-        checkIntialized();
+        checkInitialized();
 
         if (sDatabaseDirectory == null)
             sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent();
@@ -76,7 +77,7 @@
      * @return String The application's cache directory
      */
     private static synchronized String getCacheDirectory() {
-        checkIntialized();
+        checkInitialized();
 
         if (sCacheDirectory == null)
             sCacheDirectory = sContext.getCacheDir().getAbsolutePath();
@@ -166,5 +167,13 @@
         return sUseChromiumHttpStack;
     }
 
+    private static synchronized String getAutofillQueryUrl() {
+        checkInitialized();
+        // If the device has not checked in it won't have pulled down the system setting for the
+        // Autofill Url. In that case we will not make autofill server requests.
+        return Settings.Secure.getString(sContext.getContentResolver(),
+                Settings.Secure.WEB_AUTOFILL_QUERY_URL);
+    }
+
     private static native boolean nativeUseChromiumHttpStack();
 }
diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java
index 5075302..6512c4b 100644
--- a/core/java/android/webkit/SearchBox.java
+++ b/core/java/android/webkit/SearchBox.java
@@ -68,11 +68,15 @@
      * Notify the search page of any changes to the searchbox. Such as
      * a change in the typed query (onchange), the user commiting a given query
      * (onsubmit), or a change in size of a suggestions dropdown (onresize).
+     *
+     * @param listener an optional listener to notify of the success of the operation,
+     *      indicating if the javascript function existed and could be called or not.
+     *      It will be called on the UI thread.
      */
-    void onchange();
-    void onsubmit();
-    void onresize();
-    void oncancel();
+    void onchange(SearchBoxListener listener);
+    void onsubmit(SearchBoxListener listener);
+    void onresize(SearchBoxListener listener);
+    void oncancel(SearchBoxListener listener);
 
     /**
      * Add and remove listeners to the given Searchbox. Listeners are notified
@@ -91,8 +95,12 @@
      * Listeners (if any) will be called on the thread that created the
      * webview.
      */
-    interface SearchBoxListener {
-        void onSuggestionsReceived(String query, List<String> suggestions);
+    public abstract class SearchBoxListener {
+        public void onSuggestionsReceived(String query, List<String> suggestions) {}
+        public void onChangeComplete(boolean called) {}
+        public void onSubmitComplete(boolean called) {}
+        public void onResizeComplete(boolean called) {}
+        public void onCancelComplete(boolean called) {}
     }
 
     interface IsSupportedCallback {
diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java
index 61fb2ce..9942d25 100644
--- a/core/java/android/webkit/SearchBoxImpl.java
+++ b/core/java/android/webkit/SearchBoxImpl.java
@@ -16,10 +16,12 @@
 
 package android.webkit;
 
+import android.text.TextUtils;
 import android.util.Log;
 import android.webkit.WebViewCore.EventHub;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 import org.json.JSONArray;
@@ -69,7 +71,7 @@
 
     private static final String SET_VERBATIM_SCRIPT
             =  "if (window.chrome && window.chrome.searchBox) {"
-            + "  window.chrome.searchBox.verbatim = %s;"
+            + "  window.chrome.searchBox.verbatim = %1$s;"
             + "}";
 
     private static final String SET_SELECTION_SCRIPT
@@ -89,13 +91,21 @@
             + "}";
 
     private static final String DISPATCH_EVENT_SCRIPT
-            = "if (window.chrome && window.chrome.searchBox &&"
-            + "  window.chrome.searchBox.on%1$s) { window.chrome.searchBox.on%1$s(); }";
+            = "if (window.chrome && window.chrome.searchBox && window.chrome.searchBox.on%1$s) {"
+            + "  window.chrome.searchBox.on%1$s();"
+            + "  window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, true);"
+            + "} else {"
+            + "  window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, false);"
+            + "}";
+
+    private static final String EVENT_CHANGE = "change";
+    private static final String EVENT_SUBMIT = "submit";
+    private static final String EVENT_RESIZE = "resize";
+    private static final String EVENT_CANCEL = "cancel";
 
     private static final String IS_SUPPORTED_SCRIPT
             = "if (window.searchBoxJavaBridge_) {"
-            + "  if (window.chrome && window.chrome.searchBox && "
-            + "  window.chrome.searchBox.onsubmit) {"
+            + "  if (window.chrome && window.chrome.sv) {"
             + "    window.searchBoxJavaBridge_.isSupportedCallback(true);"
             + "  } else {"
             + "    window.searchBoxJavaBridge_.isSupportedCallback(false);"
@@ -105,11 +115,14 @@
     private final WebViewCore mWebViewCore;
     private final CallbackProxy mCallbackProxy;
     private IsSupportedCallback mSupportedCallback;
+    private int mNextEventId = 1;
+    private final HashMap<Integer, SearchBoxListener> mEventCallbacks;
 
     SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
         mListeners = new ArrayList<SearchBoxListener>();
         mWebViewCore = webViewCore;
         mCallbackProxy = callbackProxy;
+        mEventCallbacks = new HashMap<Integer, SearchBoxListener>();
     }
 
     @Override
@@ -141,27 +154,36 @@
     }
 
     @Override
-    public void onchange() {
-        dispatchEvent("change");
+    public void onchange(SearchBoxListener callback) {
+        dispatchEvent(EVENT_CHANGE, callback);
     }
 
     @Override
-    public void onsubmit() {
-        dispatchEvent("submit");
+    public void onsubmit(SearchBoxListener callback) {
+        dispatchEvent(EVENT_SUBMIT, callback);
     }
 
     @Override
-    public void onresize() {
-        dispatchEvent("resize");
+    public void onresize(SearchBoxListener callback) {
+        dispatchEvent(EVENT_RESIZE, callback);
     }
 
     @Override
-    public void oncancel() {
-        dispatchEvent("cancel");
+    public void oncancel(SearchBoxListener callback) {
+        dispatchEvent(EVENT_CANCEL, callback);
     }
 
-    private void dispatchEvent(String eventName) {
-        final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName);
+    private void dispatchEvent(String eventName, SearchBoxListener callback) {
+        int eventId;
+        if (callback != null) {
+            synchronized(this) {
+                eventId = mNextEventId++;
+                mEventCallbacks.put(eventId, callback);
+            }
+        } else {
+            eventId = 0;
+        }
+        final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName, eventId);
         dispatchJs(js);
     }
 
@@ -202,9 +224,35 @@
         }
     }
 
+    // Called by Javascript through the Java bridge.
+    public void dispatchCompleteCallback(String function, int id, boolean successful) {
+        mCallbackProxy.onSearchboxDispatchCompleteCallback(function, id, successful);
+    }
+
+    public void handleDispatchCompleteCallback(String function, int id, boolean successful) {
+        if (id != 0) {
+            SearchBoxListener listener;
+            synchronized(this) {
+                listener = mEventCallbacks.get(id);
+                mEventCallbacks.remove(id);
+            }
+            if (listener != null) {
+                if (TextUtils.equals(EVENT_CHANGE, function)) {
+                    listener.onChangeComplete(successful);
+                } else if (TextUtils.equals(EVENT_SUBMIT, function)) {
+                    listener.onSubmitComplete(successful);
+                } else if (TextUtils.equals(EVENT_RESIZE, function)) {
+                    listener.onResizeComplete(successful);
+                } else if (TextUtils.equals(EVENT_CANCEL, function)) {
+                    listener.onCancelComplete(successful);
+                }
+            }
+        }
+    }
+
     // 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) {
+    private static String jsonSerialize(String query) {
         JSONStringer stringer = new JSONStringer();
         try {
             stringer.array().value(query).endArray();
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 761007f..d584acd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1783,6 +1783,20 @@
     }
 
     /**
+     * @hide
+     */
+    public void setProperty(String key, String value) {
+        mWebView.nativeSetProperty(key, value);
+    }
+
+    /**
+     * @hide
+     */
+    public String getProperty(String key) {
+        return mWebView.nativeGetProperty(key);
+    }
+
+    /**
      * Transfer messages from the queue to the new WebCoreThread. Called from
      * WebCore thread.
      */
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index d54230c..b8c4e22 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -25,7 +25,7 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -87,7 +87,6 @@
     // Keep track of the text before the change so we know whether we actually
     // need to send down the DOM events.
     private String          mPreChange;
-    private Drawable        mBackground;
     // Variables for keeping track of the touch down, to send to the WebView
     // when a drag starts
     private float           mDragStartX;
@@ -190,6 +189,8 @@
         // that other applications that use embedded WebViews will properly
         // display the text in password textfields.
         setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
+        setBackgroundDrawable(DebugFlags.DRAW_WEBTEXTVIEW ? null : new ColorDrawable(Color.WHITE));
+
         // This helps to align the text better with the text in the web page.
         setIncludeFontPadding(false);
 
@@ -423,24 +424,6 @@
         // makeNewLayout does.
         super.makeNewLayout(w, hintWidth, boring, hintBoring, ellipsisWidth,
                 bringIntoView);
-
-        // For fields that do not draw, create a layout which is altered so that
-        // the text lines up.
-        if (DebugFlags.DRAW_WEBTEXTVIEW || willNotDraw()) {
-            float lineHeight = -1;
-            if (mWebView != null) {
-                float height = mWebView.nativeFocusCandidateLineHeight();
-                if (height != -1) {
-                    lineHeight = height * mWebView.getScale();
-                }
-            }
-            CharSequence text = getText();
-            // Copy from the existing Layout.
-            mLayout = new WebTextViewLayout(text, text, getPaint(), mLayout.getWidth(),
-                    mLayout.getAlignment(), mLayout.getSpacingMultiplier(),
-                    mLayout.getSpacingAdd(), false, null, ellipsisWidth,
-                    lineHeight);
-        }
         lineUpScroll();
     }
 
@@ -491,51 +474,6 @@
         return connection;
     }
 
-    /**
-     * In general, TextView makes a call to InputMethodManager.updateSelection
-     * in onDraw.  However, in the general case of WebTextView, we do not draw.
-     * This method is called by WebView.onDraw to take care of the part that
-     * needs to be called.
-     */
-    /* package */ void onDrawSubstitute() {
-        if (!willNotDraw()) {
-            // If the WebTextView is set to draw, such as in the case of a
-            // password, onDraw calls updateSelection(), so this code path is
-            // unnecessary.
-            return;
-        }
-        // This code is copied from TextView.onDraw().  That code does not get
-        // executed, however, because the WebTextView does not draw, allowing
-        // webkit's drawing to show through.
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null && imm.isActive(this)) {
-            Spannable sp = (Spannable) getText();
-            int selStart = Selection.getSelectionStart(sp);
-            int selEnd = Selection.getSelectionEnd(sp);
-            int candStart = EditableInputConnection.getComposingSpanStart(sp);
-            int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
-            imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        // onDraw should only be called for password fields.  If WebTextView is
-        // still drawing, but is no longer corresponding to a password field,
-        // remove it.
-        if (!DebugFlags.DRAW_WEBTEXTVIEW && (mWebView == null
-                || !mWebView.nativeFocusCandidateIsPassword()
-                || !isSameTextField(mWebView.nativeFocusCandidatePointer()))) {
-            // Although calling remove() would seem to make more sense here,
-            // changing it to not be a password field will make it not draw.
-            // Other code will make sure that it is removed completely, but this
-            // way the user will not see it.
-            setInPassword(false);
-        } else {
-            super.onDraw(canvas);
-        }
-    }
-
     @Override
     public void onEditorAction(int actionCode) {
         switch (actionCode) {
@@ -928,102 +866,6 @@
         if (mWebView != null) mWebView.incrementTextGeneration();
     }
 
-    /**
-     * Determine whether to use the system-wide password disguising method,
-     * or to use none.
-     * @param   inPassword  True if the textfield is a password field.
-     */
-    /* package */ void setInPassword(boolean inPassword) {
-        if (inPassword) {
-            setInputType(InputType.TYPE_CLASS_TEXT | EditorInfo.
-                TYPE_TEXT_VARIATION_WEB_PASSWORD);
-            createBackground();
-        }
-        // For password fields, draw the WebTextView.  For others, just show
-        // webkit's drawing.
-        if (!DebugFlags.DRAW_WEBTEXTVIEW) {
-            setWillNotDraw(!inPassword);
-        }
-        setBackgroundDrawable(inPassword ? mBackground : null);
-    }
-
-    /**
-     * Private class used for the background of a password textfield.
-     */
-    private static class OutlineDrawable extends Drawable {
-        private Paint mBackgroundPaint;
-        private Paint mOutlinePaint;
-        private float[] mLines;
-        public OutlineDrawable() {
-            mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            mBackgroundPaint.setColor(Color.WHITE);
-
-            mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            mOutlinePaint.setColor(Color.BLACK);
-            mOutlinePaint.setStyle(Paint.Style.STROKE);
-
-            mLines = new float[16];
-        }
-        @Override
-        public void setBounds(int left, int top, int right, int bottom) {
-            super.setBounds(left, top, right, bottom);
-            bottom--;
-            right -= 2;
-            // Top line
-            mLines[0] = left;
-            mLines[1] = top + 1;
-            mLines[2] = right;
-            mLines[3] = top + 1;
-            // Right line
-            mLines[4] = right;
-            mLines[5] = top;
-            mLines[6] = right;
-            mLines[7] = bottom;
-            // Bottom line
-            mLines[8] = left;
-            mLines[9] = bottom;
-            mLines[10] = right;
-            mLines[11] = bottom;
-            // Left line
-            mLines[12] = left + 1;
-            mLines[13] = top;
-            mLines[14] = left + 1;
-            mLines[15] = bottom;
-        }
-        @Override
-        public void draw(Canvas canvas) {
-            // Draw the background.
-            canvas.drawRect(getBounds(), mBackgroundPaint);
-            // Draw the outline.
-            canvas.drawLines(mLines, mOutlinePaint);
-        }
-        // Always want it to be opaque.
-        @Override
-        public int getOpacity() {
-            return PixelFormat.OPAQUE;
-        }
-        // These are needed because they are abstract in Drawable.
-        @Override
-        public void setAlpha(int alpha) { }
-        @Override
-        public void setColorFilter(ColorFilter cf) { }
-    }
-
-    /**
-     * Create a background for the WebTextView and set up the paint for drawing
-     * the text.  This way, we can see the password transformation of the
-     * system, which (optionally) shows the actual text before changing to dots.
-     * The background is necessary to hide the webkit-drawn text beneath.
-     */
-    private void createBackground() {
-        if (mBackground != null) {
-            return;
-        }
-        mBackground = new OutlineDrawable();
-
-        setGravity(Gravity.CENTER_VERTICAL);
-    }
-
     @Override
     public void setInputType(int type) {
         mFromSetInputType = true;
@@ -1072,7 +914,8 @@
             lp.height = height;
         }
         if (getParent() == null) {
-            mWebView.addView(this, lp);
+            // Insert the view so that it's drawn first (at index 0)
+            mWebView.addView(this, 0, lp);
         } else {
             setLayoutParams(lp);
         }
@@ -1145,7 +988,6 @@
     /* package */ void setType(int type) {
         if (mWebView == null) return;
         boolean single = true;
-        boolean inPassword = false;
         int maxLength = -1;
         int inputType = InputType.TYPE_CLASS_TEXT
                 | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
@@ -1167,7 +1009,7 @@
                 imeOptions |= EditorInfo.IME_ACTION_NONE;
                 break;
             case PASSWORD:
-                inPassword = true;
+                inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
                 imeOptions |= EditorInfo.IME_ACTION_GO;
                 break;
             case SEARCH:
@@ -1219,7 +1061,7 @@
         setHorizontallyScrolling(single);
         setInputType(inputType);
         setImeOptions(imeOptions);
-        setInPassword(inPassword);
+        setVisibility(VISIBLE);
         AutoCompleteAdapter adapter = null;
         setAdapterCustom(adapter);
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7ba86a5..a935a67 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4068,9 +4068,6 @@
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
             invalidate();
         }
-        if (inEditingMode()) {
-            mWebTextView.onDrawSubstitute();
-        }
         mWebViewCore.signalRepaintDone();
 
         if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas)) {
@@ -4287,18 +4284,18 @@
 
     private void onZoomAnimationStart() {
         // If it is in password mode, turn it off so it does not draw misplaced.
-        if (inEditingMode() && nativeFocusCandidateIsPassword()) {
-            mWebTextView.setInPassword(false);
+        if (inEditingMode()) {
+            mWebTextView.setVisibility(INVISIBLE);
         }
     }
 
     private void onZoomAnimationEnd() {
         // adjust the edit text view if needed
-        if (inEditingMode() && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)
-                && nativeFocusCandidateIsPassword()) {
+        if (inEditingMode()
+                && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)) {
             // If it is a password field, start drawing the WebTextView once
             // again.
-            mWebTextView.setInPassword(true);
+            mWebTextView.setVisibility(VISIBLE);
         }
     }
 
@@ -4593,37 +4590,23 @@
         }
         String text = nativeFocusCandidateText();
         int nodePointer = nativeFocusCandidatePointer();
-        if (alreadyThere && mWebTextView.isSameTextField(nodePointer)) {
-            // It is possible that we have the same textfield, but it has moved,
-            // i.e. In the case of opening/closing the screen.
-            // In that case, we need to set the dimensions, but not the other
-            // aspects.
-            // If the text has been changed by webkit, update it.  However, if
-            // there has been more UI text input, ignore it.  We will receive
-            // another update when that text is recognized.
-            if (text != null && !text.equals(mWebTextView.getText().toString())
-                    && nativeTextGeneration() == mTextGeneration) {
-                mWebTextView.setTextAndKeepSelection(text);
+        mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
+                Gravity.RIGHT : Gravity.NO_GRAVITY);
+        // This needs to be called before setType, which may call
+        // requestFormData, and it needs to have the correct nodePointer.
+        mWebTextView.setNodePointer(nodePointer);
+        mWebTextView.setType(nativeFocusCandidateType());
+        updateWebTextViewPadding();
+        if (null == text) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "rebuildWebTextView null == text");
             }
-        } else {
-            mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
-                    Gravity.RIGHT : Gravity.NO_GRAVITY);
-            // This needs to be called before setType, which may call
-            // requestFormData, and it needs to have the correct nodePointer.
-            mWebTextView.setNodePointer(nodePointer);
-            mWebTextView.setType(nativeFocusCandidateType());
-            updateWebTextViewPadding();
-            if (null == text) {
-                if (DebugFlags.WEB_VIEW) {
-                    Log.v(LOGTAG, "rebuildWebTextView null == text");
-                }
-                text = "";
-            }
-            mWebTextView.setTextAndKeepSelection(text);
-            InputMethodManager imm = InputMethodManager.peekInstance();
-            if (imm != null && imm.isActive(mWebTextView)) {
-                imm.restartInput(mWebTextView);
-            }
+            text = "";
+        }
+        mWebTextView.setTextAndKeepSelection(text);
+        InputMethodManager imm = InputMethodManager.peekInstance();
+        if (imm != null && imm.isActive(mWebTextView)) {
+            imm.restartInput(mWebTextView);
         }
         if (isFocused()) {
             mWebTextView.requestFocus();
@@ -4701,6 +4684,7 @@
         private Message mUpdateMessage;
         private boolean mAutoFillable;
         private boolean mAutoComplete;
+        private WebSettings mWebSettings;
 
         public RequestFormData(String name, String url, Message msg,
                 boolean autoFillable, boolean autoComplete) {
@@ -4709,6 +4693,7 @@
             mUpdateMessage = msg;
             mAutoFillable = autoFillable;
             mAutoComplete = autoComplete;
+            mWebSettings = getSettings();
         }
 
         public void run() {
@@ -4718,8 +4703,7 @@
                 // Note that code inside the adapter click handler in WebTextView depends
                 // on the AutoFill item being at the top of the drop down list. If you change
                 // the order, make sure to do it there too!
-                WebSettings settings = getSettings();
-                if (settings != null && settings.getAutoFillProfile() != null) {
+                if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) {
                     pastEntries.add(getResources().getText(
                             com.android.internal.R.string.autofill_this_form).toString() +
                             " " +
@@ -6330,8 +6314,8 @@
         if (action == MotionEvent.ACTION_POINTER_DOWN) {
             cancelTouch();
             action = MotionEvent.ACTION_DOWN;
-        } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() == 2) {
-            // set mLastTouchX/Y to the remaining point
+        } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) {
+            // set mLastTouchX/Y to the remaining points for multi-touch.
             mLastTouchX = Math.round(x);
             mLastTouchY = Math.round(y);
         } else if (action == MotionEvent.ACTION_MOVE) {
@@ -8119,19 +8103,7 @@
                     // and representing the same node as the pointer.
                     if (inEditingMode() &&
                             mWebTextView.isSameTextField(msg.arg1)) {
-                        if (msg.getData().getBoolean("password")) {
-                            Spannable text = (Spannable) mWebTextView.getText();
-                            int start = Selection.getSelectionStart(text);
-                            int end = Selection.getSelectionEnd(text);
-                            mWebTextView.setInPassword(true);
-                            // Restore the selection, which may have been
-                            // ruined by setInPassword.
-                            Spannable pword =
-                                    (Spannable) mWebTextView.getText();
-                            Selection.setSelection(pword, start, end);
-                        // If the text entry has created more events, ignore
-                        // this one.
-                        } else if (msg.arg2 == mTextGeneration) {
+                        if (msg.arg2 == mTextGeneration) {
                             String text = (String) msg.obj;
                             if (null == text) {
                                 text = "";
@@ -9089,6 +9061,44 @@
         }
     }
 
+    /**
+     * Begin collecting per-tile profiling data
+     *
+     * @hide only used by profiling tests
+     */
+    public void tileProfilingStart() {
+        nativeTileProfilingStart();
+    }
+    /**
+     * Return per-tile profiling data
+     *
+     * @hide only used by profiling tests
+     */
+    public float tileProfilingStop() {
+        return nativeTileProfilingStop();
+    }
+
+    /** @hide only used by profiling tests */
+    public void tileProfilingClear() {
+        nativeTileProfilingClear();
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingNumFrames() {
+        return nativeTileProfilingNumFrames();
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingNumTilesInFrame(int frame) {
+        return nativeTileProfilingNumTilesInFrame(frame);
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingGetInt(int frame, int tile, String key) {
+        return nativeTileProfilingGetInt(frame, tile, key);
+    }
+    /** @hide only used by profiling tests */
+    public float tileProfilingGetFloat(int frame, int tile, String key) {
+        return nativeTileProfilingGetFloat(frame, tile, key);
+    }
+
     private native int nativeCacheHitFramePointer();
     private native boolean  nativeCacheHitIsPlugin();
     private native Rect nativeCacheHitNodeBounds();
@@ -9211,6 +9221,13 @@
     private native void     nativeStopGL();
     private native Rect     nativeSubtractLayers(Rect content);
     private native int      nativeTextGeneration();
+    private native void     nativeTileProfilingStart();
+    private native float    nativeTileProfilingStop();
+    private native void     nativeTileProfilingClear();
+    private native int      nativeTileProfilingNumFrames();
+    private native int      nativeTileProfilingNumTilesInFrame(int frame);
+    private native int      nativeTileProfilingGetInt(int frame, int tile, String key);
+    private native float    nativeTileProfilingGetFloat(int frame, int tile, String key);
     // Never call this version except by updateCachedTextfield(String) -
     // we always want to pass in our generation number.
     private native void     nativeUpdateCachedTextfield(String updatedText,
@@ -9234,4 +9251,6 @@
      */
     private native boolean  nativeScrollLayer(int layer, int newX, int newY);
     private native int      nativeGetBackgroundColor();
+    native void     nativeSetProperty(String key, String value);
+    native String   nativeGetProperty(String key);
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index c652e55..8d8023b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -248,7 +248,7 @@
 
     /* Get the BrowserFrame component. This is used for subwindow creation and
      * is called only from BrowserFrame in the WebCore thread. */
-    /* package */ BrowserFrame getBrowserFrame() {
+    /* package */ synchronized BrowserFrame getBrowserFrame() {
         return mBrowserFrame;
     }
 
@@ -1069,6 +1069,15 @@
                                 + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                 + " obj=" + msg.obj);
                     }
+                    if (mWebView == null
+                            && msg.what != EventHub.RESUME_TIMERS
+                            && msg.what != EventHub.PAUSE_TIMERS) {
+                        if (DebugFlags.WEB_VIEW_CORE) {
+                            Log.v(LOGTAG, "Rejecting message " + msg.what
+                                    + " because we are destroyed");
+                        }
+                        return;
+                    }
                     switch (msg.what) {
                         case WEBKIT_DRAW:
                             webkitDraw();
@@ -1757,30 +1766,17 @@
     }
 
     /**
-     * Removes pending messages and trigger a DESTROY message to send to
-     * WebCore.
+     * Sends a DESTROY message to WebCore.
      * Called from UI thread.
      */
     void destroy() {
-        // We don't want anyone to post a message between removing pending
-        // messages and sending the destroy message.
         synchronized (mEventHub) {
-            // RESUME_TIMERS and PAUSE_TIMERS are per process base. They need to
-            // be preserved even the WebView is destroyed.
-            // Note: we should not have more than one RESUME_TIMERS/PAUSE_TIMERS
-            boolean hasResume = mEventHub.hasMessages(EventHub.RESUME_TIMERS);
-            boolean hasPause = mEventHub.hasMessages(EventHub.PAUSE_TIMERS);
-            mEventHub.removeMessages();
+            // Do not call removeMessages as then we risk removing PAUSE_TIMERS
+            // or RESUME_TIMERS messages, which we must still handle as they
+            // are per process. DESTROY will instead trigger a white list in
+            // mEventHub, skipping any remaining messages in the queue
             mEventHub.sendMessageAtFrontOfQueue(
                     Message.obtain(null, EventHub.DESTROY));
-            if (hasPause) {
-                mEventHub.sendMessageAtFrontOfQueue(
-                        Message.obtain(null, EventHub.PAUSE_TIMERS));
-            }
-            if (hasResume) {
-                mEventHub.sendMessageAtFrontOfQueue(
-                        Message.obtain(null, EventHub.RESUME_TIMERS));
-            }
             mEventHub.blockMessages();
         }
     }
@@ -2113,13 +2109,17 @@
 
     // called from JNI or WebView thread
     /* package */ void contentDraw() {
-        // don't update the Picture until we have an initial width and finish
-        // the first layout
-        if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
-            return;
-        }
-        // only fire an event if this is our first request
         synchronized (this) {
+            if (mWebView == null || mBrowserFrame == null) {
+                // We were destroyed
+                return;
+            }
+            // don't update the Picture until we have an initial width and finish
+            // the first layout
+            if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
+                return;
+            }
+            // only fire an event if this is our first request
             if (mDrawIsScheduled) return;
             mDrawIsScheduled = true;
             if (mDrawIsPaused) return;
@@ -2344,7 +2344,9 @@
             webViewWidth = mWebView.getViewWidth();
             viewportWidth = (int) (webViewWidth / adjust);
             if (viewportWidth == 0) {
-                Log.w(LOGTAG, "Can't get the viewWidth after the first layout");
+                if (DebugFlags.WEB_VIEW_CORE) {
+                    Log.v(LOGTAG, "Can't get the viewWidth yet");
+                }
             }
         } else {
             webViewWidth = Math.round(viewportWidth * mCurrentViewScale);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 49ea944..70e48ad 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -794,6 +794,8 @@
             mInitialZoomOverview = false;
             dismissZoomPicker();
             mFocusMovementQueue.clear();
+            mFocusX = detector.getFocusX();
+            mFocusY = detector.getFocusY();
             mWebView.mViewManager.startZoom();
             mWebView.onPinchToZoomAnimationStart();
             mAccumulatedSpan = 0;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1449b18..c4458df 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -271,12 +271,6 @@
     Drawable mSelector;
 
     /**
-     * Set to true if we would like to have the selector showing itself.
-     * We still need to draw and position it even if this is false.
-     */
-    boolean mSelectorShowing;
-
-    /**
      * The current position of the selector in the list.
      */
     int mSelectorPosition = INVALID_POSITION;
@@ -1669,7 +1663,6 @@
         setSelectedPositionInt(INVALID_POSITION);
         setNextSelectedPositionInt(INVALID_POSITION);
         mSelectedTop = 0;
-        mSelectorShowing = false;
         mSelectorPosition = INVALID_POSITION;
         mSelectorRect.setEmpty();
         invalidate();
@@ -2025,7 +2018,7 @@
         final boolean isChildViewEnabled = mIsChildViewEnabled;
         if (sel.isEnabled() != isChildViewEnabled) {
             mIsChildViewEnabled = !isChildViewEnabled;
-            if (mSelectorShowing) {
+            if (getSelectedItemPosition() != INVALID_POSITION) {
                 refreshDrawableState();
             }
         }
@@ -2769,6 +2762,7 @@
                 // touch mode). Force an initial layout to get rid of the selection.
                 layoutChildren();
             }
+            updateSelectorState();
         } else {
             int touchMode = mTouchMode;
             if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) {
@@ -2823,9 +2817,11 @@
                     mPositionScroller.stop();
                 }
                 mTouchMode = TOUCH_MODE_OVERSCROLL;
+                mMotionX = (int) ev.getX();
                 mMotionY = mLastY = (int) ev.getY();
                 mMotionCorrection = 0;
                 mActivePointerId = ev.getPointerId(0);
+                mDirection = 0;
                 break;
             }
 
@@ -2847,14 +2843,6 @@
                         }
                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                     } else {
-                        if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
-                            // If we couldn't find a view to click on, but the down event
-                            // was touching the edge, we will bail out and try again.
-                            // This allows the edge correcting code in ViewAncestor to try to
-                            // find a nearby view to select
-                            return false;
-                        }
-
                         if (mTouchMode == TOUCH_MODE_FLING) {
                             // Stopped a fling. It is a scroll.
                             createScrollingCache();
@@ -2888,7 +2876,11 @@
         }
 
         case MotionEvent.ACTION_MOVE: {
-            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+            int pointerIndex = ev.findPointerIndex(mActivePointerId);
+            if (pointerIndex == -1) {
+                pointerIndex = 0;
+                mActivePointerId = ev.getPointerId(pointerIndex);
+            }
             final int y = (int) ev.getY(pointerIndex);
             deltaY = y - mMotionY;
             switch (mTouchMode) {
@@ -3004,9 +2996,38 @@
                         mDirection = newDirection;
                     }
 
-                    if (mDirection != newDirection) {
+                    int overScrollDistance = -incrementalDeltaY;
+                    if ((newScroll < 0 && oldScroll >= 0) || (newScroll > 0 && oldScroll <= 0)) {
+                        overScrollDistance = -oldScroll;
+                        incrementalDeltaY += overScrollDistance;
+                    } else {
+                        incrementalDeltaY = 0;
+                    }
+
+                    if (overScrollDistance != 0) {
+                        overScrollBy(0, overScrollDistance, 0, mScrollY, 0, 0,
+                                0, mOverscrollDistance, true);
+                        final int overscrollMode = getOverScrollMode();
+                        if (overscrollMode == OVER_SCROLL_ALWAYS ||
+                                (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
+                                        !contentFits())) {
+                            if (rawDeltaY > 0) {
+                                mEdgeGlowTop.onPull((float) overScrollDistance / getHeight());
+                                if (!mEdgeGlowBottom.isFinished()) {
+                                    mEdgeGlowBottom.onRelease();
+                                }
+                            } else if (rawDeltaY < 0) {
+                                mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight());
+                                if (!mEdgeGlowTop.isFinished()) {
+                                    mEdgeGlowTop.onRelease();
+                                }
+                            }
+                            invalidate();
+                        }
+                    }
+
+                    if (incrementalDeltaY != 0) {
                         // Coming back to 'real' list scrolling
-                        incrementalDeltaY = -newScroll;
                         mScrollY = 0;
                         invalidateParentIfNeeded();
 
@@ -3015,45 +3036,17 @@
                             trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
                         }
 
-                        // Check to see if we are back in
-                        View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
-                        if (motionView != null) {
-                            mTouchMode = TOUCH_MODE_SCROLL;
+                        mTouchMode = TOUCH_MODE_SCROLL;
 
-                            // We did not scroll the full amount. Treat this essentially like the
-                            // start of a new touch scroll
-                            final int motionPosition = findClosestMotionRow(y);
+                        // We did not scroll the full amount. Treat this essentially like the
+                        // start of a new touch scroll
+                        final int motionPosition = findClosestMotionRow(y);
 
-                            mMotionCorrection = 0;
-                            motionView = getChildAt(motionPosition - mFirstPosition);
-                            mMotionViewOriginalTop = motionView.getTop();
-                            mMotionY = y;
-                            mMotionPosition = motionPosition;
-                        }
-                    } else {
-                        overScrollBy(0, -incrementalDeltaY, 0, mScrollY, 0, 0,
-                                0, mOverscrollDistance, true);
-                        final int overscrollMode = getOverScrollMode();
-                        if (overscrollMode == OVER_SCROLL_ALWAYS ||
-                                (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
-                                        !contentFits())) {
-                            if (rawDeltaY > 0) {
-                                mEdgeGlowTop.onPull((float) -incrementalDeltaY / getHeight());
-                                if (!mEdgeGlowBottom.isFinished()) {
-                                    mEdgeGlowBottom.onRelease();
-                                }
-                            } else if (rawDeltaY < 0) {
-                                mEdgeGlowBottom.onPull((float) -incrementalDeltaY / getHeight());
-                                if (!mEdgeGlowTop.isFinished()) {
-                                    mEdgeGlowTop.onRelease();
-                                }
-                            }
-                            invalidate();
-                        }
-                        if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
-                            // Don't allow overfling if we're at the edge.
-                            mVelocityTracker.clear();
-                        }
+                        mMotionCorrection = 0;
+                        View motionView = getChildAt(motionPosition - mFirstPosition);
+                        mMotionViewOriginalTop = motionView != null ? motionView.getTop() : 0;
+                        mMotionY = y;
+                        mMotionPosition = motionPosition;
                     }
                     mLastY = y;
                     mDirection = newDirection;
@@ -3330,12 +3323,6 @@
             mScrollY = scrollY;
             invalidateParentIfNeeded();
 
-            if (clampedY) {
-                // Velocity is broken by hitting the limit; don't start a fling off of this.
-                if (mVelocityTracker != null) {
-                    mVelocityTracker.clear();
-                }
-            }
             awakenScrollBars();
         }
     }
@@ -3464,7 +3451,11 @@
         case MotionEvent.ACTION_MOVE: {
             switch (mTouchMode) {
             case TOUCH_MODE_DOWN:
-                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                if (pointerIndex == -1) {
+                    pointerIndex = 0;
+                    mActivePointerId = ev.getPointerId(pointerIndex);
+                }
                 final int y = (int) ev.getY(pointerIndex);
                 if (startScrollIfNeeded(y - mMotionY)) {
                     return true;
@@ -3622,9 +3613,8 @@
         }
 
         void startOverfling(int initialVelocity) {
-            final int min = mScrollY > 0 ? Integer.MIN_VALUE : 0;
-            final int max = mScrollY > 0 ? 0 : Integer.MAX_VALUE;
-            mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, min, max, 0, getHeight());
+            mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0,
+                    Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight());
             mTouchMode = TOUCH_MODE_OVERFLING;
             invalidate();
             post(this);
@@ -3774,10 +3764,22 @@
                 final OverScroller scroller = mScroller;
                 if (scroller.computeScrollOffset()) {
                     final int scrollY = mScrollY;
-                    final int deltaY = scroller.getCurrY() - scrollY;
+                    final int currY = scroller.getCurrY();
+                    final int deltaY = currY - scrollY;
                     if (overScrollBy(0, deltaY, 0, scrollY, 0, 0,
                             0, mOverflingDistance, false)) {
-                        startSpringback();
+                        final boolean crossDown = scrollY <= 0 && currY > 0;
+                        final boolean crossUp = scrollY >= 0 && currY < 0;
+                        if (crossDown || crossUp) {
+                            int velocity = (int) scroller.getCurrVelocity();
+                            if (crossUp) velocity = -velocity;
+
+                            // Don't flywheel from this; we're just continuing things.
+                            scroller.abortAnimation();
+                            start(velocity);
+                        } else {
+                            startSpringback();
+                        }
                     } else {
                         invalidate();
                         post(this);
@@ -4521,7 +4523,6 @@
             setSelectedPositionInt(INVALID_POSITION);
             setNextSelectedPositionInt(INVALID_POSITION);
             mSelectedTop = 0;
-            mSelectorShowing = false;
         }
     }
 
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index 83f80ff..4b0a6da 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -126,7 +126,7 @@
          */
         // 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,
+        public void sort(Intent intent, List<ActivityResolveInfo> activities,
                 List<HistoricalRecord> historicalRecords);
     }
 
@@ -215,7 +215,7 @@
     /**
      * List of activities that can handle the current intent.
      */
-    private final List<Activity> mActivitys = new ArrayList<Activity>();
+    private final List<ActivityResolveInfo> mActivites = new ArrayList<ActivityResolveInfo>();
 
     /**
      * List with historical choice records.
@@ -311,15 +311,13 @@
      * @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);
             }
+            dataModel.readHistoricalData();
             return dataModel;
         }
     }
@@ -380,7 +378,7 @@
      */
     public int getActivityCount() {
         synchronized (mInstanceLock) {
-            return mActivitys.size();
+            return mActivites.size();
         }
     }
 
@@ -389,12 +387,12 @@
      *
      * @return The activity.
      *
-     * @see Activity
+     * @see ActivityResolveInfo
      * @see #setIntent(Intent)
      */
     public ResolveInfo getActivity(int index) {
         synchronized (mInstanceLock) {
-            return mActivitys.get(index).resolveInfo;
+            return mActivites.get(index).resolveInfo;
         }
     }
 
@@ -406,10 +404,10 @@
      * @return The index if found, -1 otherwise.
      */
     public int getActivityIndex(ResolveInfo activity) {
-        List<Activity> activities = mActivitys;
+        List<ActivityResolveInfo> activities = mActivites;
         final int activityCount = activities.size();
         for (int i = 0; i < activityCount; i++) {
-            Activity currentActivity = activities.get(i);
+            ActivityResolveInfo currentActivity = activities.get(i);
             if (currentActivity.resolveInfo == activity) {
                 return i;
             }
@@ -433,8 +431,7 @@
      * @see HistoricalRecord
      */
     public Intent chooseActivity(int index) {
-        Activity chosenActivity = mActivitys.get(index);
-        Activity defaultActivity = mActivitys.get(0);
+        ActivityResolveInfo chosenActivity = mActivites.get(index);
 
         ComponentName chosenName = new ComponentName(
                 chosenActivity.resolveInfo.activityInfo.packageName,
@@ -460,8 +457,8 @@
      */
     public ResolveInfo getDefaultActivity() {
         synchronized (mInstanceLock) {
-            if (!mActivitys.isEmpty()) {
-                return mActivitys.get(0).resolveInfo;
+            if (!mActivites.isEmpty()) {
+                return mActivites.get(0).resolveInfo;
             }
         }
         return null;
@@ -478,8 +475,8 @@
      * @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);
+        ActivityResolveInfo newDefaultActivity = mActivites.get(index);
+        ActivityResolveInfo oldDefaultActivity = mActivites.get(0);
 
         final float weight;
         if (oldDefaultActivity != null) {
@@ -509,7 +506,7 @@
      *       data is read until this method is invoked.
      * <p>
      */
-    public void readHistoricalData() {
+    private void readHistoricalData() {
         synchronized (mInstanceLock) {
             if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) {
                 return;
@@ -531,7 +528,7 @@
      * @throws IllegalStateException If this method is called before a call to
      *         {@link #readHistoricalData()}.
      */
-    public void persistHistoricalData() {
+    private void persistHistoricalData() {
         synchronized (mInstanceLock) {
             if (!mReadShareHistoryCalled) {
                 throw new IllegalStateException("No preceding call to #readHistoricalData");
@@ -572,8 +569,8 @@
      */
     private void sortActivities() {
         synchronized (mInstanceLock) {
-            if (mActivitySorter != null && !mActivitys.isEmpty()) {
-                mActivitySorter.sort(mIntent, mActivitys,
+            if (mActivitySorter != null && !mActivites.isEmpty()) {
+                mActivitySorter.sort(mIntent, mActivites,
                         Collections.unmodifiableList(mHistoricalRecords));
                 notifyChanged();
             }
@@ -633,6 +630,7 @@
             if (added) {
                 mHistoricalRecordsChanged = true;
                 pruneExcessiveHistoricalRecordsLocked();
+                persistHistoricalData();
                 sortActivities();
             }
             return added;
@@ -661,14 +659,14 @@
      * Loads the activities.
      */
     private void loadActivitiesLocked() {
-        mActivitys.clear();
+        mActivites.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));
+                mActivites.add(new ActivityResolveInfo(resolveInfo));
             }
             sortActivities();
         } else {
@@ -797,7 +795,7 @@
     /**
      * Represents an activity.
      */
-    public final class Activity implements Comparable<Activity> {
+    public final class ActivityResolveInfo implements Comparable<ActivityResolveInfo> {
 
         /**
          * The {@link ResolveInfo} of the activity.
@@ -814,7 +812,7 @@
          *
          * @param resolveInfo activity {@link ResolveInfo}.
          */
-        public Activity(ResolveInfo resolveInfo) {
+        public ActivityResolveInfo(ResolveInfo resolveInfo) {
             this.resolveInfo = resolveInfo;
         }
 
@@ -834,14 +832,14 @@
             if (getClass() != obj.getClass()) {
                 return false;
             }
-            Activity other = (Activity) obj;
+            ActivityResolveInfo other = (ActivityResolveInfo) obj;
             if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) {
                 return false;
             }
             return true;
         }
 
-        public int compareTo(Activity another) {
+        public int compareTo(ActivityResolveInfo another) {
              return  Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
         }
 
@@ -862,18 +860,18 @@
     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>();
+        private final Map<String, ActivityResolveInfo> mPackageNameToActivityMap =
+            new HashMap<String, ActivityResolveInfo>();
 
-        public void sort(Intent intent, List<Activity> activities,
+        public void sort(Intent intent, List<ActivityResolveInfo> activities,
                 List<HistoricalRecord> historicalRecords) {
-            Map<String, Activity> packageNameToActivityMap =
+            Map<String, ActivityResolveInfo> packageNameToActivityMap =
                 mPackageNameToActivityMap;
             packageNameToActivityMap.clear();
 
             final int activityCount = activities.size();
             for (int i = 0; i < activityCount; i++) {
-                Activity activity = activities.get(i);
+                ActivityResolveInfo activity = activities.get(i);
                 activity.weight = 0.0f;
                 String packageName = activity.resolveInfo.activityInfo.packageName;
                 packageNameToActivityMap.put(packageName, activity);
@@ -884,9 +882,11 @@
             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;
+                ActivityResolveInfo activity = packageNameToActivityMap.get(packageName);
+                if (activity != null) {
+                    activity.weight += historicalRecord.weight * nextRecordWeight;
+                    nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT;
+                }
             }
 
             Collections.sort(activities);
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 2fe8162..45d73af 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -16,18 +16,15 @@
 
 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.Resources;
 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;
@@ -56,11 +53,6 @@
  * </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
  */
@@ -84,37 +76,44 @@
     /**
      * The expand activities action button;
      */
-    private final ImageButton mExpandActivityOverflowButton;
+    private final FrameLayout mExpandActivityOverflowButton;
+
+    /**
+     * The image for the expand activities action button;
+     */
+    private final ImageView mExpandActivityOverflowButtonImage;
 
     /**
      * The default activities action button;
      */
-    private final ImageButton mDefaultActionButton;
+    private final FrameLayout mDefaultActivityButton;
 
     /**
-     * The header for handlers list.
+     * The image for the default activities action button;
      */
-    private final View mListHeaderView;
+    private final ImageView mDefaultActivityButtonImage;
 
     /**
-     * The footer for handlers list.
+     * The maximal width of the list popup.
      */
-    private final View mListFooterView;
+    private final int mListPopupMaxWidth;
 
     /**
-     * The title of the header view.
+     * Observer for the model data.
      */
-    private TextView mListHeaderViewTitle;
+    private final DataSetObserver mModelDataSetOberver = new DataSetObserver() {
 
-    /**
-     * The title for expanding the activities list.
-     */
-    private final String mListHeaderViewTitleSelectDefault;
-
-    /**
-     * The title if no activity exist.
-     */
-    private final String mListHeaderViewTitleNoActivities;
+        @Override
+        public void onChanged() {
+            super.onChanged();
+            mAdapter.notifyDataSetChanged();
+        }
+        @Override
+        public void onInvalidated() {
+            super.onInvalidated();
+            mAdapter.notifyDataSetInvalidated();
+        }
+    };
 
     /**
      * Popup window for showing the activity overflow list.
@@ -122,11 +121,6 @@
     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;
@@ -147,16 +141,6 @@
     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.
@@ -195,30 +179,23 @@
         Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
                 R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable);
 
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
         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);
+        mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
+        mDefaultActivityButton.setOnClickListener(mCallbacks);
+        mDefaultActivityButton.setOnLongClickListener(mCallbacks);
+        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
 
-        mExpandActivityOverflowButton = (ImageButton) findViewById(R.id.expand_activities_button);
+        mExpandActivityOverflowButton = (FrameLayout) 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);
+        mExpandActivityOverflowButtonImage =
+            (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image);
+        mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
 
         mAdapter = new ActivityChooserViewAdapter();
         mAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -228,6 +205,10 @@
                 updateButtons();
             }
         });
+
+        Resources resources = context.getResources();
+        mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
+              resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
     }
 
     /**
@@ -253,7 +234,7 @@
      * @param drawable The drawable.
      */
     public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
-        mExpandActivityOverflowButton.setBackgroundDrawable(drawable);
+        mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
     }
 
     /**
@@ -262,7 +243,7 @@
      * @return True if the popup was shown, false if already showing.
      */
     public boolean showPopup() {
-        if (isShowingPopup()) {
+        if (isShowingPopup() || !mIsAttachedToWindow) {
             return false;
         }
         mIsSelectingDefaultActivity = false;
@@ -276,38 +257,30 @@
      * @param maxActivityCount The max number of activities to display.
      */
     private void showPopupUnchecked(int maxActivityCount) {
+        if (mAdapter.getDataModel() == null) {
+            throw new IllegalStateException("No data model. Did you call #setDataModel?");
+        }
+
         mAdapter.setMaxActivityCount(maxActivityCount);
-        if (mIsSelectingDefaultActivity) {
-            if (mAdapter.getActivityCount() > 0) {
-                mListHeaderViewTitle.setText(mListHeaderViewTitleSelectDefault);
+
+        final int activityCount = mAdapter.getActivityCount();
+        if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
+                && activityCount > maxActivityCount + 1) {
+            mAdapter.setShowFooterView(true);
+        } else {
+            mAdapter.setShowFooterView(false);
+        }
+
+        ListPopupWindow popupWindow = getListPopupWindow();
+        if (!popupWindow.isShowing()) {
+            if (mIsSelectingDefaultActivity) {
+                mAdapter.setShowDefaultActivity(true);
             } else {
-                mListHeaderViewTitle.setText(mListHeaderViewTitleNoActivities);
+                mAdapter.setShowDefaultActivity(false);
             }
-            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;
-            }
+            final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
+            popupWindow.setContentWidth(contentWidth);
+            popupWindow.show();
         }
     }
 
@@ -317,12 +290,7 @@
      * @return True if dismissed, false if already dismissed.
      */
     public boolean dismissPopup() {
-        if (!isShowingPopup()) {
-            return false;
-        }
-        if (mIsShowingAlertDialog) {
-            getAlertDilalog().dismiss();
-        } else if (mIsShowingPopuWindow) {
+        if (isShowingPopup()) {
             getListPopupWindow().dismiss();
         }
         return true;
@@ -334,12 +302,7 @@
      * @return True if the popup is shown.
      */
     public boolean isShowingPopup() {
-        if (mIsShowingAlertDialog) {
-            return getAlertDilalog().isShowing();
-        } else if (mIsShowingPopuWindow) {
-            return getListPopupWindow().isShowing();
-        }
-        return false;
+        return getListPopupWindow().isShowing();
     }
 
     @Override
@@ -347,7 +310,7 @@
         super.onAttachedToWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
         if (dataModel != null) {
-            dataModel.readHistoricalData();
+            dataModel.registerObserver(mModelDataSetOberver);
         }
         mIsAttachedToWindow = true;
     }
@@ -357,7 +320,7 @@
         super.onDetachedFromWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
         if (dataModel != null) {
-            dataModel.persistHistoricalData();
+            dataModel.unregisterObserver(mModelDataSetOberver);
         }
         mIsAttachedToWindow = false;
     }
@@ -371,13 +334,11 @@
 
     @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();
-            }
+        mActivityChooserContent.layout(0, 0, right - left, bottom - top);
+        if (getListPopupWindow().isShowing()) {
+            showPopupUnchecked(mAdapter.getMaxActivityCount());
+        } else {
+            dismissPopup();
         }
     }
 
@@ -429,28 +390,12 @@
     }
 
     /**
-     * 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);
+            mDefaultActivityButton.setVisibility(VISIBLE);
             if (mAdapter.getCount() > 0) {
                 mExpandActivityOverflowButton.setEnabled(true);
             } else {
@@ -458,9 +403,9 @@
             }
             ResolveInfo activity = mAdapter.getDefaultActivity();
             PackageManager packageManager = mContext.getPackageManager();
-            mDefaultActionButton.setBackgroundDrawable(activity.loadIcon(packageManager));
+            mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
         } else {
-            mDefaultActionButton.setVisibility(View.INVISIBLE);
+            mDefaultActivityButton.setVisibility(View.INVISIBLE);
             mExpandActivityOverflowButton.setEnabled(false);
         }
     }
@@ -469,24 +414,23 @@
      * Interface implementation to avoid publishing them in the APIs.
      */
     private class Callbacks implements AdapterView.OnItemClickListener,
-            View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener,
-            DialogInterface.OnDismissListener {
+            View.OnClickListener, View.OnLongClickListener, PopupWindow.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);
+                        // The item at position zero is the default already.
+                        if (position > 0) {
+                            mAdapter.getDataModel().setDefaultActivity(position);
+                        }
                     } else {
                         // The first item in the model is default action => adjust index
                         Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1);
@@ -500,7 +444,7 @@
 
         // View.OnClickListener
         public void onClick(View view) {
-            if (view == mDefaultActionButton) {
+            if (view == mDefaultActivityButton) {
                 dismissPopup();
                 ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
                 final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
@@ -517,7 +461,7 @@
         // OnLongClickListener#onLongClick
         @Override
         public boolean onLongClick(View view) {
-            if (view == mDefaultActionButton) {
+            if (view == mDefaultActivityButton) {
                 if (mAdapter.getCount() > 0) {
                     mIsSelectingDefaultActivity = true;
                     showPopupUnchecked(mInitialActivityCount);
@@ -530,16 +474,6 @@
 
         // 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();
         }
 
@@ -559,59 +493,35 @@
 
         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 = 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_FOOTER = 1;
 
         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 boolean mShowDefaultActivity;
 
-        private View mHeaderView;
-
-        private View mFooterView;
+        private boolean mShowFooterView;
 
         public void setDataModel(ActivityChooserModel dataModel) {
+            ActivityChooserModel oldDataModel = mAdapter.getDataModel();
+            if (oldDataModel != null && isShown()) {
+                oldDataModel.unregisterObserver(mModelDataSetOberver);
+            }
             mDataModel = dataModel;
-            mDataModel.registerObserver(mDataSetOberver);
+            if (dataModel != null && isShown()) {
+                dataModel.registerObserver(mModelDataSetOberver);
+            }
             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) {
+            if (mShowFooterView && position == getCount() - 1) {
                 return ITEM_VIEW_TYPE_FOOTER;
             } else {
                 return ITEM_VIEW_TYPE_ACTIVITY;
@@ -626,14 +536,11 @@
         public int getCount() {
             int count = 0;
             int activityCount = mDataModel.getActivityCount();
-            if (activityCount > 0) {
+            if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
                 activityCount--;
             }
             count = Math.min(activityCount, mMaxActivityCount);
-            if (mHeaderView != null) {
-                count++;
-            }
-            if (mFooterView != null) {
+            if (mShowFooterView) {
                 count++;
             }
             return count;
@@ -642,16 +549,13 @@
         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;
+                    return null;
                 case ITEM_VIEW_TYPE_ACTIVITY:
-                    int targetIndex = (mHeaderView == null) ? position : position - 1;
-                    if (mDefaultActivity != null) {
-                        targetIndex++;
+                    if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
+                        position++;
                     }
-                    return mDataModel.getActivity(targetIndex);
+                    return mDataModel.getActivity(position);
                 default:
                     throw new IllegalArgumentException();
             }
@@ -661,27 +565,19 @@
             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;
+                    if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {
+                        convertView = LayoutInflater.from(getContext()).inflate(
+                                R.layout.activity_chooser_view_list_item, parent, false);
+                        convertView.setId(ITEM_VIEW_TYPE_FOOTER);
+                        TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                        titleView.setText(mContext.getString(
+                                R.string.activity_chooser_view_see_all));
+                    }
+                    return convertView;
                 case ITEM_VIEW_TYPE_ACTIVITY:
                     if (convertView == null || convertView.getId() != R.id.list_item) {
                         convertView = LayoutInflater.from(getContext()).inflate(
@@ -691,10 +587,16 @@
                     // Set the icon
                     ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
                     ResolveInfo activity = (ResolveInfo) getItem(position);
-                    iconView.setBackgroundDrawable(activity.loadIcon(packageManager));
+                    iconView.setImageDrawable(activity.loadIcon(packageManager));
                     // Set the title.
                     TextView titleView = (TextView) convertView.findViewById(R.id.title);
                     titleView.setText(activity.loadLabel(packageManager));
+                    // Highlight the default.
+                    if (mShowDefaultActivity && position == 0) {
+                        convertView.setActivated(true);
+                    } else {
+                        convertView.setActivated(false);
+                    }
                     return convertView;
                 default:
                     throw new IllegalArgumentException();
@@ -702,7 +604,7 @@
         }
 
         public int measureContentWidth() {
-            // The user may have specified some of the target not to be show but we
+            // The user may have specified some of the target not to be shown but we
             // want to measure all of them since after expansion they should fit.
             final int oldMaxActivityCount = mMaxActivityCount;
             mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
@@ -733,19 +635,12 @@
         }
 
         public ResolveInfo getDefaultActivity() {
-            return mDefaultActivity;
+            return mDataModel.getDefaultActivity();
         }
 
-        public void setHeaderView(View headerView) {
-            if (mHeaderView != headerView) {
-                mHeaderView = headerView;
-                notifyDataSetChanged();
-            }
-        }
-
-        public void setFooterView(View footerView) {
-            if (mFooterView != footerView) {
-                mFooterView = footerView;
+        public void setShowFooterView(boolean showFooterView) {
+            if (mShowFooterView != showFooterView) {
+                mShowFooterView = showFooterView;
                 notifyDataSetChanged();
             }
         }
@@ -761,5 +656,12 @@
         public ActivityChooserModel getDataModel() {
             return mDataModel;
         }
+
+        public void setShowDefaultActivity(boolean showDefaultActivity) {
+            if (mShowDefaultActivity != showDefaultActivity) {
+                mShowDefaultActivity = showDefaultActivity;
+                notifyDataSetChanged();
+            }
+        }
     }
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 755d4e0..00c75a9 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -902,15 +902,16 @@
 
     @Override
     public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
-        // Add a record for ourselves as well.
-        AccessibilityEvent record = AccessibilityEvent.obtain();
-        record.setSource(this);
-        // Set the class since it is not populated in #dispatchPopulateAccessibilityEvent
-        record.setClassName(getClass().getName());
-        child.onInitializeAccessibilityEvent(record);
-        child.dispatchPopulateAccessibilityEvent(record);
-        event.appendRecord(record);
-        return true;
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // Add a record for ourselves as well.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            // Populate with the text of the requesting child.
+            child.dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 273c258..4419886 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -62,15 +62,14 @@
         super(context, attrs);
 
         TypedArray a = context.obtainStyledAttributes(attrs,
-                com.android.internal.R.styleable.ViewFlipper);
+                com.android.internal.R.styleable.AdapterViewFlipper);
         mFlipInterval = a.getInt(
-                com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
+                com.android.internal.R.styleable.AdapterViewFlipper_flipInterval, DEFAULT_INTERVAL);
         mAutoStart = a.getBoolean(
-                com.android.internal.R.styleable.ViewFlipper_autoStart, false);
+                com.android.internal.R.styleable.AdapterViewFlipper_autoStart, false);
 
-        // By default we want the flipper to loop
-        mLoopViews = a.getBoolean(
-                com.android.internal.R.styleable.AdapterViewAnimator_loopViews, true);
+        // A view flipper should cycle through the views
+        mLoopViews = true;
 
         a.recycle();
     }
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 3b16994..1b713c3 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -375,6 +375,7 @@
                 com.android.internal.R.styleable.TextAppearance);
         mDateTextSize = dateTextAppearance.getDimensionPixelSize(
                 R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
+        dateTextAppearance.recycle();
 
         int weekDayTextAppearanceResId = attributesArray.getResourceId(
                 R.styleable.CalendarView_weekDayTextAppearance,
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 8d4aaea..f3a6da7 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -39,8 +39,9 @@
     private boolean mChecked;
     private int mCheckMarkResource;
     private Drawable mCheckMarkDrawable;
-    private int mBasePaddingRight;
+    private int mBasePadding;
     private int mCheckMarkWidth;
+    private boolean mNeedRequestlayout;
 
     private static final int[] CHECKED_STATE_SET = {
         R.attr.state_checked
@@ -123,6 +124,7 @@
             mCheckMarkDrawable.setCallback(null);
             unscheduleDrawable(mCheckMarkDrawable);
         }
+        mNeedRequestlayout = (d != mCheckMarkDrawable);
         if (d != null) {
             d.setCallback(this);
             d.setVisible(getVisibility() == VISIBLE, false);
@@ -130,19 +132,35 @@
             setMinHeight(d.getIntrinsicHeight());
             
             mCheckMarkWidth = d.getIntrinsicWidth();
-            mPaddingRight = mCheckMarkWidth + mBasePaddingRight;
             d.setState(getDrawableState());
         } else {
-            mPaddingRight = mBasePaddingRight;
+            mCheckMarkWidth = 0;
         }
         mCheckMarkDrawable = d;
-        requestLayout();
+        // Do padding resolution. This will call setPadding() and do a requestLayout() if needed.
+        resolvePadding();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    protected void resolvePadding() {
+        super.resolvePadding();
+        int newPadding = (mCheckMarkDrawable != null) ?
+                mCheckMarkWidth + mBasePadding : mBasePadding;
+        mNeedRequestlayout |= (mPaddingRight != newPadding);
+        mPaddingRight = newPadding;
+        if (mNeedRequestlayout) {
+            requestLayout();
+            mNeedRequestlayout = false;
+        }
     }
     
     @Override
     public void setPadding(int left, int top, int right, int bottom) {
         super.setPadding(left, top, right, bottom);
-        mBasePaddingRight = mPaddingRight;
+        mBasePadding = mPaddingRight;
     }
 
     @Override
@@ -167,9 +185,9 @@
             
             int right = getWidth();
             checkMarkDrawable.setBounds(
-                    right - mCheckMarkWidth - mBasePaddingRight, 
+                    right - mPaddingRight,
                     y, 
-                    right - mBasePaddingRight, 
+                    right - mPaddingRight + mCheckMarkWidth,
                     y + height);
             checkMarkDrawable.draw(canvas);
         }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 2410eb2..d3cdad8 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -217,6 +217,7 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setCheckable(true);
         info.setChecked(mChecked);
     }
 
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 5eba1a0..0b0b812 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -34,12 +34,17 @@
 
 /**
  * FrameLayout is designed to block out an area on the screen to display
- * a single item. You can add multiple children to a FrameLayout and control their
- * position within the FrameLayout using {@link android.widget.FrameLayout.LayoutParams#gravity}.
- * Children are drawn in a stack, with the most recently added child on top.
- * The size of the frame layout is the size of its largest child (plus padding), visible
- * or not (if the FrameLayout's parent permits). Views that are GONE are used for sizing
- * only if {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}
+ * a single item. Generally, FrameLayout should be used to hold a single child view, because it can
+ * be difficult to organize child views in a way that's scalable to different screen sizes without
+ * the children overlapping each other. You can, however, add multiple children to a FrameLayout
+ * and control their position within the FrameLayout by assigning gravity to each child, using the
+ * <a href="FrameLayout.LayoutParams.html#attr_android:layout_gravity">{@code
+ * android:layout_gravity}</a> attribute.
+ * <p>Child views are drawn in a stack, with the most recently added child on top.
+ * The size of the FrameLayout is the size of its largest child (plus padding), visible
+ * or not (if the FrameLayout's parent permits). Views that are {@link android.view.View#GONE} are
+ * used for sizing
+ * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
  * is set to true.
  *
  * @attr ref android.R.styleable#FrameLayout_foreground
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 0ffd087..3f5b571c 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -16,28 +16,28 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewConfiguration;
 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;
 
+import com.android.internal.R;
+
 /**
  * A view that shows items in a center-locked, horizontally scrolling list.
  * <p>
@@ -122,6 +122,7 @@
      * in the future. It will also trigger a selection changed.
      */
     private Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() {
+        @Override
         public void run() {
             mSuppressSelectionChanged = false;
             selectionChanged();
@@ -171,6 +172,12 @@
      * drag sends many onScrolls).
      */
     private boolean mIsFirstScroll;
+
+    /**
+     * If true, mFirstPosition is the position of the rightmost child, and
+     * the children are ordered right to left.
+     */
+    private boolean mIsRtl = true;
     
     public Gallery(Context context) {
         this(context, null);
@@ -418,7 +425,7 @@
     }
 
     int getLimitedMotionScrollAmount(boolean motionToLeft, int deltaX) {
-        int extremeItemPosition = motionToLeft ? mItemCount - 1 : 0;
+        int extremeItemPosition = motionToLeft != mIsRtl ? mItemCount - 1 : 0;
         View extremeChild = getChildAt(extremeItemPosition - mFirstPosition);
         
         if (extremeChild == null) {
@@ -490,31 +497,40 @@
         if (toLeft) {
             final int galleryLeft = mPaddingLeft;
             for (int i = 0; i < numChildren; i++) {
-                final View child = getChildAt(i);
+                int n = mIsRtl ? (numChildren - 1 - i) : i;
+                final View child = getChildAt(n);
                 if (child.getRight() >= galleryLeft) {
                     break;
                 } else {
+                    start = n;
                     count++;
-                    mRecycler.put(firstPosition + i, child);
+                    mRecycler.put(firstPosition + n, child);
                 }
             }
+            if (!mIsRtl) {
+                start = 0;
+            }
         } else {
             final int galleryRight = getWidth() - mPaddingRight;
             for (int i = numChildren - 1; i >= 0; i--) {
-                final View child = getChildAt(i);
+                int n = mIsRtl ? numChildren - 1 - i : i;
+                final View child = getChildAt(n);
                 if (child.getLeft() <= galleryRight) {
                     break;
                 } else {
-                    start = i;
+                    start = n;
                     count++;
-                    mRecycler.put(firstPosition + i, child);
+                    mRecycler.put(firstPosition + n, child);
                 }
             }
+            if (mIsRtl) {
+                start = 0;
+            }
         }
 
         detachViewsFromParent(start, count);
         
-        if (toLeft) {
+        if (toLeft != mIsRtl) {
             mFirstPosition += count;
         }
     }
@@ -614,6 +630,8 @@
     @Override
     void layout(int delta, boolean animate) {
 
+        mIsRtl = isLayoutRtl();
+
         int childrenLeft = mSpinnerPadding.left;
         int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right;
 
@@ -676,6 +694,45 @@
     }
 
     private void fillToGalleryLeft() {
+        if (mIsRtl) {
+            fillToGalleryLeftRtl();
+        } else {
+            fillToGalleryLeftLtr();
+        }
+    }
+
+    private void fillToGalleryLeftRtl() {
+        int itemSpacing = mSpacing;
+        int galleryLeft = mPaddingLeft;
+        int numChildren = getChildCount();
+        int numItems = mItemCount;
+
+        // Set state for initial iteration
+        View prevIterationView = getChildAt(numChildren - 1);
+        int curPosition;
+        int curRightEdge;
+
+        if (prevIterationView != null) {
+            curPosition = mFirstPosition + numChildren;
+            curRightEdge = prevIterationView.getLeft() - itemSpacing;
+        } else {
+            // No children available!
+            mFirstPosition = curPosition = mItemCount - 1;
+            curRightEdge = mRight - mLeft - mPaddingRight;
+            mShouldStopFling = true;
+        }
+
+        while (curRightEdge > galleryLeft && curPosition < mItemCount) {
+            prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+                    curRightEdge, false);
+
+            // Set state for next iteration
+            curRightEdge = prevIterationView.getLeft() - itemSpacing;
+            curPosition++;
+        }
+    }
+
+    private void fillToGalleryLeftLtr() {
         int itemSpacing = mSpacing;
         int galleryLeft = mPaddingLeft;
         
@@ -708,6 +765,45 @@
     }
     
     private void fillToGalleryRight() {
+        if (mIsRtl) {
+            fillToGalleryRightRtl();
+        } else {
+            fillToGalleryRightLtr();
+        }
+    }
+
+    private void fillToGalleryRightRtl() {
+        int itemSpacing = mSpacing;
+        int galleryRight = mRight - mLeft - mPaddingRight;
+
+        // Set state for initial iteration
+        View prevIterationView = getChildAt(0);
+        int curPosition;
+        int curLeftEdge;
+
+        if (prevIterationView != null) {
+            curPosition = mFirstPosition -1;
+            curLeftEdge = prevIterationView.getRight() + itemSpacing;
+        } else {
+            curPosition = 0;
+            curLeftEdge = mPaddingLeft;
+            mShouldStopFling = true;
+        }
+
+        while (curLeftEdge < galleryRight && curPosition >= 0) {
+            prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+                    curLeftEdge, true);
+
+            // Remember some state
+            mFirstPosition = curPosition;
+
+            // Set state for next iteration
+            curLeftEdge = prevIterationView.getRight() + itemSpacing;
+            curPosition--;
+        }
+    }
+
+    private void fillToGalleryRightLtr() {
         int itemSpacing = mSpacing;
         int galleryRight = mRight - mLeft - mPaddingRight;
         int numChildren = getChildCount();
@@ -745,18 +841,16 @@
      * 
      * @param position Position in the gallery for the view to obtain
      * @param offset Offset from the selected position
-     * @param x X-coordintate indicating where this view should be placed. This
+     * @param x X-coordinate indicating where this view should be placed. This
      *        will either be the left or right edge of the view, depending on
-     *        the fromLeft paramter
-     * @param fromLeft Are we posiitoning views based on the left edge? (i.e.,
+     *        the fromLeft parameter
+     * @param fromLeft Are we positioning views based on the left edge? (i.e.,
      *        building from left to right)?
      * @return A view that has been added to the gallery
      */
-    private View makeAndAddView(int position, int offset, int x,
-            boolean fromLeft) {
+    private View makeAndAddView(int position, int offset, int x, boolean fromLeft) {
 
         View child;
-
         if (!mDataChanged) {
             child = mRecycler.get(position);
             if (child != null) {
@@ -786,27 +880,26 @@
 
     /**
      * Helper for makeAndAddView to set the position of a view and fill out its
-     * layout paramters.
+     * layout parameters.
      * 
      * @param child The view to position
      * @param offset Offset from the selected position
-     * @param x X-coordintate indicating where this view should be placed. This
+     * @param x X-coordinate indicating where this view should be placed. This
      *        will either be the left or right edge of the view, depending on
-     *        the fromLeft paramter
-     * @param fromLeft Are we posiitoning views based on the left edge? (i.e.,
+     *        the fromLeft parameter
+     * @param fromLeft Are we positioning views based on the left edge? (i.e.,
      *        building from left to right)?
      */
     private void setUpChild(View child, int offset, int x, boolean fromLeft) {
 
         // Respect layout params that are already in the view. Otherwise
         // make some up...
-        Gallery.LayoutParams lp = (Gallery.LayoutParams) 
-            child.getLayoutParams();
+        Gallery.LayoutParams lp = (Gallery.LayoutParams) child.getLayoutParams();
         if (lp == null) {
             lp = (Gallery.LayoutParams) generateDefaultLayoutParams();
         }
 
-        addViewInLayout(child, fromLeft ? -1 : 0, lp);
+        addViewInLayout(child, fromLeft != mIsRtl ? -1 : 0, lp);
 
         child.setSelected(offset == 0);
 
@@ -883,9 +976,7 @@
         return retValue;
     }
     
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean onSingleTapUp(MotionEvent e) {
 
         if (mDownTouchPosition >= 0) {
@@ -905,9 +996,7 @@
         return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
         
         if (!mShouldCallbackDuringFling) {
@@ -926,9 +1015,7 @@
         return true;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
 
         if (localLOGV) Log.v(TAG, String.valueOf(e2.getX() - e1.getX()));
@@ -967,9 +1054,7 @@
         return true;
     }
     
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean onDown(MotionEvent e) {
 
         // Kill any existing fling/scroll
@@ -1009,9 +1094,7 @@
         onUp();
     }
     
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void onLongPress(MotionEvent e) {
         
         if (mDownTouchPosition < 0) {
@@ -1025,9 +1108,7 @@
 
     // Unused methods from GestureDetector.OnGestureListener below
     
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void onShowPress(MotionEvent e) {
     }
 
@@ -1164,6 +1245,7 @@
     
                     dispatchPress(mSelectedChild);
                     postDelayed(new Runnable() {
+                        @Override
                         public void run() {
                             dispatchUnpress();
                         }
@@ -1278,10 +1360,10 @@
             // Draw the selected child last
             return selectedIndex;
         } else if (i >= selectedIndex) {
-            // Move the children to the right of the selected child earlier one
+            // Move the children after the selected child earlier one
             return i + 1;
         } else {
-            // Keep the children to the left of the selected child the same
+            // Keep the children before the selected child the same
             return i;
         }
     }
@@ -1306,7 +1388,6 @@
      * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to
      * initiate a fling. Each frame of the fling is handled in {@link #run()}.
      * A FlingRunnable will keep re-posting itself until the fling is done.
-     *
      */
     private class FlingRunnable implements Runnable {
         /**
@@ -1365,6 +1446,7 @@
             if (scrollIntoSlots) scrollIntoSlots();
         }
 
+        @Override
         public void run() {
 
             if (mItemCount == 0) {
@@ -1384,15 +1466,17 @@
 
             // Pretend that each frame of a fling scroll is a touch scroll
             if (delta > 0) {
-                // Moving towards the left. Use first view as mDownTouchPosition
-                mDownTouchPosition = mFirstPosition;
+                // Moving towards the left. Use leftmost view as mDownTouchPosition
+                mDownTouchPosition = mIsRtl ? (mFirstPosition + getChildCount() - 1) :
+                    mFirstPosition;
 
                 // Don't fling more than 1 screen
                 delta = Math.min(getWidth() - mPaddingLeft - mPaddingRight - 1, delta);
             } else {
-                // Moving towards the right. Use last view as mDownTouchPosition
+                // Moving towards the right. Use rightmost view as mDownTouchPosition
                 int offsetToLast = getChildCount() - 1;
-                mDownTouchPosition = mFirstPosition + offsetToLast;
+                mDownTouchPosition = mIsRtl ? mFirstPosition :
+                    (mFirstPosition + getChildCount() - 1);
 
                 // Don't fling more than 1 screen
                 delta = Math.max(-(getWidth() - mPaddingRight - mPaddingLeft - 1), delta);
@@ -1414,7 +1498,6 @@
      * Gallery extends LayoutParams to provide a place to hold current
      * Transformation information along with previous position/transformation
      * info.
-     * 
      */
     public static class LayoutParams extends ViewGroup.LayoutParams {
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index c2759e5..f999960 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -21,14 +21,13 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-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;
-import com.android.internal.R.styleable;
+import com.android.internal.R;
 
 import java.lang.reflect.Array;
 import java.util.ArrayList;
@@ -38,6 +37,7 @@
 import java.util.List;
 import java.util.Map;
 
+import static android.view.Gravity.*;
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 
@@ -53,12 +53,12 @@
  * container and grid index {@code N} is fixed to its trailing edge
  * (after padding is taken into account).
  *
- * <h4>Row and Column Groups</h4>
+ * <h4>Row and Column Specs</h4>
  *
  * Children occupy one or more contiguous cells, as defined
- * by their {@link GridLayout.LayoutParams#rowGroup rowGroup} and
- * {@link GridLayout.LayoutParams#columnGroup columnGroup} layout parameters.
- * Each group specifies the set of rows or columns that are to be
+ * by their {@link GridLayout.LayoutParams#rowSpec rowSpec} and
+ * {@link GridLayout.LayoutParams#columnSpec columnSpec} layout parameters.
+ * Each spec defines the set of rows or columns that are to be
  * occupied; and how children should be aligned within the resulting group of cells.
  * Although cells do not normally overlap in a GridLayout, GridLayout does
  * not prevent children being defined to occupy the same cell or group of cells.
@@ -92,7 +92,7 @@
  *
  * <h4>Excess Space Distribution</h4>
  *
- * A child's ability to stretch is controlled using the {@link Group#flexibility flexibility}
+ * A child's ability to stretch is controlled using the flexibility
  * properties of its row and column groups.
  * <p>
  * <p>
@@ -167,8 +167,7 @@
     // Misc constants
 
     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 boolean DEBUG = false;
     private static final int PRF = 1;
 
     // Defaults
@@ -178,19 +177,18 @@
     private static final boolean DEFAULT_USE_DEFAULT_MARGINS = false;
     private static final boolean DEFAULT_ORDER_PRESERVED = false;
     private static final int DEFAULT_ALIGNMENT_MODE = ALIGN_MARGINS;
-    // todo remove this
-    private static final int DEFAULT_CONTAINER_MARGIN = 20;
+    private static final int DEFAULT_CONTAINER_MARGIN = 0;
     private static final int MAX_SIZE = 100000;
 
     // TypedArray indices
 
-    private static final int ORIENTATION = styleable.GridLayout_orientation;
-    private static final int ROW_COUNT = styleable.GridLayout_rowCount;
-    private static final int COLUMN_COUNT = styleable.GridLayout_columnCount;
-    private static final int USE_DEFAULT_MARGINS = styleable.GridLayout_useDefaultMargins;
-    private static final int ALIGNMENT_MODE = styleable.GridLayout_alignmentMode;
-    private static final int ROW_ORDER_PRESERVED = styleable.GridLayout_rowOrderPreserved;
-    private static final int COLUMN_ORDER_PRESERVED = styleable.GridLayout_columnOrderPreserved;
+    private static final int ORIENTATION = R.styleable.GridLayout_orientation;
+    private static final int ROW_COUNT = R.styleable.GridLayout_rowCount;
+    private static final int COLUMN_COUNT = R.styleable.GridLayout_columnCount;
+    private static final int USE_DEFAULT_MARGINS = R.styleable.GridLayout_useDefaultMargins;
+    private static final int ALIGNMENT_MODE = R.styleable.GridLayout_alignmentMode;
+    private static final int ROW_ORDER_PRESERVED = R.styleable.GridLayout_rowOrderPreserved;
+    private static final int COLUMN_ORDER_PRESERVED = R.styleable.GridLayout_columnOrderPreserved;
 
     // Instance variables
 
@@ -200,7 +198,9 @@
     private int mOrientation = DEFAULT_ORIENTATION;
     private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
     private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
-    private int mDefaultGravity = Gravity.NO_GRAVITY;
+    private Alignment mColumnAlignment = LEFT;
+    private Alignment mRowAlignment = BASELINE;
+    private int mDefaultGap;
 
     // Constructors
 
@@ -212,13 +212,14 @@
         if (DEBUG) {
             setWillNotDraw(false);
         }
-        TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout);
+        mDefaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout);
         try {
             setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT));
             setColumnCount(a.getInt(COLUMN_COUNT, DEFAULT_COUNT));
-            mOrientation = a.getInt(ORIENTATION, DEFAULT_ORIENTATION);
-            mUseDefaultMargins = a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS);
-            mAlignmentMode = a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE);
+            setOrientation(a.getInt(ORIENTATION, DEFAULT_ORIENTATION));
+            setUseDefaultMargins(a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS));
+            setAlignmentMode(a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE));
             setRowOrderPreserved(a.getBoolean(ROW_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED));
             setColumnOrderPreserved(a.getBoolean(COLUMN_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED));
         } finally {
@@ -278,12 +279,12 @@
     /**
      * Returns the current number of rows. This is either the last value that was set
      * with {@link #setRowCount(int)} or, if no such value was set, the maximum
-     * value of each the upper bounds defined in {@link LayoutParams#rowGroup}.
+     * value of each the upper bounds defined in {@link LayoutParams#rowSpec}.
      *
      * @return the current number of rows
      *
      * @see #setRowCount(int)
-     * @see LayoutParams#rowGroup
+     * @see LayoutParams#rowSpec
      *
      * @attr ref android.R.styleable#GridLayout_rowCount
      */
@@ -299,7 +300,7 @@
      * @param rowCount the number of rows
      *
      * @see #getRowCount()
-     * @see LayoutParams#rowGroup
+     * @see LayoutParams#rowSpec
      *
      * @attr ref android.R.styleable#GridLayout_rowCount
      */
@@ -310,12 +311,12 @@
     /**
      * Returns the current number of columns. This is either the last value that was set
      * with {@link #setColumnCount(int)} or, if no such value was set, the maximum
-     * value of each the upper bounds defined in {@link LayoutParams#columnGroup}.
+     * value of each the upper bounds defined in {@link LayoutParams#columnSpec}.
      *
      * @return the current number of columns
      *
      * @see #setColumnCount(int)
-     * @see LayoutParams#columnGroup
+     * @see LayoutParams#columnSpec
      *
      * @attr ref android.R.styleable#GridLayout_columnCount
      */
@@ -331,7 +332,7 @@
      * @param columnCount the number of columns.
      *
      * @see #getColumnCount()
-     * @see LayoutParams#columnGroup
+     * @see LayoutParams#columnSpec
      *
      * @attr ref android.R.styleable#GridLayout_columnCount
      */
@@ -381,6 +382,10 @@
      */
     public void setUseDefaultMargins(boolean useDefaultMargins) {
         mUseDefaultMargins = useDefaultMargins;
+        if (useDefaultMargins) {
+            int padding = mDefaultGap;
+            setPadding(padding, padding, padding, padding);
+        }
         requestLayout();
     }
 
@@ -510,6 +515,8 @@
         requestLayout();
     }
 
+    // Static utility methods
+
     private static int max2(int[] a, int valueIfEmpty) {
         int result = valueIfEmpty;
         for (int i = 0, N = a.length; i < N; i++) {
@@ -518,6 +525,14 @@
         return result;
     }
 
+    private static int sum(int[] a) {
+        int result = 0;
+        for (int i = 0, N = a.length; i < N; i++) {
+            result += a[i];
+        }
+        return result;
+    }
+
     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);
@@ -525,17 +540,29 @@
         return result;
     }
 
+    private static Alignment getAlignment(int gravity, boolean horizontal) {
+        int mask = horizontal ? HORIZONTAL_GRAVITY_MASK : VERTICAL_GRAVITY_MASK;
+        int shift = horizontal ? AXIS_X_SHIFT : AXIS_Y_SHIFT;
+        int flags = (gravity & mask) >> shift;
+        switch (flags) {
+            case (AXIS_SPECIFIED | AXIS_PULL_BEFORE):
+                return LEADING;
+            case (AXIS_SPECIFIED | AXIS_PULL_AFTER):
+                return TRAILING;
+            case (AXIS_SPECIFIED | AXIS_PULL_BEFORE | AXIS_PULL_AFTER):
+                return FILL;
+            case AXIS_SPECIFIED:
+                return CENTER;
+            default:
+                return UNDEFINED_ALIGNMENT;
+        }
+    }
+
     private int getDefaultMargin(View c, boolean horizontal, boolean leading) {
-        // In the absence of any other information, calculate a default gap such
-        // that, in a grid of identical components, the heights and the vertical
-        // gaps are in the proportion of the golden ratio.
-        // To effect this with equal margins at each edge, set each of the
-        // four margin values to half this amount.
-        return (int) (c.getMeasuredHeight() / GOLDEN_RATIO / 2);
+        return mDefaultGap / 2;
     }
 
     private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
-        // todo remove DEFAULT_CONTAINER_MARGIN. Use padding? Seek advice on Themes/Styles, etc.
         return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
     }
 
@@ -543,9 +570,9 @@
         if (!mUseDefaultMargins) {
             return 0;
         }
-        Group group = horizontal ? p.columnGroup : p.rowGroup;
+        Spec spec = horizontal ? p.columnSpec : p.rowSpec;
         Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
-        Interval span = group.span;
+        Interval span = spec.span;
         boolean isAtEdge = leading ? (span.min == 0) : (span.max == axis.getCount());
 
         return getDefaultMargin(c, isAtEdge, horizontal, leading);
@@ -590,15 +617,14 @@
                 int col = 0;
                 for (int i = 0, N = getChildCount(); i < N; i++) {
                     View c = getChildAt(i);
-                    if (isGone(c)) continue;
                     LayoutParams lp = getLayoutParams1(c);
 
-                    final Group colGroup = lp.columnGroup;
-                    final Interval cols = colGroup.span;
+                    final Spec colSpec = lp.columnSpec;
+                    final Interval cols = colSpec.span;
                     final int colSpan = cols.size();
 
-                    final Group rowGroup = lp.rowGroup;
-                    final Interval rows = rowGroup.span;
+                    final Spec rowSpec = lp.rowSpec;
+                    final Interval rows = rowSpec.span;
                     final int rowSpan = rows.size();
 
                     if (horizontal) {
@@ -623,8 +649,8 @@
                         maxSize = max(maxSize, colSpan);
                     }
 
-                    lp.setColumnGroupSpan(new Interval(col, col + colSpan));
-                    lp.setRowGroupSpan(new Interval(row, row + rowSpan));
+                    lp.setColumnSpecSpan(new Interval(col, col + colSpan));
+                    lp.setRowSpecSpan(new Interval(row, row + rowSpan));
 
                     if (horizontal) {
                         col = col + colSpan;
@@ -673,7 +699,7 @@
 
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new LayoutParams(getContext(), attrs, mDefaultGravity);
+        return new LayoutParams(getContext(), attrs);
     }
 
     @Override
@@ -737,7 +763,7 @@
             }
 
             // Draw margins
-            paint.setColor(Color.YELLOW);
+            paint.setColor(Color.MAGENTA);
             for (int i = 0; i < getChildCount(); i++) {
                 View c = getChildAt(i);
                 drawRectangle(canvas,
@@ -751,33 +777,33 @@
 
     // Add/remove
 
+    /**
+     * @hide
+     */
     @Override
-    public void addView(View child, int index, ViewGroup.LayoutParams params) {
-        super.addView(child, index, params);
+    protected void onViewAdded(View child) {
+        super.onViewAdded(child);
         invalidateStructure();
     }
 
+    /**
+     * @hide
+     */
     @Override
-    public void removeView(View view) {
-        super.removeView(view);
+    protected void onViewRemoved(View child) {
+        super.onViewRemoved(child);
         invalidateStructure();
     }
 
+    /**
+     * We need to call invalidateStructure() when a child's GONE flag changes state.
+     * This implementation is a catch-all, invalidating on any change in the visibility flags.
+     *
+     * @hide
+     */
     @Override
-    public void removeViewInLayout(View view) {
-        super.removeViewInLayout(view);
-        invalidateStructure();
-    }
-
-    @Override
-    public void removeViewsInLayout(int start, int count) {
-        super.removeViewsInLayout(start, count);
-        invalidateStructure();
-    }
-
-    @Override
-    public void removeViewAt(int index) {
-        super.removeViewAt(index);
+    protected void onChildVisibilityChanged(View child, int visibility) {
+        super.onChildVisibilityChanged(child, visibility);
         invalidateStructure();
     }
 
@@ -828,6 +854,9 @@
     }
 
     private int getMeasurementIncludingMargin(View c, boolean horizontal) {
+        if (isGone(c)) {
+            return 0;
+        }
         int result = getMeasurement(c, horizontal);
         if (mAlignmentMode == ALIGN_MARGINS) {
             return result + getTotalMargin(c, horizontal);
@@ -841,6 +870,11 @@
         invalidateValues();
     }
 
+    private Alignment getAlignment(Alignment alignment, boolean horizontal) {
+        return (alignment != UNDEFINED_ALIGNMENT) ? alignment :
+                (horizontal ? mColumnAlignment : mRowAlignment);
+    }
+
     // Layout container
 
     /**
@@ -872,11 +906,11 @@
             View c = getChildAt(i);
             if (isGone(c)) continue;
             LayoutParams lp = getLayoutParams(c);
-            Group columnGroup = lp.columnGroup;
-            Group rowGroup = lp.rowGroup;
+            Spec columnSpec = lp.columnSpec;
+            Spec rowSpec = lp.rowSpec;
 
-            Interval colSpan = columnGroup.span;
-            Interval rowSpan = rowGroup.span;
+            Interval colSpan = columnSpec.span;
+            Interval rowSpan = rowSpec.span;
 
             int x1 = mHorizontalAxis.getLocationIncludingMargin(true, colSpan.min);
             int y1 = mVerticalAxis.getLocationIncludingMargin(true, rowSpan.min);
@@ -890,8 +924,8 @@
             int pWidth = getMeasurement(c, true);
             int pHeight = getMeasurement(c, false);
 
-            Alignment hAlign = columnGroup.alignment;
-            Alignment vAlign = rowGroup.alignment;
+            Alignment hAlign = getAlignment(columnSpec.alignment, true);
+            Alignment vAlign = getAlignment(rowSpec.alignment, false);
 
             int dx, dy;
 
@@ -961,7 +995,7 @@
         public boolean countValid = false;
         public boolean countWasExplicitySet = false;
 
-        PackedMap<Group, Bounds> groupBounds;
+        PackedMap<Spec, Bounds> groupBounds;
         public boolean groupBoundsValid = false;
 
         PackedMap<Interval, MutableInt> forwardLinks;
@@ -996,11 +1030,10 @@
             int count = -1;
             for (int i = 0, N = getChildCount(); i < N; i++) {
                 View c = getChildAt(i);
-                if (isGone(c)) continue;
                 LayoutParams params = getLayoutParams(c);
-                Group g = horizontal ? params.columnGroup : params.rowGroup;
-                count = max(count, g.span.min);
-                count = max(count, g.span.max);
+                Spec spec = horizontal ? params.columnSpec : params.rowSpec;
+                count = max(count, spec.span.min);
+                count = max(count, spec.span.max);
             }
             return count == -1 ? UNDEFINED : count;
         }
@@ -1027,18 +1060,14 @@
             invalidateStructure();
         }
 
-        private PackedMap<Group, Bounds> createGroupBounds() {
-            Assoc<Group, Bounds> assoc = Assoc.of(Group.class, Bounds.class);
+        private PackedMap<Spec, Bounds> createGroupBounds() {
+            Assoc<Spec, Bounds> assoc = Assoc.of(Spec.class, Bounds.class);
             for (int i = 0, N = getChildCount(); i < N; i++) {
                 View c = getChildAt(i);
-                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);
-                }
+                LayoutParams lp = getLayoutParams(c);
+                Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
+                Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds();
+                assoc.put(spec, bounds);
             }
             return assoc.pack();
         }
@@ -1050,14 +1079,13 @@
             }
             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;
-                groupBounds.getValue(i).include(c, g, GridLayout.this, this);
+                Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
+                groupBounds.getValue(i).include(c, spec, GridLayout.this, this);
             }
         }
 
-        private PackedMap<Group, Bounds> getGroupBounds() {
+        private PackedMap<Spec, Bounds> getGroupBounds() {
             if (groupBounds == null) {
                 groupBounds = createGroupBounds();
             }
@@ -1071,7 +1099,7 @@
         // Add values computed by alignment - taking the max of all alignments in each span
         private PackedMap<Interval, MutableInt> createLinks(boolean min) {
             Assoc<Interval, MutableInt> result = Assoc.of(Interval.class, MutableInt.class);
-            Group[] keys = getGroupBounds().keys;
+            Spec[] 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());
@@ -1090,12 +1118,8 @@
             for (int i = 0; i < bounds.length; i++) {
                 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);
-                }
+                // this effectively takes the max() of the minima and the min() of the maxima
+                valueHolder.value = max(valueHolder.value, min ? size : -size);
             }
         }
 
@@ -1236,8 +1260,8 @@
                 View c = getChildAt(i);
                 if (isGone(c)) continue;
                 LayoutParams lp = getLayoutParams(c);
-                Group g = horizontal ? lp.columnGroup : lp.rowGroup;
-                Interval span = g.span;
+                Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
+                Interval span = spec.span;
                 leadingEdgeCount[span.min]++;
                 trailingEdgeCount[span.max]++;
             }
@@ -1394,7 +1418,7 @@
                 }
                 if (!changed) {
                     if (DEBUG) {
-                        Log.d(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N);
+                        Log.v(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N);
                     }
                     return;
                 }
@@ -1436,8 +1460,8 @@
                 View c = getChildAt(i);
                 if (isGone(c)) continue;
                 LayoutParams lp = getLayoutParams(c);
-                Group g = horizontal ? lp.columnGroup : lp.rowGroup;
-                Interval span = g.span;
+                Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
+                Interval span = spec.span;
                 int index = leading ? span.min : span.max;
                 margins[index] = max(margins[index], getMargin(c, horizontal, leading));
             }
@@ -1514,6 +1538,12 @@
         }
 
         private void setParentConstraints(int min, int max) {
+            if (mAlignmentMode != ALIGN_MARGINS) {
+                int margins = sum(getLeadingMargins()) + sum(getTrailingMargins());
+                min -= margins;
+                max -= margins;
+            }
+
             parentMin.value = min;
             parentMax.value = -max;
             locationsValid = false;
@@ -1529,7 +1559,7 @@
             int size = MeasureSpec.getSize(measureSpec);
             switch (mode) {
                 case MeasureSpec.UNSPECIFIED: {
-                     return getMeasure(0, MAX_SIZE);
+                    return getMeasure(0, MAX_SIZE);
                 }
                 case MeasureSpec.EXACTLY: {
                     return getMeasure(size, size);
@@ -1584,14 +1614,14 @@
      * GridLayout supports both row and column spanning and arbitrary forms of alignment within
      * each cell group. The fundamental parameters associated with each cell group are
      * gathered into their vertical and horizontal components and stored
-     * in the {@link #rowGroup} and {@link #columnGroup} layout parameters.
-     * {@link Group Groups} are immutable structures and may be shared between the layout
-     * parameters of different children.
+     * in the {@link #rowSpec} and {@link #columnSpec} layout parameters.
+     * {@link android.widget.GridLayout.Spec Specs} are immutable structures
+     * and may be shared between the layout parameters of different children.
      * <p>
-     * The row and column groups contain the leading and trailing indices along each axis
+     * The row and column specs contain the leading and trailing indices along each axis
      * and together specify the four grid indices that delimit the cells of this cell group.
      * <p>
-     * The {@link Group#alignment alignment} fields of the row and column groups together specify
+     * The  alignment properties of the row and column specs together specify
      * both aspects of alignment within the cell group. It is also possible to specify a child's
      * alignment within its cell group by using the {@link GridLayout.LayoutParams#setGravity(int)}
      * method.
@@ -1620,10 +1650,10 @@
      *          {@link GridLayout#setUseDefaultMargins(boolean) useDefaultMargins} is
      *          {@code false}; otherwise {@link #UNDEFINED}, to
      *          indicate that a default value should be computed on demand. </li>
-     *     <li>{@link #rowGroup}{@code .span} = {@code [0, 1]} </li>
-     *     <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 #rowSpec}{@code .span} = {@code [0, 1]} </li>
+     *     <li>{@link #rowSpec}{@code .alignment} = {@link #BASELINE} </li>
+     *     <li>{@link #columnSpec}{@code .span} = {@code [0, 1]} </li>
+     *     <li>{@link #columnSpec}{@code .alignment} = {@link #LEFT} </li>
      * </ul>
      *
      * @attr ref android.R.styleable#GridLayout_Layout_layout_row
@@ -1645,81 +1675,73 @@
         private static final int DEFAULT_COLUMN = UNDEFINED;
         private static final Interval DEFAULT_SPAN = new Interval(UNDEFINED, UNDEFINED + 1);
         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;
-
-        // Misc
-
-        private static final Rect CONTAINER_BOUNDS = new Rect(0, 0, 2, 2);
-        private static final Alignment[] COLUMN_ALIGNMENTS = { LEFT, CENTER, RIGHT };
-        private static final Alignment[] ROW_ALIGNMENTS = { TOP, CENTER, BOTTOM };
 
         // TypedArray indices
 
-        private static final int MARGIN = styleable.ViewGroup_MarginLayout_layout_margin;
-        private static final int LEFT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginLeft;
-        private static final int TOP_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginTop;
-        private static final int RIGHT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginRight;
+        private static final int MARGIN = R.styleable.ViewGroup_MarginLayout_layout_margin;
+        private static final int LEFT_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginLeft;
+        private static final int TOP_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginTop;
+        private static final int RIGHT_MARGIN =
+                R.styleable.ViewGroup_MarginLayout_layout_marginRight;
         private static final int BOTTOM_MARGIN =
-                styleable.ViewGroup_MarginLayout_layout_marginBottom;
+                R.styleable.ViewGroup_MarginLayout_layout_marginBottom;
 
-        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 = R.styleable.GridLayout_Layout_layout_column;
+        private static final int COLUMN_SPAN = R.styleable.GridLayout_Layout_layout_columnSpan;
         private static final int COLUMN_FLEXIBILITY =
-                styleable.GridLayout_Layout_layout_columnFlexibility;
+                R.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 = R.styleable.GridLayout_Layout_layout_row;
+        private static final int ROW_SPAN = R.styleable.GridLayout_Layout_layout_rowSpan;
         private static final int ROW_FLEXIBILITY =
-                styleable.GridLayout_Layout_layout_rowFlexibility;
+                R.styleable.GridLayout_Layout_layout_rowFlexibility;
 
-        private static final int GRAVITY = styleable.GridLayout_Layout_layout_gravity;
+        private static final int GRAVITY = R.styleable.GridLayout_Layout_layout_gravity;
 
         // Instance variables
 
         /**
-         * The group that specifies the vertical characteristics of the cell group
+         * The spec that specifies the vertical characteristics of the cell group
          * described by these layout parameters.
          */
-        public Group rowGroup;
+        public Spec rowSpec;
         /**
-         * The group that specifies the horizontal characteristics of the cell group
+         * The spec that specifies the horizontal characteristics of the cell group
          * described by these layout parameters.
          */
-        public Group columnGroup;
+        public Spec columnSpec;
 
         // Constructors
 
         private LayoutParams(
                 int width, int height,
                 int left, int top, int right, int bottom,
-                Group rowGroup, Group columnGroup) {
+                Spec rowSpec, Spec columnSpec) {
             super(width, height);
             setMargins(left, top, right, bottom);
-            this.rowGroup = rowGroup;
-            this.columnGroup = columnGroup;
+            this.rowSpec = rowSpec;
+            this.columnSpec = columnSpec;
         }
 
         /**
-         * Constructs a new LayoutParams instance for this <code>rowGroup</code>
-         * and <code>columnGroup</code>. All other fields are initialized with
+         * Constructs a new LayoutParams instance for this <code>rowSpec</code>
+         * and <code>columnSpec</code>. All other fields are initialized with
          * default values as defined in {@link LayoutParams}.
          *
-         * @param rowGroup    the rowGroup
-         * @param columnGroup the columnGroup
+         * @param rowSpec    the rowSpec
+         * @param columnSpec the columnSpec
          */
-        public LayoutParams(Group rowGroup, Group columnGroup) {
+        public LayoutParams(Spec rowSpec, Spec columnSpec) {
             this(DEFAULT_WIDTH, DEFAULT_HEIGHT,
                     DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN,
-                    rowGroup, columnGroup);
+                    rowSpec, columnSpec);
         }
 
         /**
          * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
          */
         public LayoutParams() {
-            this(new Group(DEFAULT_SPAN, DEFAULT_ROW_ALIGNMENT),
-                 new Group(DEFAULT_SPAN, DEFAULT_COLUMN_ALIGNMENT));
+            this(spec(UNDEFINED), spec(UNDEFINED));
         }
 
         // Copying constructors
@@ -1743,18 +1765,12 @@
          */
         public LayoutParams(LayoutParams that) {
             super(that);
-            this.columnGroup = new Group(that.columnGroup);
-            this.rowGroup = new Group(that.rowGroup);
+            this.rowSpec = new Spec(that.rowSpec);
+            this.columnSpec = new Spec(that.columnSpec);
         }
 
         // AttributeSet constructors
 
-        private LayoutParams(Context context, AttributeSet attrs, int defaultGravity) {
-            super(context, attrs);
-            reInitSuper(context, attrs);
-            init(context, attrs, defaultGravity);
-        }
-
         /**
          * {@inheritDoc}
          *
@@ -1762,27 +1778,13 @@
          * defined in {@link LayoutParams}.
          */
         public LayoutParams(Context context, AttributeSet attrs) {
-            this(context, attrs, Gravity.NO_GRAVITY);
+            super(context, attrs);
+            reInitSuper(context, attrs);
+            init(context, attrs);
         }
 
         // Implementation
 
-        private static boolean definesVertical(int gravity) {
-            return gravity > 0 && (gravity & Gravity.VERTICAL_GRAVITY_MASK) != 0;
-        }
-
-        private static boolean definesHorizontal(int gravity) {
-            return gravity > 0 && (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) != 0;
-        }
-
-        private static <T> T getAlignment(T[] alignments, T fill, int min, int max,
-                boolean isUndefined, T defaultValue) {
-            if (isUndefined) {
-                return defaultValue;
-            }
-            return min != max ? fill : alignments[min];
-        }
-
         // Reinitialise the margins using a different default policy than MarginLayoutParams.
         // Here we use the value UNDEFINED (as distinct from zero) to represent the undefined state
         // so that a layout manager default can be accessed post set up. We need this as, at the
@@ -1793,7 +1795,8 @@
 
         // This method could be parametrized and moved into MarginLayout.
         private void reInitSuper(Context context, AttributeSet attrs) {
-            TypedArray a = context.obtainStyledAttributes(attrs, styleable.ViewGroup_MarginLayout);
+            TypedArray a =
+                    context.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
             try {
                 int margin = a.getDimensionPixelSize(MARGIN, DEFAULT_MARGIN);
 
@@ -1806,44 +1809,20 @@
             }
         }
 
-        // 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 getColAlignment(int gravity, int width) {
-            Rect r = new Rect(0, 0, 0, 0);
-            Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r);
-
-            boolean fill = (width == MATCH_PARENT);
-            Alignment defaultAlignment = fill ? FILL : DEFAULT_COLUMN_ALIGNMENT;
-            return getAlignment(COLUMN_ALIGNMENTS, FILL, r.left, r.right,
-                    !definesHorizontal(gravity), defaultAlignment);
-        }
-
-        private static Alignment getRowAlignment(int gravity, int height) {
-            Rect r = new Rect(0, 0, 0, 0);
-            Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r);
-
-            boolean fill = (height == MATCH_PARENT);
-            Alignment defaultAlignment = fill ? FILL : DEFAULT_ROW_ALIGNMENT;
-            return getAlignment(ROW_ALIGNMENTS, FILL, r.top, r.bottom,
-                    !definesVertical(gravity), defaultAlignment);
-        }
-
-        private void init(Context context, AttributeSet attrs, int defaultGravity) {
-            TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout_Layout);
+        private void init(Context context, AttributeSet attrs) {
+            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout_Layout);
             try {
-                int gravity = a.getInt(GRAVITY, defaultGravity);
+                int gravity = a.getInt(GRAVITY, Gravity.NO_GRAVITY);
 
                 int column = a.getInt(COLUMN, DEFAULT_COLUMN);
-                int columnSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
-                Interval hSpan = new Interval(column, column + columnSpan);
-                int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Group.DEFAULT_FLEXIBILITY);
-                this.columnGroup = new Group(hSpan, getColAlignment(gravity, width), hFlexibility);
+                int colSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
+                int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY);
+                this.columnSpec = spec(column, colSpan, getAlignment(gravity, true), hFlexibility);
 
                 int row = a.getInt(ROW, DEFAULT_ROW);
                 int rowSpan = a.getInt(ROW_SPAN, DEFAULT_SPAN_SIZE);
-                Interval vSpan = new Interval(row, row + rowSpan);
-                int vFlexibility = a.getInt(ROW_FLEXIBILITY, Group.DEFAULT_FLEXIBILITY);
-                this.rowGroup = new Group(vSpan, getRowAlignment(gravity, height), vFlexibility);
+                int vFlexibility = a.getInt(ROW_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY);
+                this.rowSpec = spec(row, rowSpan, getAlignment(gravity, false), vFlexibility);
             } finally {
                 a.recycle();
             }
@@ -1858,8 +1837,8 @@
          * @attr ref android.R.styleable#GridLayout_Layout_layout_gravity
          */
         public void setGravity(int gravity) {
-            columnGroup = columnGroup.copyWriteAlignment(getColAlignment(gravity, width));
-            rowGroup = rowGroup.copyWriteAlignment(getRowAlignment(gravity, height));
+            rowSpec = rowSpec.copyWriteAlignment(getAlignment(gravity, false));
+            columnSpec = columnSpec.copyWriteAlignment(getAlignment(gravity, true));
         }
 
         @Override
@@ -1868,12 +1847,12 @@
             this.height = attributes.getLayoutDimension(heightAttr, DEFAULT_HEIGHT);
         }
 
-        private void setRowGroupSpan(Interval span) {
-            rowGroup = rowGroup.copyWriteSpan(span);
+        private void setRowSpecSpan(Interval span) {
+            rowSpec = rowSpec.copyWriteSpan(span);
         }
 
-        private void setColumnGroupSpan(Interval span) {
-            columnGroup = columnGroup.copyWriteSpan(span);
+        private void setColumnSpecSpan(Interval span) {
+            columnSpec = columnSpec.copyWriteSpan(span);
         }
     }
 
@@ -2019,14 +1998,14 @@
     }
 
     /*
-    For each Group (with a given alignment) we need to store the amount of space required
+    For each group (with a given alignment) we need to store the amount of space required
     before the alignment point and the amount of space required after it. One side of this
     calculation is always 0 for LEADING and TRAILING alignments but we don't make use of this.
     For CENTER and BASELINE alignments both sides are needed and in the BASELINE case no
     simple optimisations are possible.
 
     The general algorithm therefore is to create a Map (actually a PackedMap) from
-    Group to Bounds and to loop through all Views in the group taking the maximum
+    group to Bounds and to loop through all Views in the group taking the maximum
     of the values for each View.
     */
     private static class Bounds {
@@ -2034,7 +2013,7 @@
 
         public int before;
         public int after;
-        public int flexibility;
+        public int flexibility; // we're flexible iff all included specs are flexible
 
         private Bounds() {
             reset();
@@ -2043,7 +2022,7 @@
         protected void reset() {
             before = Integer.MIN_VALUE;
             after = Integer.MIN_VALUE;
-            flexibility = UNDEFINED_FLEXIBILITY;
+            flexibility = CAN_STRETCH; // from the above, we're flexible when empty
         }
 
         protected void include(int before, int after) {
@@ -2053,10 +2032,7 @@
 
         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)) {
+                if (canStretch(flexibility)) {
                     return MAX_SIZE;
                 }
             }
@@ -2067,11 +2043,12 @@
             return before - alignment.getAlignmentValue(c, size);
         }
 
-        protected void include(View c, Group group, GridLayout gridLayout, Axis axis) {
-            this.flexibility &= group.flexibility;
+        protected final void include(View c, Spec spec, GridLayout gridLayout, Axis axis) {
+            this.flexibility &= spec.getFlexibility();
             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);
+            Alignment alignment = gridLayout.getAlignment(spec.alignment, axis.horizontal);
+            int before = alignment.getAlignmentValue(c, size);
             include(before, size - before);
         }
 
@@ -2096,8 +2073,6 @@
      * {@code x} such that {@code min <= x < max}.
      */
     static class Interval {
-        private static final Interval GONE = new Interval(UNDEFINED, UNDEFINED);
-
         /**
          * The minimum value.
          */
@@ -2175,119 +2150,86 @@
         }
     }
 
-    /**
-     * A group specifies either the horizontal or vertical characteristics of a group of
-     * cells.
-     * <p>
-     * Groups are immutable and so may be shared between views with the same
-     * {@code span} and {@code alignment}.
-     */
-    public static class Group {
-        private static final int DEFAULT_FLEXIBILITY = UNDEFINED_FLEXIBILITY;
+   /**
+    * A Spec defines the horizontal or vertical characteristics of a group of
+    * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and
+    * <em>flexibility</em> along the appropriate axis.
+    * <p>
+    * The <em>grid indices</em> are the leading and trailing edges of this cell group.
+    * See {@link GridLayout} for a description of the conventions used by GridLayout
+    * for grid indices.
+    * <p>
+    * The <em>alignment</em> property specifies how cells should be aligned in this group.
+    * For row groups, this specifies the vertical alignment.
+    * For column groups, this specifies the horizontal alignment.
+    */
+    public static class Spec {
+        private static final int UNDEFINED_FLEXIBILITY = UNDEFINED;
 
-        private static final Group GONE = new Group(Interval.GONE, Alignment.GONE);
-
-        /**
-         * The grid indices of the leading and trailing edges of this cell group for the
-         * appropriate axis.
-         * <p>
-         * See {@link GridLayout} for a description of the conventions used by GridLayout
-         * for grid indices.
-         */
         final Interval span;
-        /**
-         * Specifies how cells should be aligned in this group.
-         * For row groups, this specifies the vertical alignment.
-         * For column groups, this specifies the horizontal alignment.
-         */
-        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;
+        final Alignment alignment;
 
-        /**
-         * Construct a new Group, {@code group}, where:
-         * <ul>
-         *     <li> {@code group.span = span} </li>
-         *     <li> {@code group.alignment = alignment} </li>
-         * </ul>
-         *
-         * @param span      the span
-         * @param alignment the alignment
-         */
-        private Group(Interval span, Alignment alignment) {
-            this.span = span;
-            this.alignment = alignment;
-        }
+     /**
+       * The <em>flexibility</em> property 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.
+       * <p>
+       * A cell group is flexible only if <em>all</em> of its components are flexible.
+       * <p>
+       * By default, flexibility is {@link #INFLEXIBLE} only when alignment/gravity is undefined.
+       */
+        final int flexibility;
 
-        private Group(Interval span, Alignment alignment, int flexibility) {
+        private Spec(Interval span, Alignment alignment, int flexibility) {
             this.span = span;
             this.alignment = alignment;
             this.flexibility = flexibility;
         }
 
+        private Spec(Interval span, Alignment alignment) {
+            this(span, alignment, UNDEFINED_FLEXIBILITY);
+        }
+
         /* Copying constructor */
-        private Group(Group that) {
-            this.span = that.span;
-            this.alignment = that.alignment;
-            this.flexibility = that.flexibility;
+        private Spec(Spec that) {
+            this(that.span, that.alignment, that.flexibility);
+        }
+
+        Spec(int start, int size, Alignment alignment, int flexibility) {
+            this(new Interval(start, start + size), alignment, flexibility);
+        }
+
+        private Spec copyWriteSpan(Interval span) {
+            return new Spec(span, alignment, flexibility);
+        }
+
+        private Spec copyWriteAlignment(Alignment alignment) {
+            return new Spec(span, alignment, flexibility);
+        }
+
+        private static int defaultFlexibility(Alignment alignment) {
+            return (alignment == UNDEFINED_ALIGNMENT) ? INFLEXIBLE : CAN_STRETCH;
+        }
+
+        int getFlexibility() {
+            return (flexibility != UNDEFINED_FLEXIBILITY) ?
+                    flexibility :
+                    defaultFlexibility(alignment);
         }
 
         /**
-         * Construct a new Group, {@code group}, where:
-         * <ul>
-         *     <li> {@code group.span = [start, start + size]} </li>
-         *     <li> {@code group.alignment = alignment} </li>
-         * </ul>
-         *
-         * @param start     the start
-         * @param size      the size
-         * @param alignment the alignment
-         */
-        public Group(int start, int size, Alignment alignment) {
-            this(new Interval(start, start + size), alignment);
-        }
-
-        /**
-         * Construct a new Group, {@code group}, where:
-         * <ul>
-         *     <li> {@code group.span = [start, start + 1]} </li>
-         *     <li> {@code group.alignment = alignment} </li>
-         * </ul>
-         *
-         * @param start     the start index
-         * @param alignment the alignment
-         */
-        public Group(int start, Alignment alignment) {
-            this(start, 1, alignment);
-        }
-
-        private Group copyWriteSpan(Interval span) {
-            return new Group(span, alignment, flexibility);
-        }
-
-        private Group copyWriteAlignment(Alignment alignment) {
-            return new Group(span, alignment, flexibility);
-        }
-
-        /**
-         * Returns {@code true} if the {@link #getClass class}, {@link #alignment} and {@code span}
-         * properties of this Group and the supplied parameter are pairwise equal,
+         * Returns {@code true} if the {@code class}, {@code alignment} and {@code span}
+         * properties of this Spec and the supplied parameter are pairwise equal,
          * {@code false} otherwise.
          *
-         * @param that the object to compare this group with
+         * @param that the object to compare this spec with
          *
          * @return {@code true} if the specified object is equal to this
-         *         {@code Group}; {@code false} otherwise
+         *         {@code Spec}; {@code false} otherwise
          */
         @Override
         public boolean equals(Object that) {
@@ -2298,12 +2240,12 @@
                 return false;
             }
 
-            Group group = (Group) that;
+            Spec spec = (Spec) that;
 
-            if (!alignment.equals(group.alignment)) {
+            if (!alignment.equals(spec.alignment)) {
                 return false;
             }
-            if (!span.equals(group.span)) {
+            if (!span.equals(spec.span)) {
                 return false;
             }
 
@@ -2319,12 +2261,88 @@
     }
 
     /**
+     * @deprecated Please use {@link #spec(int, int, Alignment)} instead,
+     * all spec's that define alignments (gravity) are  assumed to be able to stretch.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static Spec spec(int start, int size, Alignment alignment, int flexibility) {
+        return new Spec(start, size, alignment, flexibility);
+    }
+
+    /**
+     * @deprecated Please use {@link #spec(int, Alignment)} instead,
+     * all spec's that define alignments (gravity) are assumed to be able to stretch.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static Spec spec(int start, Alignment alignment, int flexibility) {
+        return spec(start, 1, alignment, flexibility);
+    }
+
+    /**
+     * Return a Spec, {@code spec}, where:
+     * <ul>
+     *     <li> {@code spec.span = [start, start + size]} </li>
+     *     <li> {@code spec.alignment = alignment} </li>
+     * </ul>
+     *
+     * @param start     the start
+     * @param size      the size
+     * @param alignment the alignment
+     */
+    public static Spec spec(int start, int size, Alignment alignment) {
+        return spec(start, size, alignment, Spec.UNDEFINED_FLEXIBILITY);
+    }
+
+    /**
+     * Return a Spec, {@code spec}, where:
+     * <ul>
+     *     <li> {@code spec.span = [start, start + 1]} </li>
+     *     <li> {@code spec.alignment = alignment} </li>
+     * </ul>
+     *
+     * @param start     the start index
+     * @param alignment the alignment
+     */
+    public static Spec spec(int start, Alignment alignment) {
+        return spec(start, 1, alignment);
+    }
+
+    /**
+     * Return a Spec, {@code spec}, where:
+     * <ul>
+     *     <li> {@code spec.span = [start, start + size]} </li>
+     * </ul>
+     *
+     * @param start     the start
+     * @param size      the size
+     */
+    public static Spec spec(int start, int size) {
+        return spec(start, size, UNDEFINED_ALIGNMENT);
+    }
+
+    /**
+     * Return a Spec, {@code spec}, where:
+     * <ul>
+     *     <li> {@code spec.span = [start, start + 1]} </li>
+     * </ul>
+     *
+     * @param start     the start index
+     */
+    public static Spec spec(int start) {
+        return spec(start, 1);
+    }
+
+    /**
      * Alignments specify where a view should be placed within a cell group and
      * what size it should be.
      * <p>
-     * The {@link LayoutParams} class contains a {@link LayoutParams#rowGroup rowGroup}
-     * and a {@link LayoutParams#columnGroup columnGroup} each of which contains an
-     * {@link Group#alignment alignment}. Overall placement of the view in the cell
+     * The {@link LayoutParams} class contains a {@link LayoutParams#rowSpec rowSpec}
+     * and a {@link LayoutParams#columnSpec columnSpec} each of which contains an
+     * {@code alignment}. Overall placement of the view in the cell
      * group is specified by the two alignments which act along each axis independently.
      * <p>
      *  The GridLayout class defines the most common alignments used in general layout:
@@ -2340,13 +2358,6 @@
      * <p>
      */
     public static abstract class Alignment {
-        private static final Alignment GONE = new Alignment() {
-            public int getAlignmentValue(View view, int viewSize) {
-                assert false;
-                return 0;
-            }
-        };
-
         Alignment() {
         }
 
@@ -2386,11 +2397,16 @@
         }
     }
 
+    private static final Alignment UNDEFINED_ALIGNMENT = new Alignment() {
+        public int getAlignmentValue(View view, int viewSize) {
+            return UNDEFINED;
+        }
+    };
+
     private static final Alignment LEADING = new Alignment() {
         public int getAlignmentValue(View view, int viewSize) {
             return 0;
         }
-
     };
 
     private static final Alignment TRAILING = new Alignment() {
@@ -2425,8 +2441,8 @@
 
     /**
      * Indicates that a view should be <em>centered</em> with the other views in its cell group.
-     * This constant may be used in both {@link LayoutParams#rowGroup rowGroups} and {@link
-     * LayoutParams#columnGroup columnGroups}.
+     * This constant may be used in both {@link LayoutParams#rowSpec rowSpecs} and {@link
+     * LayoutParams#columnSpec columnSpecs}.
      */
     public static final Alignment CENTER = new Alignment() {
         public int getAlignmentValue(View view, int viewSize) {
@@ -2437,7 +2453,7 @@
     /**
      * Indicates that a view should be aligned with the <em>baselines</em>
      * of the other views in its cell group.
-     * This constant may only be used as an alignment in {@link LayoutParams#rowGroup rowGroups}.
+     * This constant may only be used as an alignment in {@link LayoutParams#rowSpec rowSpecs}.
      *
      * @see View#getBaseline()
      */
@@ -2488,8 +2504,8 @@
 
     /**
      * Indicates that a view should expanded to fit the boundaries of its cell group.
-     * This constant may be used in both {@link LayoutParams#rowGroup rowGroups} and
-     * {@link LayoutParams#columnGroup columnGroups}.
+     * This constant may be used in both {@link LayoutParams#rowSpec rowSpecs} and
+     * {@link LayoutParams#columnSpec columnSpecs}.
      */
     public static final Alignment FILL = new Alignment() {
         public int getAlignmentValue(View view, int viewSize) {
@@ -2506,50 +2522,17 @@
         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;
+    private static final int INFLEXIBLE = 0;
 
     /**
      * Indicates that a view's size should be greater than or equal to the size specified by
      * its layout parameters.
      *
-     * @see Group#flexibility
+     * @deprecated Please use {@link #spec(int, int, Alignment)} instead,
+     * all spec's that define alignment (gravity) are assumed to able to stretch.
+     *
+     * @hide
      */
+    @Deprecated
     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 7c9be1e..b428301 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -498,13 +498,6 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
-            // Don't handle edge touches immediately -- they may actually belong to one of our
-            // descendants.
-            return false;
-        }
-
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 161b404..299e1ff 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -30,14 +30,15 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.RemotableViewMethod;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
-
 /**
  * Displays an arbitrary image, such as an icon.  The ImageView class
  * can load images from various sources (such as resources or content
@@ -208,7 +209,15 @@
         }
         return false;
     }
-    
+
+    @Override
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        CharSequence contentDescription = getContentDescription();
+        if (!TextUtils.isEmpty(contentDescription)) {
+            event.getText().add(contentDescription);
+        }
+    }
+
     /**
      * Set this to true if you want the ImageView to adjust its bounds
      * to preserve the aspect ratio of its drawable.
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 5642877..f057d07 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -62,6 +62,7 @@
     private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
     private int mDropDownHorizontalOffset;
     private int mDropDownVerticalOffset;
+    private boolean mDropDownVerticalOffsetSet;
 
     private boolean mDropDownAlwaysVisible = false;
     private boolean mForceIgnoreOutsideTouch = false;
@@ -404,6 +405,9 @@
      * @return The vertical offset of the popup from its anchor in pixels.
      */
     public int getVerticalOffset() {
+        if (!mDropDownVerticalOffsetSet) {
+            return 0;
+        }
         return mDropDownVerticalOffset;
     }
 
@@ -414,6 +418,7 @@
      */
     public void setVerticalOffset(int offset) {
         mDropDownVerticalOffset = offset;
+        mDropDownVerticalOffsetSet = true;
     }
 
     /**
@@ -1061,21 +1066,27 @@
             }
         }
 
-        // Max height available on the screen for a popup.
-        boolean ignoreBottomDecorations =
-                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
-        final int maxHeight = mPopup.getMaxAvailableHeight(
-                getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
-
-        // getMaxAvailableHeight() subtracts the padding, so we put it back,
+        // getMaxAvailableHeight() subtracts the padding, so we put it back
         // to get the available height for the whole window
         int padding = 0;
         Drawable background = mPopup.getBackground();
         if (background != null) {
             background.getPadding(mTempRect);
             padding = mTempRect.top + mTempRect.bottom;
+
+            // If we don't have an explicit vertical offset, determine one from the window
+            // background so that content will line up.
+            if (!mDropDownVerticalOffsetSet) {
+                mDropDownVerticalOffset = -mTempRect.top;
+            }
         }
 
+        // Max height available on the screen for a popup.
+        boolean ignoreBottomDecorations =
+                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
+        final int maxHeight = mPopup.getMaxAvailableHeight(
+                getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
+
         if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
             return maxHeight + padding;
         }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e7a9e41..1f29b16 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3588,17 +3588,6 @@
         return null;
     }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        //noinspection SimplifiableIfStatement
-        if (mItemsCanFocus && ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
-            // Don't handle edge touches immediately -- they may actually belong to one of our
-            // descendants.
-            return false;
-        }
-        return super.onTouchEvent(ev);
-    }
-
     /**
      * Returns the set of checked items ids. The result is only valid if the
      * choice mode has not been set to {@link #CHOICE_MODE_NONE}.
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 563fc26..36927ca 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -91,6 +91,7 @@
     private boolean mLayoutInScreen;
     private boolean mClipToScreen;
     private boolean mAllowScrollingAnchorParent = true;
+    private boolean mLayoutInsetDecor = false;
 
     private OnTouchListener mTouchInterceptor;
     
@@ -658,6 +659,22 @@
     }
 
     /**
+     * Allows the popup window to force the flag
+     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
+     * This will cause the popup to inset its content to account for system windows overlaying
+     * the screen, such as the status bar.
+     *
+     * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
+     *
+     * @param enabled true if the popup's views should inset content to account for system windows,
+     *                the way that decor views behave for full-screen windows.
+     * @hide
+     */
+    public void setLayoutInsetDecor(boolean enabled) {
+        mLayoutInsetDecor = enabled;
+    }
+
+    /**
      * Set the layout type for this window. Should be one of the TYPE constants defined in
      * {@link WindowManager.LayoutParams}.
      *
@@ -942,6 +959,7 @@
         if (mContext != null) {
             p.packageName = mContext.getPackageName();
         }
+        mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
         mWindowManager.addView(mPopupView, p);
     }
 
@@ -1012,6 +1030,9 @@
         if (mLayoutInScreen) {
             curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
         }
+        if (mLayoutInsetDecor) {
+            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+        }
         return curFlags;
     }
     
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 4c47d37..867ebb4 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -53,6 +53,10 @@
     // This ensures that we don't stay continually bound to the service and that it can be destroyed
     // if we need the memory elsewhere in the system.
     private static final int sUnbindServiceDelay = 5000;
+
+    // Default height for the default loading view, in case we cannot get inflate the first view
+    private static final int sDefaultLoadingViewHeight = 50;
+
     // Type defs for controlling different messages across the main and worker message queues
     private static final int sDefaultMessageType = 0;
     private static final int sUnbindServiceMessageType = 1;
@@ -386,21 +390,39 @@
 
             // Create a new loading view
             synchronized (mCache) {
+                boolean customLoadingViewAvailable = false;
+
                 if (mUserLoadingView != null) {
-                    // A user-specified loading view
-                    View loadingView = mUserLoadingView.apply(parent.getContext(), parent);
-                    loadingView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(0));
-                    layout.addView(loadingView);
-                } else {
+                    // Try to inflate user-specified loading view
+                    try {
+                        View loadingView = mUserLoadingView.apply(parent.getContext(), parent);
+                        loadingView.setTagInternal(com.android.internal.R.id.rowTypeId,
+                                new Integer(0));
+                        layout.addView(loadingView);
+                        customLoadingViewAvailable = true;
+                    } catch (Exception e) {
+                        Log.w(TAG, "Error inflating custom loading view, using default loading" +
+                                "view instead", e);
+                    }
+                }
+                if (!customLoadingViewAvailable) {
                     // A default loading view
                     // Use the size of the first row as a guide for the size of the loading view
                     if (mFirstViewHeight < 0) {
-                        View firstView = mFirstView.apply(parent.getContext(), parent);
-                        firstView.measure(
-                                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
-                                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-                        mFirstViewHeight = firstView.getMeasuredHeight();
-                        mFirstView = null;
+                        try {
+                            View firstView = mFirstView.apply(parent.getContext(), parent);
+                            firstView.measure(
+                                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+                            mFirstViewHeight = firstView.getMeasuredHeight();
+                            mFirstView = null;
+                        } catch (Exception e) {
+                            float density = mContext.getResources().getDisplayMetrics().density;
+                            mFirstViewHeight = (int)
+                                    Math.round(sDefaultLoadingViewHeight * density);
+                            mFirstView = null;
+                            Log.w(TAG, "Error inflating first RemoteViews" + e);
+                        }
                     }
 
                     // Compose the loading view text
@@ -937,24 +959,40 @@
                 indexMetaData.isRequested = true;
                 int typeId = indexMetaData.typeId;
 
-                // Reuse the convert view where possible
-                if (layout != null) {
-                    if (convertViewTypeId == typeId) {
-                        rv.reapply(context, convertViewChild);
-                        return layout;
+                try {
+                    // Reuse the convert view where possible
+                    if (layout != null) {
+                        if (convertViewTypeId == typeId) {
+                            rv.reapply(context, convertViewChild);
+                            return layout;
+                        }
+                        layout.removeAllViews();
+                    } else {
+                        layout = new RemoteViewsFrameLayout(context);
                     }
-                    layout.removeAllViews();
-                } else {
-                    layout = new RemoteViewsFrameLayout(context);
+
+                    // Otherwise, create a new view to be returned
+                    View newView = rv.apply(context, parent);
+                    newView.setTagInternal(com.android.internal.R.id.rowTypeId,
+                            new Integer(typeId));
+                    layout.addView(newView);
+                    return layout;
+
+                } catch (Exception e){
+                    // We have to make sure that we successfully inflated the RemoteViews, if not
+                    // we return the loading view instead.
+                    Log.w(TAG, "Error inflating RemoteViews at position: " + position + ", using" +
+                            "loading view instead" + e);
+
+                    RemoteViewsFrameLayout loadingView = null;
+                    final RemoteViewsMetaData metaData = mCache.getMetaData();
+                    synchronized (metaData) {
+                        loadingView = metaData.createLoadingView(position, convertView, parent);
+                    }
+                    return loadingView;
+                } finally {
+                    if (hasNewItems) loadNextIndexInBackground();
                 }
-
-                // Otherwise, create a new view to be returned
-                View newView = rv.apply(context, parent);
-                newView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(typeId));
-                layout.addView(newView);
-                if (hasNewItems) loadNextIndexInBackground();
-
-                return layout;
             } else {
                 // If the cache does not have the RemoteViews at this position, then create a
                 // loading view and queue the actual position to be loaded in the background
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 12775a4..e59f731 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -65,7 +65,6 @@
 
     static final float MAX_SCROLL_FACTOR = 0.5f;
 
-
     private long mLastScroll;
 
     private final Rect mTempRect = new Rect();
@@ -506,13 +505,6 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
-            // Don't handle edge touches immediately -- they may actually belong to one of our
-            // descendants.
-            return false;
-        }
-
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
@@ -1438,17 +1430,6 @@
 
             final boolean movingDown = velocityY > 0;
 
-            View currentFocused = findFocus();
-            View newFocused =
-                    findFocusableViewInMyBounds(movingDown, mScroller.getFinalY(), currentFocused);
-            if (newFocused == null) {
-                newFocused = this;
-            }
-
-            if (newFocused != currentFocused) {
-                    newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP);
-            }
-
             if (mFlingStrictSpan == null) {
                 mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling");
             }
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index f3bda43..91b19ed 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -18,8 +18,6 @@
 
 import static android.widget.SuggestionsAdapter.getColumnString;
 
-import com.android.internal.R;
-
 import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -39,10 +37,15 @@
 import android.os.Bundle;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.style.ImageSpan;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
+import android.view.CollapsibleActionView;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -51,21 +54,35 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.R;
+
 import java.util.WeakHashMap;
 
 /**
- * A widget that provides a user interface for the user to enter a search query and submit a
- * request to a search provider. Shows a list of query suggestions or results, if
- * available, and allows the user to pick a suggestion or result to launch into.
+ * A widget that provides a user interface for the user to enter a search query and submit a request
+ * to a search provider. Shows a list of query suggestions or results, if available, and allows the
+ * user to pick a suggestion or result to launch into.
  *
- * <p>For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
- * documentation.<p>
+ * <p>
+ * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it
+ * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean)
+ * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done.
+ * </p>
+ * <p>
+ * If you want the search field to always be visible, then call setIconifiedByDefault(false).
+ * </p>
  *
+ * <p>
+ * For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
+ * documentation.
+ * <p>
+ *
+ * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
  * @attr ref android.R.styleable#SearchView_iconifiedByDefault
  * @attr ref android.R.styleable#SearchView_maxWidth
  * @attr ref android.R.styleable#SearchView_queryHint
  */
-public class SearchView extends LinearLayout {
+public class SearchView extends LinearLayout implements CollapsibleActionView {
 
     private static final boolean DBG = false;
     private static final String LOG_TAG = "SearchView";
@@ -87,6 +104,8 @@
     private View mSearchEditFrame;
     private View mVoiceButton;
     private SearchAutoComplete mQueryTextView;
+    private View mDropDownAnchor;
+    private ImageView mSearchHintIcon;
     private boolean mSubmitButtonEnabled;
     private CharSequence mQueryHint;
     private boolean mQueryRefinement;
@@ -94,6 +113,7 @@
     private int mMaxWidth;
     private boolean mVoiceButtonEnabled;
     private CharSequence mUserQuery;
+    private boolean mExpandedInActionView;
 
     private SearchableInfo mSearchable;
     private Bundle mAppSearchData;
@@ -195,11 +215,13 @@
         mSubmitButton = findViewById(R.id.search_go_btn);
         mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
         mVoiceButton = findViewById(R.id.search_voice_btn);
+        mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon);
 
         mSearchButton.setOnClickListener(mOnClickListener);
         mCloseButton.setOnClickListener(mOnClickListener);
         mSubmitButton.setOnClickListener(mOnClickListener);
         mVoiceButton.setOnClickListener(mOnClickListener);
+        mQueryTextView.setOnClickListener(mOnClickListener);
 
         mQueryTextView.addTextChangedListener(mTextWatcher);
         mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
@@ -244,7 +266,20 @@
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
+        mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor());
+        if (mDropDownAnchor != null) {
+            mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+                @Override
+                public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                    adjustDropDownSizeAndPosition();
+                }
+
+            });
+        }
+
         updateViewsVisibility(mIconifiedByDefault);
+        updateQueryHint();
     }
 
     /**
@@ -263,7 +298,7 @@
         }
         // Cache the voice search capability
         mVoiceButtonEnabled = hasVoiceSearch();
-        updateViewsVisibility(mIconifiedByDefault);
+        updateViewsVisibility(isIconified());
     }
 
     /**
@@ -285,7 +320,9 @@
         // If it is not iconified, then give the focus to the text field
         if (!isIconified()) {
             boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
-            if (result) updateViewsVisibility(false);
+            if (result) {
+                updateViewsVisibility(false);
+            }
             return result;
         } else {
             return super.requestFocus(direction, previouslyFocusedRect);
@@ -296,11 +333,10 @@
     @Override
     public void clearFocus() {
         mClearingFocus = true;
+        setImeVisibility(false);
         super.clearFocus();
         mQueryTextView.clearFocus();
-        setImeVisibility(false);
         mClearingFocus = false;
-        updateViewsVisibility(mIconifiedByDefault);
     }
 
     /**
@@ -555,6 +591,7 @@
         mSearchButton.setVisibility(visCollapsed);
         updateSubmitButton(hasText);
         mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
+        mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
         updateCloseButton();
         updateVoiceButton(!hasText);
         updateSubmitArea();
@@ -603,7 +640,7 @@
         final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
         // Should we show the close button? It is not shown if there's no focus,
         // field is not iconified by default and there is no text in it.
-        final boolean showClose = hasText || mIconifiedByDefault;
+        final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
         mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
         mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
     }
@@ -647,6 +684,8 @@
                 onSubmitQuery();
             } else if (v == mVoiceButton) {
                 onVoiceClicked();
+            } else if (v == mQueryTextView) {
+                forceSuggestionQuery();
             }
         }
     };
@@ -822,9 +861,29 @@
         return result;
     }
 
+    private int getSearchIconId() {
+        TypedValue outValue = new TypedValue();
+        getContext().getTheme().resolveAttribute(com.android.internal.R.attr.searchViewSearchIcon,
+                outValue, true);
+        return outValue.resourceId;
+    }
+
+    private CharSequence getDecoratedHint(CharSequence hintText) {
+        // If the field is always expanded, then don't add the search icon to the hint
+        if (!mIconifiedByDefault) return hintText;
+
+        SpannableStringBuilder ssb = new SpannableStringBuilder("   "); // for the icon
+        ssb.append(hintText);
+        Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId());
+        int textSize = (int) (mQueryTextView.getTextSize() * 1.25);
+        searchIcon.setBounds(0, 0, textSize, textSize);
+        ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return ssb;
+    }
+
     private void updateQueryHint() {
         if (mQueryHint != null) {
-            mQueryTextView.setHint(mQueryHint);
+            mQueryTextView.setHint(getDecoratedHint(mQueryHint));
         } else if (mSearchable != null) {
             CharSequence hint = null;
             int hintId = mSearchable.getHintId();
@@ -832,8 +891,10 @@
                 hint = getContext().getString(hintId);
             }
             if (hint != null) {
-                mQueryTextView.setHint(hint);
+                mQueryTextView.setHint(getDecoratedHint(hint));
             }
+        } else {
+            mQueryTextView.setHint(getDecoratedHint(""));
         }
     }
 
@@ -922,9 +983,13 @@
         CharSequence text = mQueryTextView.getText();
         if (TextUtils.isEmpty(text)) {
             if (mIconifiedByDefault) {
-                // query field already empty, hide the keyboard and remove focus
-                clearFocus();
-                setImeVisibility(false);
+                // If the app doesn't override the close behavior
+                if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
+                    // hide the keyboard and remove focus
+                    clearFocus();
+                    // collapse the search field
+                    updateViewsVisibility(true);
+                }
             }
         } else {
             mQueryTextView.setText("");
@@ -932,10 +997,6 @@
             setImeVisibility(true);
         }
 
-        if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) {
-            updateViewsVisibility(mIconifiedByDefault);
-            setImeVisibility(false);
-        }
     }
 
     private void onSearchClicked() {
@@ -973,6 +1034,51 @@
     void onTextFocusChanged() {
         updateViewsVisibility(isIconified());
         updateFocusedState(mQueryTextView.hasFocus());
+        if (mQueryTextView.hasFocus()) {
+            forceSuggestionQuery();
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onActionViewCollapsed() {
+        clearFocus();
+        updateViewsVisibility(true);
+        mQueryTextView.setText("");
+        mExpandedInActionView = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onActionViewExpanded() {
+        mExpandedInActionView = true;
+        setIconified(false);
+    }
+
+    private void adjustDropDownSizeAndPosition() {
+        if (mDropDownAnchor.getWidth() > 1) {
+            Resources res = getContext().getResources();
+            int anchorPadding = mSearchPlate.getPaddingLeft();
+            Rect dropDownPadding = new Rect();
+            int iconOffset = mIconifiedByDefault
+                    ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
+                    + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
+                    : 0;
+            mQueryTextView.getDropDownBackground().getPadding(dropDownPadding);
+            mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset)
+                    + anchorPadding);
+            mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left
+                    + dropDownPadding.right + iconOffset - (anchorPadding));
+        }
     }
 
     private boolean onItemClicked(int position, int actionKey, String actionMsg) {
@@ -1279,6 +1385,11 @@
         }
     }
 
+    private void forceSuggestionQuery() {
+        mQueryTextView.doBeforeTextChanged();
+        mQueryTextView.doAfterTextChanged();
+    }
+
     static boolean isLandscapeMode(Context context) {
         return context.getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_LANDSCAPE;
@@ -1393,5 +1504,32 @@
         public boolean enoughToFilter() {
             return mThreshold <= 0 || super.enoughToFilter();
         }
+
+        @Override
+        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                // special case for the back key, we do not even try to send it
+                // to the drop down list but instead, consume it immediately
+                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
+                    return true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.handleUpEvent(event);
+                    }
+                    if (event.isTracking() && !event.isCanceled()) {
+                        mSearchView.clearFocus();
+                        mSearchView.setImeVisibility(false);
+                        return true;
+                    }
+                }
+            }
+            return super.onKeyPreIme(keyCode, event);
+        }
+
     }
 }
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index f48261d..665109a 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -16,21 +16,25 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.ActionProvider;
+import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
 import android.view.SubMenu;
 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.
+ * that enable data sharing and also to show a sub menu with sharing activities
+ * if the hosting item is placed on the overflow menu.
  * <p>
  * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
  * </p>
@@ -48,15 +52,13 @@
  *      // {@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);
+ *      mShareActionProvider.setShareIntent(shareIntent);
  *  }
  * </pre>
  * </code>
@@ -71,11 +73,34 @@
 public class ShareActionProvider extends ActionProvider {
 
     /**
+     * The default for the maximal number of activities shown in the sub-menu.
+     */
+    private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
+
+    /**
+     * The the maximum number activities shown in the sub-menu.
+     */
+    private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
+
+    /**
+     * Listener for handling menu item clicks.
+     */
+    private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
+        new ShareMenuItemOnMenuItemClickListener();
+
+    /**
      * The default name for storing share history.
      */
     public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
 
+    /**
+     * Context for accessing resources.
+     */
     private final Context mContext;
+
+    /**
+     * The name of the file with share history data.
+     */
     private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
 
     /**
@@ -93,24 +118,62 @@
      */
     @Override
     public View onCreateActionView() {
+        // Create the view and set its data model.
         ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
         ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
         activityChooserView.setActivityChooserModel(dataModel);
+
+        // Lookup and set the expand action icon.
         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 boolean hasSubMenu() {
         return true;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void onPrepareSubMenu(SubMenu subMenu) {
-        // TODO Implement me
+        // Clear since the order of items may change.
+        subMenu.clear();
+
+        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+        PackageManager packageManager = mContext.getPackageManager();
+
+        final int expandedActivityCount = dataModel.getActivityCount();
+        final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
+
+        // Populate the sub-menu with a sub set of the activities.
+        for (int i = 0; i < collapsedActivityCount; i++) {
+            ResolveInfo activity = dataModel.getActivity(i);
+            subMenu.add(0, i, i, activity.loadLabel(packageManager))
+                .setIcon(activity.loadIcon(packageManager))
+                .setOnMenuItemClickListener(mOnMenuItemClickListener);
+        }
+
+        if (collapsedActivityCount < expandedActivityCount) {
+            // Add a sub-menu for showing all activities as a list item.
+            SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
+                    collapsedActivityCount,
+                    mContext.getString(R.string.activity_chooser_view_see_all));
+            for (int i = 0; i < expandedActivityCount; i++) {
+                ResolveInfo activity = dataModel.getActivity(i);
+                expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
+                    .setIcon(activity.loadIcon(packageManager))
+                    .setOnMenuItemClickListener(mOnMenuItemClickListener);
+            }
+        }
     }
 
     /**
@@ -145,18 +208,29 @@
      * </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");
+    public void setShareIntent(Intent shareIntent) {
+        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
+            mShareHistoryFileName);
+        dataModel.setIntent(shareIntent);
+    }
+
+    /**
+     * Reusable listener for handling share item clicks.
+     */
+    private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
+        @Override
+        public boolean onMenuItemClick(MenuItem item) {
+            ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
+                    mShareHistoryFileName);
+            final int itemId = item.getItemId();
+            Intent launchIntent = dataModel.chooseActivity(itemId);
+            mContext.startActivity(launchIntent);
+            return true;
         }
     }
 }
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 485c678..2fba18b 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -165,10 +165,17 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT);
             popup.setBackgroundDrawable(a.getDrawable(
                     com.android.internal.R.styleable.Spinner_popupBackground));
-            popup.setVerticalOffset(a.getDimensionPixelOffset(
-                    com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0));
-            popup.setHorizontalOffset(a.getDimensionPixelOffset(
-                    com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0));
+            final int verticalOffset = a.getDimensionPixelOffset(
+                    com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0);
+            if (verticalOffset != 0) {
+                popup.setVerticalOffset(verticalOffset);
+            }
+
+            final int horizontalOffset = a.getDimensionPixelOffset(
+                    com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0);
+            if (horizontalOffset != 0) {
+                popup.setHorizontalOffset(horizontalOffset);
+            }
 
             mPopup = popup;
             break;
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index 2cfc016..9e32c9a 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.app.SearchDialog;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -47,6 +45,8 @@
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 
+import com.android.internal.R;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -88,8 +88,8 @@
     private int mIconName2Col = INVALID_INDEX;
     private int mFlagsCol = INVALID_INDEX;
 
-    private final Runnable mStartSpinnerRunnable;
-    private final Runnable mStopSpinnerRunnable;
+    // private final Runnable mStartSpinnerRunnable;
+    // private final Runnable mStopSpinnerRunnable;
 
     /**
      * The amount of time we delay in the filter when the user presses the delete key.
@@ -113,17 +113,18 @@
 
         mOutsideDrawablesCache = outsideDrawablesCache;
         
-        mStartSpinnerRunnable = new Runnable() {
-                public void run() {
-                // mSearchView.setWorking(true); // TODO:
-                }
-            };
 
-        mStopSpinnerRunnable = new Runnable() {
-            public void run() {
-                // mSearchView.setWorking(false); // TODO:
-            }
-        };
+        // mStartSpinnerRunnable = new Runnable() {
+        // public void run() {
+        // // mSearchView.setWorking(true); // TODO:
+        // }
+        // };
+        //
+        // mStopSpinnerRunnable = new Runnable() {
+        // public void run() {
+        // // mSearchView.setWorking(false); // TODO:
+        // }
+        // };
 
         // delay 500ms when deleting
         getFilter().setDelayer(new Filter.Delayer() {
@@ -341,10 +342,10 @@
         }
 
         if (views.mIcon1 != null) {
-            setViewDrawable(views.mIcon1, getIcon1(cursor));
+            setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE);
         }
         if (views.mIcon2 != null) {
-            setViewDrawable(views.mIcon2, getIcon2(cursor));
+            setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE);
         }
         if (mQueryRefinement == REFINE_ALL
                 || (mQueryRefinement == REFINE_BY_ENTRY
@@ -414,13 +415,13 @@
      * Sets the drawable in an image view, makes sure the view is only visible if there
      * is a drawable.
      */
-    private void setViewDrawable(ImageView v, Drawable drawable) {
+    private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) {
         // Set the icon even if the drawable is null, since we need to clear any
         // previous icon.
         v.setImageDrawable(drawable);
 
         if (drawable == null) {
-            v.setVisibility(View.GONE);
+            v.setVisibility(nullVisibility);
         } else {
             v.setVisibility(View.VISIBLE);
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index b7565f3..0c80a11 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -34,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.R;
 
@@ -360,6 +361,13 @@
         }
     }
 
+    @Override
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        super.onPopulateAccessibilityEvent(event);
+        Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
+        event.getText().add(switchText.getText());
+    }
+
     private Layout makeLayout(CharSequence text) {
         return new StaticLayout(text, mTextPaint,
                 (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)),
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6b4e454..127b6a3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -59,6 +59,13 @@
 import android.text.Spanned;
 import android.text.SpannedString;
 import android.text.StaticLayout;
+import android.text.TextDirectionHeuristic;
+import android.text.TextDirectionHeuristics;
+import android.text.TextDirectionHeuristics.AnyStrong;
+import android.text.TextDirectionHeuristics.CharCount;
+import android.text.TextDirectionHeuristics.FirstStrong;
+import android.text.TextDirectionHeuristics.TextDirectionAlgorithm;
+import android.text.TextDirectionHeuristics.TextDirectionHeuristicImpl;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -105,12 +112,12 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewAncestor;
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewParent;
+import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
@@ -322,7 +329,6 @@
     private int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout;
     private int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout;
 
-    private int mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout;
     private int mTextEditSuggestionItemLayout;
     private SuggestionsPopupWindow mSuggestionsPopupWindow;
     private SuggestionRangeSpan mSuggestionRangeSpan;
@@ -355,7 +361,7 @@
         INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
     }
 
-    private boolean bResolvedDrawables = false;
+    private boolean mResolvedDrawables = false;
 
     /*
      * Kick-start the font cache for the zygote process (to pay the cost of
@@ -823,14 +829,6 @@
                 mTextEditSideNoPasteWindowLayout = a.getResourceId(attr, 0);
                 break;
 
-            case com.android.internal.R.styleable.TextView_textEditSuggestionsBottomWindowLayout:
-                mTextEditSuggestionsBottomWindowLayout = a.getResourceId(attr, 0);
-                break;
-
-            case com.android.internal.R.styleable.TextView_textEditSuggestionsTopWindowLayout:
-                mTextEditSuggestionsTopWindowLayout = a.getResourceId(attr, 0);
-                break;
-
             case com.android.internal.R.styleable.TextView_textEditSuggestionItemLayout:
                 mTextEditSuggestionItemLayout = a.getResourceId(attr, 0);
                 break;
@@ -3417,7 +3415,7 @@
         return mHint;
     }
 
-    private boolean isMultilineInputType(int type) {
+    private static boolean isMultilineInputType(int type) {
         return (type & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE)) ==
             (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
     }
@@ -3493,7 +3491,7 @@
         return mTransformation instanceof PasswordTransformationMethod;
     }
 
-    private boolean isPasswordInputType(int inputType) {
+    private static boolean isPasswordInputType(int inputType) {
         final int variation =
                 inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
         return variation
@@ -3504,7 +3502,7 @@
                 == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
     }
 
-    private boolean isVisiblePasswordInputType(int inputType) {
+    private static boolean isVisiblePasswordInputType(int inputType) {
         final int variation =
                 inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
         return variation
@@ -3724,13 +3722,13 @@
         Handler h = getHandler();
         if (h != null) {
             long eventTime = SystemClock.uptimeMillis();
-            h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME,
+            h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
                     new KeyEvent(eventTime, eventTime,
                     KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0,
                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                     KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
                     | KeyEvent.FLAG_EDITOR_ACTION)));
-            h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME,
+            h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
                     new KeyEvent(SystemClock.uptimeMillis(), eventTime,
                     KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0,
                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
@@ -5055,6 +5053,67 @@
         return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
     }
 
+    /**
+     * @hide
+     * @param offsetRequired
+     */
+    @Override
+    protected int getFadeTop(boolean offsetRequired) {
+        if (mLayout == null) return 0;
+
+        int voffset = 0;
+        if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
+            voffset = getVerticalOffset(true);
+        }
+        
+        if (offsetRequired) voffset += getTopPaddingOffset();
+
+        return getExtendedPaddingTop() + voffset;
+    }
+
+    /**
+     * @hide
+     * @param offsetRequired
+     */
+    @Override
+    protected int getFadeHeight(boolean offsetRequired) {
+        return mLayout != null ? mLayout.getHeight() : 0;
+    }
+
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            boolean areSuggestionsShown = areSuggestionsShown();
+            boolean isInSelectionMode = mSelectionActionMode != null;
+
+            if (areSuggestionsShown || isInSelectionMode) {
+                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
+                    return true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.handleUpEvent(event);
+                    }
+                    if (event.isTracking() && !event.isCanceled()) {
+                        if (areSuggestionsShown) {
+                            hideSuggestions();
+                            return true;
+                        }
+                        if (isInSelectionMode) {
+                            stopSelectionActionMode();
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return super.onKeyPreIme(keyCode, event);
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         int which = doKeyDown(keyCode, event, null);
@@ -5207,6 +5266,10 @@
 
                 // Has to be done on key down (and not on key up) to correctly be intercepted.
             case KeyEvent.KEYCODE_BACK:
+                if (areSuggestionsShown()) {
+                    hideSuggestions();
+                    return -1;
+                }
                 if (mSelectionActionMode != null) {
                     stopSelectionActionMode();
                     return -1;
@@ -5832,6 +5895,7 @@
         if (curs >= 0) {
             mHighlightPathBogus = true;
             makeBlink();
+            bringPointIntoView(curs);
         }
 
         checkForResize();
@@ -5992,14 +6056,17 @@
         Layout.Alignment alignment = getLayoutAlignment();
         boolean shouldEllipsize = mEllipsize != null && mInput == null;
 
+        if (mTextDir == null) {
+            resolveTextDirection();
+        }
         if (mText instanceof Spannable) {
             mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w,
-                    alignment, mSpacingMult,
+                    alignment, mTextDir, mSpacingMult,
                     mSpacingAdd, mIncludePad, mInput == null ? mEllipsize : null,
                     ellipsisWidth);
         } else {
             if (boring == UNKNOWN_BORING) {
-                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
+                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -6036,23 +6103,23 @@
                 } else if (shouldEllipsize) {
                     mLayout = new StaticLayout(mTransformed,
                                 0, mTransformed.length(),
-                                mTextPaint, w, alignment, mSpacingMult,
+                                mTextPaint, w, alignment, mTextDir, mSpacingMult,
                                 mSpacingAdd, mIncludePad, mEllipsize,
                                 ellipsisWidth);
                 } else {
                     mLayout = new StaticLayout(mTransformed, mTextPaint,
-                            w, alignment, mSpacingMult, mSpacingAdd,
+                            w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
                             mIncludePad);
                 }
             } else if (shouldEllipsize) {
                 mLayout = new StaticLayout(mTransformed,
                             0, mTransformed.length(),
-                            mTextPaint, w, alignment, mSpacingMult,
+                            mTextPaint, w, alignment, mTextDir, mSpacingMult,
                             mSpacingAdd, mIncludePad, mEllipsize,
                             ellipsisWidth);
             } else {
                 mLayout = new StaticLayout(mTransformed, mTextPaint,
-                        w, alignment, mSpacingMult, mSpacingAdd,
+                        w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
                         mIncludePad);
             }
         }
@@ -6064,7 +6131,7 @@
             if (shouldEllipsize) hintWidth = w;
 
             if (hintBoring == UNKNOWN_BORING) {
-                hintBoring = BoringLayout.isBoring(mHint, mTextPaint,
+                hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
                                                    mHintBoring);
                 if (hintBoring != null) {
                     mHintBoring = hintBoring;
@@ -6102,23 +6169,23 @@
                 } else if (shouldEllipsize) {
                     mHintLayout = new StaticLayout(mHint,
                                 0, mHint.length(),
-                                mTextPaint, hintWidth, alignment, mSpacingMult,
+                                mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
                                 mSpacingAdd, mIncludePad, mEllipsize,
                                 ellipsisWidth);
                 } else {
                     mHintLayout = new StaticLayout(mHint, mTextPaint,
-                            hintWidth, alignment, mSpacingMult, mSpacingAdd,
+                            hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
                             mIncludePad);
                 }
             } else if (shouldEllipsize) {
                 mHintLayout = new StaticLayout(mHint,
                             0, mHint.length(),
-                            mTextPaint, hintWidth, alignment, mSpacingMult,
+                            mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
                             mSpacingAdd, mIncludePad, mEllipsize,
                             ellipsisWidth);
             } else {
                 mHintLayout = new StaticLayout(mHint, mTextPaint,
-                        hintWidth, alignment, mSpacingMult, mSpacingAdd,
+                        hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
                         mIncludePad);
             }
         }
@@ -6219,6 +6286,10 @@
         BoringLayout.Metrics boring = UNKNOWN_BORING;
         BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
 
+        if (mTextDir == null) {
+            resolveTextDirection();
+        }
+
         int des = -1;
         boolean fromexisting = false;
 
@@ -6231,7 +6302,7 @@
             }
 
             if (des < 0) {
-                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
+                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -6571,11 +6642,11 @@
                     scrollx = left;
                 }
             }
-        } else if (a == Layout.Alignment.ALIGN_LEFT) {
-            scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
-        } else { // a == Layout.Alignment.ALIGN_RIGHT
+        } else if (a == Layout.Alignment.ALIGN_RIGHT) {
             int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
             scrollx = right - hspace;
+        } else { // a == Layout.Alignment.ALIGN_LEFT (will also be the default)
+            scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
         }
 
         if (ht < vspace) {
@@ -6603,6 +6674,8 @@
     public boolean bringPointIntoView(int offset) {
         boolean changed = false;
 
+        if (mLayout == null) return changed;
+
         int line = mLayout.getLineForOffset(offset);
 
         // FIXME: Is it okay to truncate this, or should we round?
@@ -7573,9 +7646,9 @@
         // Because of View recycling in ListView, there is no easy way to know when a TextView with
         // selection becomes visible again. Until a better solution is found, stop text selection
         // mode (if any) as soon as this TextView is recycled.
-        stopSelectionActionMode();
+        hideControllers();
     }
-    
+
     @Override
     public void onFinishTemporaryDetach() {
         super.onFinishTemporaryDetach();
@@ -7583,7 +7656,7 @@
         // usually because this instance is an editable field in a list
         if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
     }
-    
+
     @Override
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
         if (mTemporaryDetach) {
@@ -7845,8 +7918,7 @@
                 if (!selectAllGotFocus && hasSelection()) {
                     startSelectionActionMode();
                 } else {
-                    stopSelectionActionMode();
-                    hideSuggestions();
+                    hideControllers();
                     if (hasInsertionController() && !selectAllGotFocus && mText.length() > 0) {
                         getInsertionController().show();
                     }
@@ -8703,22 +8775,48 @@
     private class SuggestionsPopupWindow implements OnClickListener {
         private static final int MAX_NUMBER_SUGGESTIONS = 5;
         private static final int NO_SUGGESTIONS = -1;
-        private final PopupWindow mContainer;
-        private final ViewGroup[] mSuggestionViews = new ViewGroup[2];
-        private final int[] mSuggestionViewLayouts = new int[] {
-                mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout};
+        private final PopupWindow mPopupWindow;
+        private LinearLayout mSuggestionsContainer;
         private WordIterator mSuggestionWordIterator;
         private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
 
         public SuggestionsPopupWindow() {
-            mContainer = new PopupWindow(TextView.this.mContext, null,
+            mPopupWindow = new PopupWindow(TextView.this.mContext, null,
                     com.android.internal.R.attr.textSuggestionsWindowStyle);
-            mContainer.setSplitTouchEnabled(true);
-            mContainer.setClippingEnabled(false);
-            mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+            mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+            mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+            mPopupWindow.setOutsideTouchable(true);
 
-            mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
-            mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+            mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+            mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+
+            mSuggestionsContainer = new LinearLayout(TextView.this.mContext);
+            mSuggestionsContainer.setOrientation(LinearLayout.VERTICAL);
+
+            LayoutInflater inflater = (LayoutInflater) TextView.this.mContext.
+                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            if (inflater == null) {
+                throw new IllegalArgumentException(
+                        "Unable to create inflater for TextEdit suggestions");
+            }
+
+            // Inflate the suggestion items once and for all.
+            for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
+                View childView = inflater.inflate(mTextEditSuggestionItemLayout,
+                        mSuggestionsContainer, false);
+
+                if (! (childView instanceof TextView)) {
+                    throw new IllegalArgumentException(
+                            "Inflated TextEdit suggestion item is not a TextView: " + childView);
+                }
+
+                childView.setTag(new SuggestionInfo());
+                mSuggestionsContainer.addView(childView);
+                childView.setOnClickListener(this);
+            }
+
+            mPopupWindow.setContentView(mSuggestionsContainer);
         }
 
         private class SuggestionInfo {
@@ -8728,50 +8826,6 @@
             int suggestionIndex; // the index of the suggestion inside suggestionSpan
         }
 
-        private ViewGroup getViewGroup(boolean under) {
-            final int viewIndex = under ? 0 : 1;
-            ViewGroup viewGroup = mSuggestionViews[viewIndex];
-
-            if (viewGroup == null) {
-                final int layout = mSuggestionViewLayouts[viewIndex];
-                LayoutInflater inflater = (LayoutInflater) TextView.this.mContext.
-                        getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-                if (inflater == null) {
-                    throw new IllegalArgumentException(
-                            "Unable to create TextEdit suggestion window inflater");
-                }
-
-                View view = inflater.inflate(layout, null);
-
-                if (! (view instanceof ViewGroup)) {
-                    throw new IllegalArgumentException(
-                            "Inflated TextEdit suggestion window is not a ViewGroup: " + view);
-                }
-
-                viewGroup = (ViewGroup) view;
-
-                // Inflate the suggestion items once and for all.
-                for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
-                    View childView = inflater.inflate(mTextEditSuggestionItemLayout, viewGroup,
-                            false);
-
-                    if (! (childView instanceof TextView)) {
-                        throw new IllegalArgumentException(
-                               "Inflated TextEdit suggestion item is not a TextView: " + childView);
-                    }
-
-                    childView.setTag(new SuggestionInfo());
-                    viewGroup.addView(childView);
-                    childView.setOnClickListener(this);
-                }
-
-                mSuggestionViews[viewIndex] = viewGroup;
-            }
-
-            return viewGroup;
-        }
-
         public void show() {
             if (!(mText instanceof Editable)) return;
 
@@ -8780,9 +8834,6 @@
             SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
             final int nbSpans = suggestionSpans.length;
 
-            ViewGroup viewGroup = getViewGroup(true);
-            mContainer.setContentView(viewGroup);
-
             int totalNbSuggestions = 0;
             int spanUnionStart = mText.length();
             int spanUnionEnd = 0;
@@ -8797,7 +8848,8 @@
                 String[] suggestions = suggestionSpan.getSuggestions();
                 int nbSuggestions = suggestions.length;
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
-                    TextView textView = (TextView) viewGroup.getChildAt(totalNbSuggestions);
+                    TextView textView = (TextView) mSuggestionsContainer.getChildAt(
+                            totalNbSuggestions);
                     textView.setText(suggestions[suggestionIndex]);
                     SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
                     suggestionInfo.spanStart = spanStart;
@@ -8816,7 +8868,7 @@
 
             if (totalNbSuggestions == 0) {
                 // TODO Replace by final text, use a dedicated layout, add a fade out timer...
-                TextView textView = (TextView) viewGroup.getChildAt(0);
+                TextView textView = (TextView) mSuggestionsContainer.getChildAt(0);
                 textView.setText("No suggestions available");
                 SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
                 suggestionInfo.spanStart = NO_SUGGESTIONS;
@@ -8827,17 +8879,24 @@
                         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
                 for (int i = 0; i < totalNbSuggestions; i++) {
-                    final TextView textView = (TextView) viewGroup.getChildAt(i);
+                    final TextView textView = (TextView) mSuggestionsContainer.getChildAt(i);
                     highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
                 }
             }
 
-            for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
-                viewGroup.getChildAt(i).setVisibility(i < totalNbSuggestions ? VISIBLE : GONE);
+            for (int i = 0; i < totalNbSuggestions; i++) {
+                mSuggestionsContainer.getChildAt(i).setVisibility(VISIBLE);
+            }
+            for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
+                mSuggestionsContainer.getChildAt(i).setVisibility(GONE);
             }
 
-            final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
-            viewGroup.measure(size, size);
+            final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
+            final int screenWidth = displayMetrics.widthPixels;
+            final int screenHeight = displayMetrics.heightPixels;
+            mSuggestionsContainer.measure(
+                    View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST),
+                    View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST));
 
             positionAtCursor();
         }
@@ -8995,7 +9054,11 @@
             if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
                 ((Editable) mText).removeSpan(mSuggestionRangeSpan);
             }
-            mContainer.dismiss();
+            mPopupWindow.dismiss();
+        }
+
+        public boolean isShowing() {
+            return mPopupWindow.isShowing();
         }
 
         @Override
@@ -9059,7 +9122,7 @@
         }
 
         void positionAtCursor() {
-            View contentView = mContainer.getContentView();
+            View contentView = mPopupWindow.getContentView();
             int width = contentView.getMeasuredWidth();
             int height = contentView.getMeasuredHeight();
             final int offset = TextView.this.getSelectionStart();
@@ -9086,25 +9149,14 @@
 
             // Vertical clipping
             if (coords[1] + height > screenHeight) {
-                // Try to position above current line instead
-                // TODO use top layout instead, reverse suggestion order,
-                // try full screen vertical down if it still does not fit. TBD with designers.
-
-                // Update dimensions from new view
-                contentView = mContainer.getContentView();
-                width = contentView.getMeasuredWidth();
-                height = contentView.getMeasuredHeight();
-
-                final int lineTop = mLayout.getLineTop(line);
-                final int lineHeight = lineBottom - lineTop;
-                coords[1] -= height + lineHeight;
+                coords[1] = screenHeight - height;
             }
 
             // Horizontal clipping
-            coords[0] = Math.max(0, coords[0]);
             coords[0] = Math.min(displayMetrics.widthPixels - width, coords[0]);
+            coords[0] = Math.max(0, coords[0]);
 
-            mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
+            mPopupWindow.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
         }
     }
 
@@ -9124,6 +9176,10 @@
         }
     }
 
+    boolean areSuggestionsShown() {
+        return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
+    } 
+
     /**
      * Some parts of the text can have alternate suggestion text attached. This is typically done by
      * the IME by adding {@link SuggestionSpan}s to the text.
@@ -9157,16 +9213,17 @@
      * Paste actions, depending on what this View supports.
      *
      * A custom implementation can add new entries in the default menu in its
-     * {@link ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The default actions
-     * can also be removed from the menu using {@link Menu#removeItem(int)} and passing
-     * {@link android.R.id#selectAll}, {@link android.R.id#cut}, {@link android.R.id#copy} or
-     * {@link android.R.id#paste} ids as parameters.
+     * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
+     * default actions can also be removed from the menu using {@link Menu#removeItem(int)} and
+     * passing {@link android.R.id#selectAll}, {@link android.R.id#cut}, {@link android.R.id#copy}
+     * or {@link android.R.id#paste} ids as parameters.
      *
-     * Returning false from {@link ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will
-     * prevent the action mode from being started.
+     * Returning false from 
+     * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
+     * the action mode from being started.
      *
      * Action click events should be handled by the custom implementation of
-     * {@link ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
+     * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
      *
      * Note that text selection mode is not started when a TextView receives focus and the
      * {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
@@ -9441,7 +9498,7 @@
         @Override
         public void onClick(View v) {
             if (canPaste()) {
-                paste(getSelectionStart(), getSelectionEnd());
+                onTextContextMenuItem(ID_PASTE);
             }
             hide();
         }
@@ -9722,9 +9779,9 @@
                         mLastParentX = mTempCoords[0];
                         mLastParentY = mTempCoords[1];
                     }
-                }
 
-                onHandleMoved();
+                    onHandleMoved();
+                }
 
                 if (isPositionVisible()) {
                     mContainer.update(mContainerPositionX, mContainerPositionY,
@@ -10167,7 +10224,6 @@
 
                     mPreviousTapPositionX = x;
                     mPreviousTapPositionY = y;
-
                     break;
 
                 case MotionEvent.ACTION_POINTER_DOWN:
@@ -10439,11 +10495,21 @@
         return mInBatchEditControllers;
     }
 
+    private class TextViewDirectionHeuristic extends TextDirectionHeuristicImpl {
+        private TextViewDirectionHeuristic(TextDirectionAlgorithm algorithm) {
+            super(algorithm);
+        }
+        @Override
+        protected boolean defaultIsRtl() {
+            return getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL;
+        }
+    }
+
     /**
      * 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
+     * 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
@@ -10452,157 +10518,28 @@
      */
     @Override
     protected void resolveTextDirection() {
-        int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
-        switch(mTextDirection) {
+        super.resolveTextDirection();
+
+        int textDir = getResolvedTextDirection();
+        switch (textDir) {
             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);
+                mTextDir = new TextViewDirectionHeuristic(FirstStrong.INSTANCE);
                 break;
             case TEXT_DIRECTION_ANY_RTL:
-                resolvedTextDirection = getTextDirectionFromAnyRtl(mText);
+                mTextDir = new TextViewDirectionHeuristic(AnyStrong.INSTANCE_RTL);
                 break;
             case TEXT_DIRECTION_CHAR_COUNT:
-                resolvedTextDirection = getTextDirectionFromCharCount(mText);
+                mTextDir = new TextViewDirectionHeuristic(CharCount.INSTANCE_DEFAULT);
                 break;
             case TEXT_DIRECTION_LTR:
-                resolvedTextDirection = TEXT_DIRECTION_LTR;
+                mTextDir = TextDirectionHeuristics.LTR;
                 break;
             case TEXT_DIRECTION_RTL:
-                resolvedTextDirection = TEXT_DIRECTION_RTL;
+                mTextDir = TextDirectionHeuristics.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);
     }
 
     /**
@@ -10614,7 +10551,7 @@
      */
     protected void resolveDrawables() {
         // No need to resolve twice
-        if (bResolvedDrawables) {
+        if (mResolvedDrawables) {
             return;
         }
         // No drawable to resolve
@@ -10623,7 +10560,7 @@
         }
         // No relative drawable to resolve
         if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
-            bResolvedDrawables = true;
+            mResolvedDrawables = true;
             return;
         }
 
@@ -10660,11 +10597,11 @@
                 }
                 break;
         }
-        bResolvedDrawables = true;
+        mResolvedDrawables = true;
     }
 
     protected void resetResolvedDrawables() {
-        bResolvedDrawables = false;
+        mResolvedDrawables = false;
     }
 
     @ViewDebug.ExportedProperty(category = "text")
@@ -10768,6 +10705,8 @@
 
     private BoringLayout mSavedLayout, mSavedHintLayout;
 
+    private TextDirectionHeuristic mTextDir = null;
+
     private static final InputFilter[] NO_FILTERS = new InputFilter[0];
     private InputFilter[] mFilters = NO_FILTERS;
     private static final Spanned EMPTY_SPANNED = new SpannedString("");
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 9e37c7b..f3d891d 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -33,7 +33,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.View.OnClickListener;
 import android.view.WindowManager.LayoutParams;
@@ -501,7 +501,7 @@
 
         } else {
 
-            ViewAncestor viewRoot = getOwnerViewAncestor();
+            ViewRootImpl viewRoot = getOwnerViewRootImpl();
             if (viewRoot != null) {
                 viewRoot.dispatchKey(event);
             }
@@ -526,15 +526,15 @@
         }
     }
 
-    private ViewAncestor getOwnerViewAncestor() {
+    private ViewRootImpl getOwnerViewRootImpl() {
         View rootViewOfOwner = mOwnerView.getRootView();
         if (rootViewOfOwner == null) {
             return null;
         }
 
         ViewParent parentOfRootView = rootViewOfOwner.getParent();
-        if (parentOfRootView instanceof ViewAncestor) {
-            return (ViewAncestor) parentOfRootView;
+        if (parentOfRootView instanceof ViewRootImpl) {
+            return (ViewRootImpl) parentOfRootView;
         } else {
             return null;
         }
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 519acf5..95f1f98 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -36,6 +36,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Handler;
 import android.view.ActionMode;
 import android.view.LayoutInflater;
@@ -75,7 +76,9 @@
     private TabImpl mSelectedTab;
     private int mSavedTabPosition = INVALID_POSITION;
     
-    private ActionMode mActionMode;
+    ActionModeImpl mActionMode;
+    ActionMode mDeferredDestroyActionMode;
+    ActionMode.Callback mDeferredModeDestroyCallback;
     
     private boolean mLastMenuVisibility;
     private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
@@ -103,10 +106,12 @@
         public void onAnimationEnd(Animator animation) {
             if (mContentView != null) {
                 mContentView.setTranslationY(0);
+                mContainerView.setTranslationY(0);
             }
             mContainerView.setVisibility(View.GONE);
             mContainerView.setTransitioning(false);
             mCurrentShowAnim = null;
+            completeDeferredDestroyActionMode();
         }
     };
 
@@ -155,6 +160,11 @@
                 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
 
         mContentHeight = mActionView.getContentHeight();
+
+        // Older apps get the home button interaction enabled by default.
+        // Newer apps need to enable it explicitly.
+        setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion <
+                Build.VERSION_CODES.ICE_CREAM_SANDWICH);
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
@@ -201,6 +211,14 @@
         mTabScrollView = tabScroller;
     }
 
+    void completeDeferredDestroyActionMode() {
+        if (mDeferredModeDestroyCallback != null) {
+            mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
+            mDeferredDestroyActionMode = null;
+            mDeferredModeDestroyCallback = null;
+        }
+    }
+
     /**
      * Enables or disables animation between show/hide states.
      * If animation is disabled using this method, animations in progress
@@ -266,8 +284,8 @@
     }
 
     @Override
-    public void setDisplayDisableHomeEnabled(boolean disableHome) {
-        setDisplayOptions(disableHome ? DISPLAY_DISABLE_HOME : 0, DISPLAY_DISABLE_HOME);
+    public void setHomeButtonEnabled(boolean enable) {
+        mActionView.setHomeButtonEnabled(enable);
     }
 
     @Override
@@ -351,14 +369,16 @@
     }
 
     public ActionMode startActionMode(ActionMode.Callback callback) {
+        boolean wasHidden = false;
         if (mActionMode != null) {
+            wasHidden = mWasHiddenBeforeMode;
             mActionMode.finish();
         }
 
         mContextView.killMode();
         ActionModeImpl mode = new ActionModeImpl(callback);
         if (mode.dispatchOnCreate()) {
-            mWasHiddenBeforeMode = !isShowing();
+            mWasHiddenBeforeMode = !isShowing() || wasHidden;
             mode.invalidate();
             mContextView.initForMode(mode);
             animateToMode(true);
@@ -492,7 +512,7 @@
 
     @Override
     public int getHeight() {
-        return mActionView.getHeight();
+        return mContainerView.getHeight();
     }
 
     @Override
@@ -571,7 +591,9 @@
     }
 
     void animateToMode(boolean toActionMode) {
-        show(false);
+        if (toActionMode) {
+            show(false);
+        }
         if (mCurrentModeAnim != null) {
             mCurrentModeAnim.end();
         }
@@ -615,7 +637,16 @@
                 return;
             }
 
-            mCallback.onDestroyActionMode(this);
+            // If we were hidden before the mode was shown, defer the onDestroy
+            // callback until the animation is finished and associated relayout
+            // is about to happen. This lets apps better anticipate visibility
+            // and layout behavior.
+            if (mWasHiddenBeforeMode) {
+                mDeferredDestroyActionMode = this;
+                mDeferredModeDestroyCallback = mCallback;
+            } else {
+                mCallback.onDestroyActionMode(this);
+            }
             mCallback = null;
             animateToMode(false);
 
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 8d6caa1..2061c90 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -438,7 +438,7 @@
             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                     LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
             
-            topPanel.addView(mCustomTitleView, lp);
+            topPanel.addView(mCustomTitleView, 0, lp);
             
             // Hide the title template
             View titleTemplate = mWindow.findViewById(R.id.title_template);
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 6039cc2..e1166f1 100755
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -23,6 +23,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.widget.Toast;
 import android.util.Log;
 import android.location.LocationManager;
@@ -44,8 +46,12 @@
     private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
     private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE;
 
+    private static final int GPS_NO_RESPONSE_TIME_OUT = 1;
     // Received ID from intent, -1 when no notification is in progress
     private int notificationId = -1;
+    private int timeout = -1;
+    private int default_response = -1;
+    private int default_response_timeout = 6;
 
     /** Used to detect when NI request is received */
     private BroadcastReceiver mNetInitiatedReceiver = new BroadcastReceiver() {
@@ -58,6 +64,21 @@
         }
     };
 
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case GPS_NO_RESPONSE_TIME_OUT: {
+                if (notificationId != -1) {
+                    sendUserResponse(default_response);
+                }
+                finish();
+            }
+            break;
+            default:
+            }
+        }
+    };
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -75,8 +96,11 @@
         p.mNegativeButtonListener = this;
 
         notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
-        if (DEBUG) Log.d(TAG, "onCreate, notifId: " + notificationId);
+        timeout = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TIMEOUT, default_response_timeout);
+        default_response = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_DEFAULT_RESPONSE, GpsNetInitiatedHandler.GPS_NI_RESPONSE_ACCEPT);
+        if (DEBUG) Log.d(TAG, "onCreate() : notificationId: " + notificationId + " timeout: " + timeout + " default_response:" + default_response);
 
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(GPS_NO_RESPONSE_TIME_OUT), (timeout * 1000));
         setupAlert();
     }
 
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 9ae7def..1531946 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -1,22 +1,9 @@
 package com.android.internal.content;
 
-import android.content.pm.PackageManager;
 import android.os.Build;
-import android.os.FileUtils;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
 
 /**
  * Native libraries helper.
@@ -28,270 +15,22 @@
 
     private static final boolean DEBUG_NATIVE = false;
 
-    /*
-     * The following constants are returned by listPackageSharedLibsForAbiLI
-     * to indicate if native shared libraries were found in the package.
-     * Values are:
-     *    PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
-     *    PACKAGE_INSTALL_NATIVE_NO_LIBRARIES     => no native libraries in package
-     *    PACKAGE_INSTALL_NATIVE_ABI_MISMATCH     => native libraries for another ABI found
-     *                                        in package (and not installed)
-     *
-     */
-    private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
-    private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
-    private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
+    private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);
 
-    // Directory in the APK that holds all the native shared libraries.
-    private static final String APK_LIB = "lib/";
-    private static final int APK_LIB_LENGTH = APK_LIB.length();
-
-    // Prefix that native shared libraries must have.
-    private static final String LIB_PREFIX = "lib";
-    private static final int LIB_PREFIX_LENGTH = LIB_PREFIX.length();
-
-    // Suffix that the native shared libraries must have.
-    private static final String LIB_SUFFIX = ".so";
-    private static final int LIB_SUFFIX_LENGTH = LIB_SUFFIX.length();
-
-    // Name of the GDB binary.
-    private static final String GDBSERVER = "gdbserver";
-
-    // the minimum length of a valid native shared library of the form
-    // lib/<something>/lib<name>.so.
-    private static final int MIN_ENTRY_LENGTH = APK_LIB_LENGTH + 2 + LIB_PREFIX_LENGTH + 1
-            + LIB_SUFFIX_LENGTH;
-
-    /*
-     * Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
-     * and add them to a list to be installed later.
-     *
-     * NOTE: this method may throw an IOException if the library cannot
-     * be copied to its final destination, e.g. if there isn't enough
-     * room left on the data partition, or a ZipException if the package
-     * file is malformed.
-     */
-    private static int listPackageSharedLibsForAbiLI(ZipFile zipFile,
-            String cpuAbi, List<Pair<ZipEntry, String>> libEntries) throws IOException,
-            ZipException {
-        final int cpuAbiLen = cpuAbi.length();
-        boolean hasNativeLibraries = false;
-        boolean installedNativeLibraries = false;
-
-        if (DEBUG_NATIVE) {
-            Slog.d(TAG, "Checking " + zipFile.getName() + " for shared libraries of CPU ABI type "
-                    + cpuAbi);
-        }
-
-        Enumeration<? extends ZipEntry> entries = zipFile.entries();
-
-        while (entries.hasMoreElements()) {
-            ZipEntry entry = entries.nextElement();
-
-            // skip directories
-            if (entry.isDirectory()) {
-                continue;
-            }
-            String entryName = entry.getName();
-
-            /*
-             * Check that the entry looks like lib/<something>/lib<name>.so
-             * here, but don't check the ABI just yet.
-             *
-             * - must be sufficiently long
-             * - must end with LIB_SUFFIX, i.e. ".so"
-             * - must start with APK_LIB, i.e. "lib/"
-             */
-            if (entryName.length() < MIN_ENTRY_LENGTH || !entryName.endsWith(LIB_SUFFIX)
-                    || !entryName.startsWith(APK_LIB)) {
-                continue;
-            }
-
-            // file name must start with LIB_PREFIX, i.e. "lib"
-            int lastSlash = entryName.lastIndexOf('/');
-
-            if (lastSlash < 0
-                    || !entryName.regionMatches(lastSlash + 1, LIB_PREFIX, 0, LIB_PREFIX_LENGTH)) {
-                continue;
-            }
-
-            hasNativeLibraries = true;
-
-            // check the cpuAbi now, between lib/ and /lib<name>.so
-            if (lastSlash != APK_LIB_LENGTH + cpuAbiLen
-                    || !entryName.regionMatches(APK_LIB_LENGTH, cpuAbi, 0, cpuAbiLen))
-                continue;
-
-            /*
-             * Extract the library file name, ensure it doesn't contain
-             * weird characters. we're guaranteed here that it doesn't contain
-             * a directory separator though.
-             */
-            String libFileName = entryName.substring(lastSlash+1);
-            if (!FileUtils.isFilenameSafe(new File(libFileName))) {
-                continue;
-            }
-
-            installedNativeLibraries = true;
-
-            if (DEBUG_NATIVE) {
-                Log.d(TAG, "Caching shared lib " + entry.getName());
-            }
-
-            libEntries.add(Pair.create(entry, libFileName));
-        }
-        if (!hasNativeLibraries)
-            return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
-
-        if (!installedNativeLibraries)
-            return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
-
-        return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
+    public static long sumNativeBinariesLI(File apkFile) {
+        final String cpuAbi = Build.CPU_ABI;
+        final String cpuAbi2 = Build.CPU_ABI2;
+        return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2);
     }
 
-    /*
-     * Find the gdbserver executable program in a package at
-     * lib/<cpuAbi>/gdbserver and add it to the list of binaries
-     * to be copied out later.
-     *
-     * Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
-     * or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
-     */
-    private static int listPackageGdbServerLI(ZipFile zipFile, String cpuAbi,
-            List<Pair<ZipEntry, String>> nativeFiles) throws IOException, ZipException {
-        final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
+    private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
+            String cpuAbi, String cpuAbi2);
 
-        Enumeration<? extends ZipEntry> entries = zipFile.entries();
-
-        while (entries.hasMoreElements()) {
-            ZipEntry entry = entries.nextElement();
-            // skip directories
-            if (entry.isDirectory()) {
-                continue;
-            }
-            String entryName = entry.getName();
-
-            if (!entryName.equals(apkGdbServerPath)) {
-                continue;
-            }
-
-            if (false) {
-                Log.d(TAG, "Found gdbserver: " + entry.getName());
-            }
-
-            final String installGdbServerPath = GDBSERVER;
-            nativeFiles.add(Pair.create(entry, installGdbServerPath));
-
-            return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
-        }
-        return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
-    }
-
-    /*
-     * Examine shared libraries stored in the APK as
-     * lib/<cpuAbi>/lib<name>.so and add them to a list to be copied
-     * later.
-     *
-     * This function will first try the main CPU ABI defined by Build.CPU_ABI
-     * (which corresponds to ro.product.cpu.abi), and also try an alternate
-     * one if ro.product.cpu.abi2 is defined.
-     */
-    public static int listPackageNativeBinariesLI(ZipFile zipFile,
-            List<Pair<ZipEntry, String>> nativeFiles) throws ZipException, IOException {
-        String cpuAbi = Build.CPU_ABI;
-
-        int result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi, nativeFiles);
-
-        /*
-         * Some architectures are capable of supporting several CPU ABIs
-         * for example, 'armeabi-v7a' also supports 'armeabi' native code
-         * this is indicated by the definition of the ro.product.cpu.abi2
-         * system property.
-         *
-         * only scan the package twice in case of ABI mismatch
-         */
-        if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
-            final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2", null);
-            if (cpuAbi2 != null) {
-                result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi2, nativeFiles);
-            }
-
-            if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
-                Slog.w(TAG, "Native ABI mismatch from package file");
-                return PackageManager.INSTALL_FAILED_INVALID_APK;
-            }
-
-            if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
-                cpuAbi = cpuAbi2;
-            }
-        }
-
-        /*
-         * Debuggable packages may have gdbserver embedded, so add it to
-         * the list to the list of items to be extracted (as lib/gdbserver)
-         * into the application's native library directory later.
-         */
-        if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
-            listPackageGdbServerLI(zipFile, cpuAbi, nativeFiles);
-        }
-        return PackageManager.INSTALL_SUCCEEDED;
-    }
-
-    public static int copyNativeBinariesLI(File scanFile, File sharedLibraryDir) {
-        /*
-         * Check all the native files that need to be copied and add
-         * that to the container size.
-         */
-        ZipFile zipFile;
-        try {
-            zipFile = new ZipFile(scanFile);
-
-            List<Pair<ZipEntry, String>> nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
-
-            NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
-
-            final int N = nativeFiles.size();
-
-            for (int i = 0; i < N; i++) {
-                final Pair<ZipEntry, String> entry = nativeFiles.get(i);
-
-                File destFile = new File(sharedLibraryDir, entry.second);
-                copyNativeBinaryLI(zipFile, entry.first, sharedLibraryDir, destFile);
-            }
-            zipFile.close();
-        } catch (ZipException e) {
-            Slog.w(TAG, "Failed to extract data from package file", e);
-            return PackageManager.INSTALL_FAILED_INVALID_APK;
-        } catch (IOException e) {
-            Slog.w(TAG, "Failed to cache package shared libs", e);
-            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-        }
-
-        return PackageManager.INSTALL_SUCCEEDED;
-    }
-
-    private static void copyNativeBinaryLI(ZipFile zipFile, ZipEntry entry,
-            File binaryDir, File binaryFile) throws IOException {
-        InputStream inputStream = zipFile.getInputStream(entry);
-        try {
-            File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
-            String tempFilePath = tempFile.getPath();
-            // XXX package manager can't change owner, so the executable files for
-            // now need to be left as world readable and owned by the system.
-            if (!FileUtils.copyToFile(inputStream, tempFile)
-                    || !tempFile.setLastModified(entry.getTime())
-                    || FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR | FileUtils.S_IWUSR
-                            | FileUtils.S_IRGRP | FileUtils.S_IXUSR | FileUtils.S_IXGRP
-                            | FileUtils.S_IXOTH | FileUtils.S_IROTH, -1, -1) != 0
-                    || !tempFile.renameTo(binaryFile)) {
-                // Failed to properly write file.
-                tempFile.delete();
-                throw new IOException("Couldn't create cached binary " + binaryFile + " in "
-                        + binaryDir);
-            }
-        } finally {
-            inputStream.close();
-        }
+    public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
+        final String cpuAbi = Build.CPU_ABI;
+        final String cpuAbi2 = Build.CPU_ABI2;
+        return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi,
+                cpuAbi2);
     }
 
     // Convenience method to call removeNativeBinariesFromDirLI(File)
diff --git a/services/java/com/android/server/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
similarity index 99%
rename from services/java/com/android/server/ProcessStats.java
rename to core/java/com/android/internal/os/ProcessStats.java
index f693ed1..ea5ce09 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.internal.os;
 
 import static android.os.Process.*;
 
@@ -182,7 +182,7 @@
 
         public String baseName;
         public String name;
-        int nameWidth;
+        public int nameWidth;
 
         public long base_uptime;
         public long rel_uptime;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ec186d..16336e0 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -474,7 +474,7 @@
         String args[] = {
             "--setuid=1000",
             "--setgid=1000",
-            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
+            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006",
             "--capabilities=130104352,130104352",
             "--runtime-init",
             "--nice-name=system_server",
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a9e5057..07430e7 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -27,7 +27,7 @@
     void expand();
     void collapse();
     void disable(int what, IBinder token, String pkg);
-    void setIcon(String slot, String iconPackage, int iconId, int iconLevel);
+    void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
     void setIconVisibility(String slot, boolean visible);
     void removeIcon(String slot);
     void topAppWindowChanged(boolean menuVisible);
diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java
index ae2cac2..3333c82 100644
--- a/core/java/com/android/internal/statusbar/StatusBarIcon.java
+++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java
@@ -19,42 +19,35 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-/**
- * @hide
- */
 public class StatusBarIcon implements Parcelable {
     public String iconPackage;
     public int iconId;
     public int iconLevel;
     public boolean visible = true;
     public int number;
+    public CharSequence contentDescription;
 
-    private StatusBarIcon() {
-    }
-
-    public StatusBarIcon(String iconPackage, int iconId, int iconLevel) {
-        this.iconPackage = iconPackage;
-        this.iconId = iconId;
-        this.iconLevel = iconLevel;
-    }
-
-    public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number) {
+    public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number,
+            CharSequence contentDescription) {
         this.iconPackage = iconPackage;
         this.iconId = iconId;
         this.iconLevel = iconLevel;
         this.number = number;
+        this.contentDescription = contentDescription;
     }
 
+    @Override
     public String toString() {
         return "StatusBarIcon(pkg=" + this.iconPackage + " id=0x" + Integer.toHexString(this.iconId)
                 + " level=" + this.iconLevel + " visible=" + visible
                 + " num=" + this.number + " )";
     }
 
+    @Override
     public StatusBarIcon clone() {
-        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel);
+        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel,
+                this.number, this.contentDescription);
         that.visible = this.visible;
-        that.number = this.number;
         return that;
     }
 
@@ -71,6 +64,7 @@
         this.iconLevel = in.readInt();
         this.visible = in.readInt() != 0;
         this.number = in.readInt();
+        this.contentDescription = in.readCharSequence();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -79,6 +73,7 @@
         out.writeInt(this.iconLevel);
         out.writeInt(this.visible ? 1 : 0);
         out.writeInt(this.number);
+        out.writeCharSequence(this.contentDescription);
     }
 
     public int describeContents() {
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
similarity index 60%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/com/android/internal/textservice/ISpellCheckerService.aidl
index eaf7bde..ff00492 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package com.android.internal.textservice;
 
-#include <input/InputWindow.h>
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
 
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+/**
+ * Public interface to the global spell checker.
+ * @hide
+ */
+interface ISpellCheckerService {
+    ISpellCheckerSession getISpellCheckerSession(
+            String locale, ISpellCheckerSessionListener listener);
+}
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
index eaf7bde..79e43510c0 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package com.android.internal.textservice;
 
-#include <input/InputWindow.h>
+import android.view.textservice.TextInfo;
 
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+/**
+ * @hide
+ */
+oneway interface ISpellCheckerSession {
+    void getSuggestionsMultiple(
+            in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
+    void cancel();
+}
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl
index eaf7bde..796b06e 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl
@@ -14,19 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package com.android.internal.textservice;
 
-#include <input/InputWindow.h>
+import android.view.textservice.SuggestionsInfo;
 
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+/**
+ * @hide
+ */
+oneway interface ISpellCheckerSessionListener {
+    void onGetSuggestions(in SuggestionsInfo[] results);
+}
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
new file mode 100644
index 0000000..2a045e3
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.content.ComponentName;
+import android.view.textservice.SpellCheckerInfo;
+
+/**
+ * Interface to the text service manager.
+ * @hide
+ */
+interface ITextServicesManager {
+    SpellCheckerInfo getCurrentSpellChecker(String locale);
+    oneway void getSpellCheckerService(in SpellCheckerInfo info, in String locale,
+            in ITextServicesSessionListener tsListener,
+            in ISpellCheckerSessionListener scListener);
+    oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
+    SpellCheckerInfo[] getEnabledSpellCheckers();
+}
diff --git a/services/jni/com_android_server_InputWindow.h b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
similarity index 62%
copy from services/jni/com_android_server_InputWindow.h
copy to core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
index eaf7bde..ecb6cd0 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
+package com.android.internal.textservice;
 
-#include <input/InputWindow.h>
+import com.android.internal.textservice.ISpellCheckerSession;
 
-#include "JNIHelp.h"
-#include "jni.h"
+import android.view.textservice.SpellCheckerInfo;
 
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+/**
+ * Interface to the text service session.
+ * @hide
+ */
+interface ITextServicesSessionListener {
+    oneway void onServiceConnected(in ISpellCheckerSession spellCheckerSession);
+}
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index b754d94..9ecd29f 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -40,6 +40,10 @@
 
     /** Non system protocols */
     public static final int BASE_WIFI                                               = 0x00020000;
+    public static final int BASE_WIFI_WATCHDOG                                      = 0x00021000;
+    public static final int BASE_WIFI_P2P_MANAGER                                   = 0x00022000;
+    public static final int BASE_WIFI_P2P_SERVICE                                   = 0x00023000;
+    public static final int BASE_WIFI_MONITOR                                       = 0x00024000;
     public static final int BASE_DHCP                                               = 0x00030000;
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 812f92b..ce0299c 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -68,5 +68,5 @@
     boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
     boolean switchToLastInputMethod(in IBinder token);
     boolean setInputMethodEnabled(String id, boolean enabled);
-    boolean setAdditionalInputMethodSubtypes(in IBinder token, in InputMethodSubtype[] subtypes);
+    boolean setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 9c06d69..06f753f 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -48,6 +48,7 @@
     private boolean mMaxItemsSet;
     private boolean mStrictWidthLimit;
     private boolean mWidthLimitSet;
+    private boolean mExpandedActionViewsExclusive;
 
     private int mMinCellSize;
 
@@ -124,6 +125,10 @@
         mMaxItemsSet = true;
     }
 
+    public void setExpandedActionViewsExclusive(boolean isExclusive) {
+        mExpandedActionViewsExclusive = isExclusive;
+    }
+
     @Override
     public MenuView getMenuView(ViewGroup root) {
         MenuView result = super.getMenuView(root);
@@ -326,6 +331,11 @@
             } else {
                 hasOverflow = true;
             }
+            if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) {
+                // Overflow everything if we have an expanded action view and we're
+                // space constrained.
+                maxActions = 0;
+            }
         }
 
         // Reserve a spot for the overflow item if needed.
@@ -544,6 +554,17 @@
             }
 
             setCallback(mPopupPresenterCallback);
+
+            boolean preserveIconSpacing = false;
+            final int count = subMenu.size();
+            for (int i = 0; i < count; i++) {
+                MenuItem childItem = subMenu.getItem(i);
+                if (childItem.isVisible() && childItem.getIcon() != null) {
+                    preserveIconSpacing = true;
+                    break;
+                }
+            }
+            setForceShowIcon(preserveIconSpacing);
         }
 
         @Override
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index bf2965b..bff621c 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -36,8 +36,8 @@
 
     private boolean mReserveOverflow;
     private ActionMenuPresenter mPresenter;
-    private boolean mUpdateContentsBeforeMeasure;
     private boolean mFormatItems;
+    private int mFormatItemsWidth;
     private int mMinCellSize;
     private int mMeasuredExtraWidth;
 
@@ -71,19 +71,21 @@
     }
 
     @Override
-    public void requestLayout() {
-        // Layout can influence how many action items fit.
-        mUpdateContentsBeforeMeasure = true;
-        super.requestLayout();
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // If we've been given an exact size to match, apply special formatting during layout.
+        final boolean wasFormatted = mFormatItems;
         mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
-        if (mUpdateContentsBeforeMeasure && mMenu != null) {
+
+        if (wasFormatted != mFormatItems) {
+            mFormatItemsWidth = 0; // Reset this when switching modes
+        }
+
+        // Special formatting can change whether items can fit as action buttons.
+        // Kick the menu and update presenters when this changes.
+        final int widthSize = MeasureSpec.getMode(widthMeasureSpec);
+        if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
+            mFormatItemsWidth = widthSize;
             mMenu.onItemsChanged(true);
-            mUpdateContentsBeforeMeasure = false;
         }
 
         if (mFormatItems) {
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index 56128d4..d1b1dae 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -179,8 +179,10 @@
         @Override
         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
             mOpenSubMenuId = 0;
-            mOpenSubMenu.dismiss();
-            mOpenSubMenu = null;
+            if (mOpenSubMenu != null) {
+                mOpenSubMenu.dismiss();
+                mOpenSubMenu = null;
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 0c3c605..a1e16d4 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -22,6 +22,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.ImageView;
@@ -50,6 +51,8 @@
     
     private LayoutInflater mInflater;
 
+    private boolean mForceShowIcon;
+
     public ListMenuItemView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs);
     
@@ -99,6 +102,10 @@
         setEnabled(itemData.isEnabled());
     }
 
+    public void setForceShowIcon(boolean forceShow) {
+        mPreserveIconSpacing = mForceShowIcon = forceShow;
+    }
+
     public void setTitle(CharSequence title) {
         if (title != null) {
             mTitleView.setText(title);
@@ -189,12 +196,12 @@
     }
     
     public void setIcon(Drawable icon) {
-        final boolean showIcon = mItemData.shouldShowIcon();
+        final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon;
         if (!showIcon && !mPreserveIconSpacing) {
             return;
         }
         
-        if (mIconView == null && icon == null) {
+        if (mIconView == null && icon == null && !mPreserveIconSpacing) {
             return;
         }
         
@@ -213,6 +220,19 @@
         }
     }
     
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mIconView != null && mPreserveIconSpacing) {
+            // Enforce minimum icon spacing
+            ViewGroup.LayoutParams lp = getLayoutParams();
+            LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+            if (lp.height > 0 && iconLp.width <= 0) {
+                iconLp.width = lp.height;
+            }
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
     private void insertIconView() {
         LayoutInflater inflater = getInflater();
         mIconView = (ImageView) inflater.inflate(com.android.internal.R.layout.list_menu_item_icon,
@@ -241,7 +261,7 @@
     }
 
     public boolean showsIcon() {
-        return false;
+        return mForceShowIcon;
     }
     
     private LayoutInflater getInflater() {
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index b0b49213..19cbe25 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.util.Log;
 import android.util.SparseArray;
 import android.view.ActionProvider;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -47,9 +48,11 @@
  * standard menu UI.
  */
 public class MenuBuilder implements Menu {
-    private static final String LOGTAG = "MenuBuilder";
+    private static final String TAG = "MenuBuilder";
 
     private static final String PRESENTER_KEY = "android:menu:presenters";
+    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
+    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
 
     private static final int[]  sCategoryToOrder = new int[] {
         1, /* No category */
@@ -308,6 +311,67 @@
         dispatchRestoreInstanceState(state);
     }
 
+    public void saveActionViewStates(Bundle outStates) {
+        SparseArray<Parcelable> viewStates = null;
+
+        final int itemCount = size();
+        for (int i = 0; i < itemCount; i++) {
+            final MenuItem item = getItem(i);
+            final View v = item.getActionView();
+            if (v != null && v.getId() != View.NO_ID) {
+                if (viewStates == null) {
+                    viewStates = new SparseArray<Parcelable>();
+                }
+                v.saveHierarchyState(viewStates);
+                if (item.isActionViewExpanded()) {
+                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
+                }
+            }
+            if (item.hasSubMenu()) {
+                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+                subMenu.saveActionViewStates(outStates);
+            }
+        }
+
+        if (viewStates != null) {
+            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
+        }
+    }
+
+    public void restoreActionViewStates(Bundle states) {
+        if (states == null) {
+            return;
+        }
+
+        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
+                getActionViewStatesKey());
+
+        final int itemCount = size();
+        for (int i = 0; i < itemCount; i++) {
+            final MenuItem item = getItem(i);
+            final View v = item.getActionView();
+            if (v != null && v.getId() != View.NO_ID) {
+                v.restoreHierarchyState(viewStates);
+            }
+            if (item.hasSubMenu()) {
+                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+                subMenu.restoreActionViewStates(states);
+            }
+        }
+
+        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
+        if (expandedId > 0) {
+            MenuItem itemToExpand = findItem(expandedId);
+            if (itemToExpand != null) {
+                itemToExpand.expandActionView();
+            }
+        }
+    }
+
+    protected String getActionViewStatesKey() {
+        return ACTION_VIEW_STATES_KEY;
+    }
+
     public void setCallback(Callback cb) {
         mCallback = cb;
     }
@@ -799,7 +863,7 @@
         if (itemImpl == null || !itemImpl.isEnabled()) {
             return false;
         }
-        
+
         boolean invoked = itemImpl.invoke();
 
         if (itemImpl.hasCollapsibleActionView()) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 0a7313c..8b53bb8 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -320,11 +320,6 @@
     }
 
     void setSubMenu(SubMenuBuilder subMenu) {
-        if ((mMenu != null) && (mMenu instanceof SubMenu)) {
-            throw new UnsupportedOperationException(
-            "Attempt to add a sub-menu to a sub-menu.");
-        }
-        
         mSubMenu = subMenu;
         
         subMenu.setHeaderTitle(getTitle());
@@ -558,6 +553,9 @@
     public MenuItem setActionView(View view) {
         mActionView = view;
         mActionProvider = null;
+        if (view != null && view.getId() == View.NO_ID && mId > 0) {
+            view.setId(mId);
+        }
         mMenu.onItemActionRequestChanged(this);
         return this;
     }
@@ -565,7 +563,7 @@
     public MenuItem setActionView(int resId) {
         final Context context = mMenu.getContext();
         final LayoutInflater inflater = LayoutInflater.from(context);
-        setActionView(inflater.inflate(resId, new LinearLayout(context)));
+        setActionView(inflater.inflate(resId, new LinearLayout(context), false));
         return this;
     }
 
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 4ecc828..6265618 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -19,15 +19,16 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Parcelable;
-import android.util.DisplayMetrics;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
 import android.widget.ListAdapter;
 import android.widget.ListPopupWindow;
 import android.widget.PopupWindow;
@@ -58,6 +59,10 @@
 
     private Callback mPresenterCallback;
 
+    boolean mForceShowIcon;
+
+    private ViewGroup mMeasureParent;
+
     public MenuPopupHelper(Context context, MenuBuilder menu) {
         this(context, menu, null, false);
     }
@@ -86,6 +91,10 @@
         mAnchorView = anchor;
     }
 
+    public void setForceShowIcon(boolean forceShow) {
+        mForceShowIcon = forceShow;
+    }
+
     public void show() {
         if (!tryShow()) {
             throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
@@ -170,7 +179,10 @@
                 itemType = positionType;
                 itemView = null;
             }
-            itemView = adapter.getView(i, itemView, null);
+            if (mMeasureParent == null) {
+                mMeasureParent = new FrameLayout(mContext);
+            }
+            itemView = adapter.getView(i, itemView, mMeasureParent);
             itemView.measure(widthMeasureSpec, heightMeasureSpec);
             width = Math.max(width, itemView.getMeasuredWidth());
         }
@@ -228,6 +240,18 @@
         if (subMenu.hasVisibleItems()) {
             MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
             subPopup.setCallback(mPresenterCallback);
+
+            boolean preserveIconSpacing = false;
+            final int count = subMenu.size();
+            for (int i = 0; i < count; i++) {
+                MenuItem childItem = subMenu.getItem(i);
+                if (childItem.isVisible() && childItem.getIcon() != null) {
+                    preserveIconSpacing = true;
+                    break;
+                }
+            }
+            subPopup.setForceShowIcon(preserveIconSpacing);
+
             if (subPopup.tryShow()) {
                 if (mPresenterCallback != null) {
                     mPresenterCallback.onOpenSubMenu(subMenu);
@@ -293,6 +317,9 @@
             }
 
             MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+            if (mForceShowIcon) {
+                ((ListMenuItemView) convertView).setForceShowIcon(true);
+            }
             itemView.initialize(getItem(position), 0);
             return convertView;
         }
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index fb1cd5e..92acf8c 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -121,4 +121,13 @@
     public boolean collapseItemActionView(MenuItemImpl item) {
         return mParentMenu.collapseItemActionView(item);
     }
+
+    @Override
+    public String getActionViewStatesKey() {
+        final int itemId = mItem != null ? mItem.getItemId() : 0;
+        if (itemId == 0) {
+            return null;
+        }
+        return super.getActionViewStatesKey() + ":" + itemId;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 595753a..468f28e 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -42,6 +42,7 @@
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.CollapsibleActionView;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -285,8 +286,11 @@
     public void setSplitActionBar(boolean splitActionBar) {
         if (mSplitActionBar != splitActionBar) {
             if (mMenuView != null) {
+                final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
+                if (oldParent != null) {
+                    oldParent.removeView(mMenuView);
+                }
                 if (splitActionBar) {
-                    removeView(mMenuView);
                     if (mSplitView != null) {
                         mSplitView.addView(mMenuView);
                     }
@@ -332,7 +336,10 @@
         MenuBuilder builder = (MenuBuilder) menu;
         mOptionsMenu = builder;
         if (mMenuView != null) {
-            removeView(mMenuView);
+            final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
+            if (oldParent != null) {
+                oldParent.removeView(mMenuView);
+            }
         }
         if (mActionMenuPresenter == null) {
             mActionMenuPresenter = new ActionMenuPresenter();
@@ -345,11 +352,19 @@
         final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                 LayoutParams.MATCH_PARENT);
         if (!mSplitActionBar) {
+            mActionMenuPresenter.setExpandedActionViewsExclusive(
+                    getResources().getBoolean(
+                    com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
             builder.addMenuPresenter(mActionMenuPresenter);
             builder.addMenuPresenter(mExpandedMenuPresenter);
             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
+            final ViewGroup oldParent = (ViewGroup) menuView.getParent();
+            if (oldParent != null && oldParent != this) {
+                oldParent.removeView(menuView);
+            }
             addView(menuView, layoutParams);
         } else {
+            mActionMenuPresenter.setExpandedActionViewsExclusive(false);
             // Allow full screen width in split mode.
             mActionMenuPresenter.setWidthLimit(
                     getContext().getResources().getDisplayMetrics().widthPixels, true);
@@ -361,6 +376,10 @@
             builder.addMenuPresenter(mExpandedMenuPresenter);
             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
             if (mSplitView != null) {
+                final ViewGroup oldParent = (ViewGroup) menuView.getParent();
+                if (oldParent != null && oldParent != mSplitView) {
+                    oldParent.removeView(menuView);
+                }
                 mSplitView.addView(menuView, layoutParams);
             } else {
                 // We'll add this later if we missed it this time.
@@ -370,6 +389,19 @@
         mMenuView = menuView;
     }
 
+    public boolean hasExpandedActionView() {
+        return mExpandedMenuPresenter != null &&
+                mExpandedMenuPresenter.mCurrentExpandedItem != null;
+    }
+
+    public void collapseActionView() {
+        final MenuItemImpl item = mExpandedMenuPresenter == null ? null :
+                mExpandedMenuPresenter.mCurrentExpandedItem;
+        if (item != null) {
+            item.collapseActionView();
+        }
+    }
+
     public void setCustomNavigationView(View view) {
         final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
         if (mCustomNavView != null && showCustom) {
@@ -434,22 +466,40 @@
         }
     }
 
+    public void setHomeButtonEnabled(boolean enable) {
+        mHomeLayout.setEnabled(enable);
+        // Make sure the home button has an accurate content description for accessibility.
+        if (!enable) {
+            mHomeLayout.setContentDescription(null);
+        } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+            mHomeLayout.setContentDescription(mContext.getResources().getText(
+                    R.string.action_bar_up_description));
+        } else {
+            mHomeLayout.setContentDescription(mContext.getResources().getText(
+                    R.string.action_bar_home_description));
+        }
+    }
+
     public void setDisplayOptions(int options) {
         final int flagsChanged = options ^ mDisplayOptions;
         mDisplayOptions = options;
 
-        if ((flagsChanged & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
-            final boolean disableHome = (options & ActionBar.DISPLAY_DISABLE_HOME) != 0;
-            mHomeLayout.setEnabled(!disableHome);
-        }
-
         if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
             final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
             final int vis = showHome ? VISIBLE : GONE;
             mHomeLayout.setVisibility(vis);
 
             if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                mHomeLayout.setUp((options & ActionBar.DISPLAY_HOME_AS_UP) != 0);
+                final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
+                mHomeLayout.setUp(setUp);
+
+                // Showing home as up implicitly enables interaction with it.
+                // In honeycomb it was always enabled, so make this transition
+                // a bit easier for developers in the common case.
+                // (It would be silly to show it as up without responding to it.)
+                if (setUp) {
+                    setHomeButtonEnabled(true);
+                }
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
@@ -487,7 +537,7 @@
         }
 
         // Make sure the home button has an accurate content description for accessibility.
-        if ((options & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
+        if (!mHomeLayout.isEnabled()) {
             mHomeLayout.setContentDescription(null);
         } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
             mHomeLayout.setContentDescription(mContext.getResources().getText(
@@ -1254,7 +1304,7 @@
         @Override
         public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
             mExpandedActionView = item.getActionView();
-            mExpandedHomeLayout.setIcon(item.getIcon());
+            mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
             mCurrentExpandedItem = item;
             if (mExpandedActionView.getParent() != ActionBarView.this) {
                 addView(mExpandedActionView);
@@ -1269,11 +1319,22 @@
             if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
             requestLayout();
             item.setActionViewExpanded(true);
+
+            if (mExpandedActionView instanceof CollapsibleActionView) {
+                ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
+            }
+
             return true;
         }
 
         @Override
         public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+            // Do this before detaching the actionview from the hierarchy, in case
+            // it needs to dismiss the soft keyboard, etc.
+            if (mExpandedActionView instanceof CollapsibleActionView) {
+                ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
+            }
+
             removeView(mExpandedActionView);
             removeView(mExpandedHomeLayout);
             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
@@ -1300,6 +1361,7 @@
             mCurrentExpandedItem = null;
             requestLayout();
             item.setActionViewExpanded(false);
+
             return true;
         }
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d034eab..bbddf29 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -114,6 +114,23 @@
     private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false);
     private static FileObserver sPasswordObserver;
 
+    private static class PasswordFileObserver extends FileObserver {
+        public PasswordFileObserver(String path, int mask) {
+            super(path, mask);
+        }
+
+        @Override
+        public void onEvent(int event, String path) {
+            if (LOCK_PATTERN_FILE.equals(path)) {
+                Log.d(TAG, "lock pattern file changed");
+                sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
+            } else if (LOCK_PASSWORD_FILE.equals(path)) {
+                Log.d(TAG, "lock password file changed");
+                sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
+            }
+        }
+    }
+
     public DevicePolicyManager getDevicePolicyManager() {
         if (mDevicePolicyManager == null) {
             mDevicePolicyManager =
@@ -143,18 +160,7 @@
             sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
             int fileObserverMask = FileObserver.CLOSE_WRITE | FileObserver.DELETE |
                     FileObserver.MOVED_TO | FileObserver.CREATE;
-            sPasswordObserver = new FileObserver(dataSystemDirectory, fileObserverMask) {
-                    @Override
-                    public void onEvent(int event, String path) {
-                        if (LOCK_PATTERN_FILE.equals(path)) {
-                            Log.d(TAG, "lock pattern file changed");
-                            sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
-                        } else if (LOCK_PASSWORD_FILE.equals(path)) {
-                            Log.d(TAG, "lock password file changed");
-                            sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
-                        }
-                    }
-                };
+            sPasswordObserver = new PasswordFileObserver(dataSystemDirectory, fileObserverMask);
             sPasswordObserver.startWatching();
         }
     }
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index 3070e3e..fb33748 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -29,7 +29,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewAncestor;
+import android.view.ViewRootImpl;
 import com.android.internal.R;
 
 public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener {
@@ -150,7 +150,7 @@
                 KeyEvent event = events[i];
                 event = KeyEvent.changeFlags(event, event.getFlags()
                         | KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
-                handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY, event));
+                handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY, event));
             }
         }
     }
@@ -158,11 +158,11 @@
     public void sendDownUpKeyEvents(int keyEventCode) {
         long eventTime = SystemClock.uptimeMillis();
         Handler handler = mTargetView.getHandler();
-        handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME,
+        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
                 new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyEventCode, 0, 0,
                         KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                     KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
-        handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME,
+        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
                 new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0,
                         KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                         KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 04bb689..94990b6 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -45,7 +45,7 @@
  */
 public class MultiWaveView extends View {
     private static final String TAG = "MultiWaveView";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     // Wave state machine
     private static final int STATE_IDLE = 0;
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 2871073..59bef92 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -16,11 +16,15 @@
 
 package com.android.server;
 
+import android.os.SystemProperties;
+import android.util.Log;
 import dalvik.system.SocketTagger;
+import libcore.io.IoUtils;
+
 import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.math.BigInteger;
 import java.net.SocketException;
 import java.nio.charset.Charsets;
 
@@ -28,12 +32,19 @@
  * Assigns tags to sockets for traffic stats.
  */
 public final class NetworkManagementSocketTagger extends SocketTagger {
+    private static final String TAG = "NetworkManagementSocketTagger";
+    private static final boolean LOGD = false;
 
-    private static final boolean LOGI = false;
-    private static final boolean ENABLE_TAGGING = false;
+    /**
+     * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth
+     * controls have been enabled.
+     */
+    // TODO: remove when always enabled, or once socket tagging silently fails.
+    public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled";
 
     private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
-        @Override protected SocketTags initialValue() {
+        @Override
+        protected SocketTags initialValue() {
             return new SocketTags();
         }
     };
@@ -46,15 +57,20 @@
         threadSocketTags.get().statsTag = tag;
     }
 
+    public static int getThreadSocketStatsTag() {
+        return threadSocketTags.get().statsTag;
+    }
+
     public static void setThreadSocketStatsUid(int uid) {
         threadSocketTags.get().statsUid = uid;
     }
 
-    @Override public void tag(FileDescriptor fd) throws SocketException {
+    @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);
+        if (LOGD) {
+            Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=" + options.statsTag
+                    + ", statsUid=" + options.statsUid);
         }
         try {
             // TODO: skip tagging when options would be no-op
@@ -82,9 +98,10 @@
         internalModuleCtrl(cmd);
     }
 
-    @Override public void untag(FileDescriptor fd) throws SocketException {
-        if (LOGI) {
-            System.logI("untagSocket(" + fd.getInt$() + ")");
+    @Override
+    public void untag(FileDescriptor fd) throws SocketException {
+        if (LOGD) {
+            Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
         }
         try {
             unTagSocketFd(fd);
@@ -125,31 +142,22 @@
      *
      */
     private void internalModuleCtrl(String cmd) throws IOException {
-        if (!ENABLE_TAGGING) return;
+        if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
 
-        final FileOutputStream procOut;
-        // TODO: Use something like
-        //  android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
-        // to see if tagging should happen or not.
+        // TODO: migrate to native library for tagging commands
+        FileOutputStream procOut = null;
         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();
+            IoUtils.closeQuietly(procOut);
         }
     }
 
     /**
      * 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}.
+     * avoid using {@link BigInteger}.
      */
     public static String tagToKernel(int tag) {
         // TODO: eventually write in hex, since that's what proc exports
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 58e7c8d..6e73889 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -29,6 +29,7 @@
 	ActivityManager.cpp \
 	AndroidRuntime.cpp \
 	Time.cpp \
+	com_android_internal_content_NativeLibraryHelper.cpp \
 	com_google_android_gles_jni_EGLImpl.cpp \
 	com_google_android_gles_jni_GLImpl.cpp.arm \
 	android_app_NativeActivity.cpp \
@@ -139,13 +140,13 @@
 	android_bluetooth_common.cpp \
 	android_bluetooth_BluetoothAudioGateway.cpp \
 	android_bluetooth_BluetoothSocket.cpp \
+	android_bluetooth_c.c \
 	android_server_BluetoothService.cpp \
 	android_server_BluetoothEventLoop.cpp \
 	android_server_BluetoothA2dpService.cpp \
 	android_server_Watchdog.cpp \
 	android_ddm_DdmHandleNativeHeap.cpp \
 	com_android_internal_os_ZygoteInit.cpp \
-	com_android_internal_graphics_NativeUtils.cpp \
 	android_backup_BackupDataInput.cpp \
 	android_backup_BackupDataOutput.cpp \
 	android_backup_FileBackupHelperBase.cpp \
@@ -178,6 +179,7 @@
 	external/icu4c/common \
 	external/jpeg \
 	external/harfbuzz/src \
+	external/zlib \
 	frameworks/opt/emoji \
 	libcore/include
 
@@ -211,6 +213,7 @@
 	libnfc_ndef \
 	libusbhost \
 	libharfbuzz \
+	libz \
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a61217a..9e46d80 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -115,7 +115,6 @@
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
 extern int register_android_graphics_PixelFormat(JNIEnv* env);
-extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
 extern int register_android_view_Display(JNIEnv* env);
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
@@ -176,6 +175,7 @@
 extern int register_android_content_res_ObbScanner(JNIEnv* env);
 extern int register_android_content_res_Configuration(JNIEnv* env);
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
+extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -623,27 +623,11 @@
     }
 
     /* enable debugging; set suspend=y to pause during VM init */
-#ifdef HAVE_ANDROID_OS
     /* use android ADB transport */
     opt.optionString =
         "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
-#else
-    /* use TCP socket; address=0 means start at port 8000 and probe up */
-    LOGI("Using TCP socket for JDWP\n");
-    opt.optionString =
-        "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
-#endif
     mOptions.add(opt);
 
-    char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
-    property_get("dalvik.vm.deadlock-predict", propBuf, "");
-    if (strlen(propBuf) > 0) {
-        strcpy(enableDPBuf, "-Xdeadlockpredict:");
-        strcat(enableDPBuf, propBuf);
-        opt.optionString = enableDPBuf;
-        mOptions.add(opt);
-    }
-
     LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
     if (checkJni) {
         /* extended JNI checking */
@@ -1154,7 +1138,6 @@
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
-    REG_JNI(register_com_android_internal_graphics_NativeUtils),
 
     REG_JNI(register_android_database_CursorWindow),
     REG_JNI(register_android_database_SQLiteCompiledSql),
@@ -1217,6 +1200,7 @@
     REG_JNI(register_android_content_res_Configuration),
 
     REG_JNI(register_android_animation_PropertyValuesHolder),
+    REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
 };
 
 /*
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 258ffa5..ea35006 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -116,7 +116,7 @@
                         bool forcePurgeable = false) {
     int sampleSize = 1;
     SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
-    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
+    SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
     bool doDither = true;
     bool isMutable = false;
     bool isPurgeable = forcePurgeable ||
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 942aa8a1..682c3c4 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -799,24 +799,6 @@
                 x, y, flags, paint);
     }
 
-    static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
-                                      jcharArray text, int index, int count,
-                                      jfloat x, jfloat y, int flags, SkPaint* paint) {
-        jchar* textArray = env->GetCharArrayElements(text, NULL);
-        drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
-        env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
-    }
-
-    static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject,
-                                          SkCanvas* canvas, jstring text,
-                                          int start, int end,
-                                          jfloat x, jfloat y, int flags, SkPaint* paint) {
-
-        const jchar* textArray = env->GetStringChars(text, NULL);
-        drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
-        env->ReleaseStringChars(text, textArray);
-    }
-
     static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
             jfloat x, jfloat y, int flags, SkPaint* paint) {
         // TODO: need to suppress this code after the GL renderer is modified for not
@@ -833,16 +815,6 @@
         paint->setTextEncoding(oldEncoding);
     }
 
-    static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
-                                         jcharArray glyphs, int index, int count,
-                                         jfloat x, jfloat y, int flags, SkPaint* paint) {
-        jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL);
-
-        doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint);
-
-        env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT);
-    }
-
     static void drawTextRun___CIIIIFFIPaint(
         JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
         int count, int contextIndex, int contextCount,
@@ -1044,12 +1016,6 @@
         (void*) SkCanvasGlue::drawText___CIIFFIPaint},
     {"native_drawText","(ILjava/lang/String;IIFFII)V",
         (void*) SkCanvasGlue::drawText__StringIIFFIPaint},
-    {"native_drawTextWithGlyphs","(I[CIIFFII)V",
-        (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint},
-    {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V",
-        (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint},
-    {"native_drawGlyphs","(I[CIIFFII)V",
-        (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint},
     {"native_drawTextRun","(I[CIIIIFFII)V",
         (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint},
     {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V",
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 6a13876..30fe298 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -323,9 +323,7 @@
 
 void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font,
         FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count,
-        size_t contextCount, int dirFlags) {
-    bool isRTL = dirFlags & 0x1;
-
+        size_t contextCount, bool isRTL) {
     font->klass = &harfbuzzSkiaClass;
     font->userData = 0;
     // The values which harfbuzzSkiaClass returns are already scaled to
@@ -374,10 +372,10 @@
 
 void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font,
         FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count,
-        size_t contextCount, int dirFlags) {
+        size_t contextCount, bool isRTL) {
     // Setup Harfbuzz Shaper
     setupShaperItem(shaperItem, font, fontData, paint, chars, start, count,
-            contextCount, dirFlags);
+            contextCount, isRTL);
 
     // Shape
     resetGlyphArrays(shaperItem);
@@ -430,7 +428,7 @@
                     LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d",
                             forceLTR, forceRTL);
 #endif
-            computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
+            computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL,
                     outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
             if (forceRTL && *outGlyphsCount > 1) {
@@ -451,10 +449,15 @@
                     LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir);
 #endif
                     if (rc == 1 || !U_SUCCESS(status)) {
+                        bool isRTL = (paraDir == 1);
+#if DEBUG_GLYPHS
+                        LOGD("computeValuesWithHarfbuzz -- processing SINGLE run "
+                                "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
+#endif
                         computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount,
-                                dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
+                                isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
-                        if (dirFlags == 1 && *outGlyphsCount > 1) {
+                        if (isRTL && *outGlyphsCount > 1) {
                             reverseGlyphArray(*outGlyphs, *outGlyphsCount);
                         }
                     } else {
@@ -485,14 +488,14 @@
 
                             lengthRun = endRun - startRun;
 
-                            int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
+                            bool isRTL = (runDir == UBIDI_RTL);
                             jfloat runTotalAdvance = 0;
 #if DEBUG_GLYPHS
-                            LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d",
-                                    startRun, lengthRun, newFlags);
+                            LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d isRTL=%d",
+                                    startRun, lengthRun, isRTL);
 #endif
                             computeRunValuesWithHarfbuzz(paint, chars, startRun,
-                                    lengthRun, contextCount, newFlags,
+                                    lengthRun, contextCount, isRTL,
                                     outAdvances, &runTotalAdvance,
                                     &runGlyphs, &runGlyphsCount);
 
@@ -506,7 +509,7 @@
                                 LOGD("                          -- glyphs[%d]=%d", j, runGlyphs[j]);
                             }
 #endif
-                            glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags));
+                            glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, isRTL));
                         }
                         *outGlyphs = new jchar[*outGlyphsCount];
 
@@ -528,13 +531,15 @@
                 ubidi_close(bidi);
             } else {
                 // Cannot run BiDi, just consider one Run
+                bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL);
 #if DEBUG_GLYPHS
-                LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering only one Run");
+                LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run "
+                        "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
 #endif
-                computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
+                computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL,
                         outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
-                if (dirFlags == 1 && *outGlyphsCount > 1) {
+                if (isRTL && *outGlyphsCount > 1) {
                     reverseGlyphArray(*outGlyphs, *outGlyphsCount);
                 }
             }
@@ -545,17 +550,15 @@
 }
 
 void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
-        size_t start, size_t count, size_t contextCount, int dirFlags,
+        size_t start, size_t count, size_t contextCount, bool isRTL,
         jfloat* outAdvances, jfloat* outTotalAdvance,
         jchar** outGlyphs, size_t* outGlyphsCount) {
 
-    bool isRTL = dirFlags & 0x1;
-
     HB_ShaperItem shaperItem;
     HB_FontRec font;
     FontData fontData;
     shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count,
-            contextCount, dirFlags);
+            contextCount, isRTL);
 
 #if DEBUG_GLYPHS
     LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs,
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 690caac..10dee87 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -128,11 +128,11 @@
 
     static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
             SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
-            int dirFlags);
+            bool isRTL);
 
     static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
             SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
-            int dirFlags);
+            bool isRTL);
 
     static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
             size_t count, size_t contextCount, int dirFlags,
@@ -179,7 +179,7 @@
     static void resetGlyphArrays(HB_ShaperItem* shaperItem);
 
     static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
-            size_t count, size_t contextCount, int dirFlags,
+            size_t count, size_t contextCount, bool isRTL,
             jfloat* outAdvances, jfloat* outTotalAdvance,
             jchar** outGlyphs, size_t* outGlyphsCount);
 }; // TextLayoutCacheValue
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
index cb742a3..29c9c2d 100755
--- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
+++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BluetoothAudioGateway.cpp"
 
 #include "android_bluetooth_common.h"
+#include "android_bluetooth_c.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
 #include "jni.h"
@@ -491,7 +492,8 @@
     }
 
     laddr.rc_family = AF_BLUETOOTH;
-    memcpy(&laddr.rc_bdaddr, BDADDR_ANY, sizeof(bdaddr_t));
+    bdaddr_t any = android_bluetooth_bdaddr_any();
+    memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t));
     laddr.rc_channel = channel;
 
     if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index d09c4e9..4c84324 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BluetoothSocket.cpp"
 
 #include "android_bluetooth_common.h"
+#include "android_bluetooth_c.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
 #include "utils/Log.h"
@@ -245,7 +246,7 @@
     jint type;
     socklen_t addr_sz;
     struct sockaddr *addr;
-    bdaddr_t bdaddr = *BDADDR_ANY;
+    bdaddr_t bdaddr = android_bluetooth_bdaddr_any();
     struct asocket *s = get_socketData(env, obj);
 
     if (!s)
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml b/core/jni/android_bluetooth_c.c
old mode 100644
new mode 100755
similarity index 63%
copy from packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml
copy to core/jni/android_bluetooth_c.c
index f9bba2a..b4c6727
--- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml
+++ b/core/jni/android_bluetooth_c.c
@@ -1,7 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
+/*
 ** Copyright 2011, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,8 +13,19 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
--->
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/recents_thumbnail_bg_press"/>
-    <item android:drawable="@drawable/recents_thumbnail_bg_press"/>
-</transition>
+
+#ifdef HAVE_BLUETOOTH
+
+#include "android_bluetooth_c.h"
+
+/*
+ * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
+ * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
+ * is not valid C++ code.
+ */
+bdaddr_t android_bluetooth_bdaddr_any(void)
+{
+  bdaddr_t any = *BDADDR_ANY;
+  return any;
+}
+#endif
diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h
new file mode 100644
index 0000000..e890244
--- /dev/null
+++ b/core/jni/android_bluetooth_c.h
@@ -0,0 +1,39 @@
+/*
+** Copyright 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_BLUETOOTH_C_H
+#define ANDROID_BLUETOOTH_C_H
+#ifdef HAVE_BLUETOOTH
+
+#include <bluetooth/bluetooth.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
+ * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
+ * is not valid C++ code.
+ */
+bdaddr_t android_bluetooth_bdaddr_any(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*HAVE_BLUETOOTH*/
+#endif /*ANDROID_BLUETOOTH_C_H*/
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4687ee0..3328fc8 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -38,6 +38,12 @@
     jfieldID    surfaceTexture;
     jfieldID    facing;
     jfieldID    orientation;
+    jfieldID    face_rectangle;
+    jfieldID    face_score;
+    jfieldID    rect_left;
+    jfieldID    rect_top;
+    jfieldID    rect_right;
+    jfieldID    rect_bottom;
     jmethodID   post_event;
 };
 
@@ -708,6 +714,35 @@
     }
 }
 
+static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz,
+        jint type, jobjectArray face)
+{
+    LOGV("startFaceDetection");
+    JNICameraContext* context;
+    sp<Camera> camera = get_native_camera(env, thiz, &context);
+    if (camera == 0) return;
+
+    status_t rc = camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, type, 0);
+    if (rc == BAD_VALUE) {
+        char msg[64];
+        snprintf(msg, sizeof(msg), "invalid face detection type=%d", type);
+        jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+    } else if (rc != NO_ERROR) {
+        jniThrowRuntimeException(env, "start face detection failed");
+    }
+}
+
+static void android_hardware_Camera_stopFaceDetection(JNIEnv *env, jobject thiz)
+{
+    LOGV("stopFaceDetection");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) return;
+
+    if (camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0) != NO_ERROR) {
+        jniThrowRuntimeException(env, "stop face detection failed");
+    }
+}
+
 //-------------------------------------------------
 
 static JNINativeMethod camMethods[] = {
@@ -732,7 +767,7 @@
   { "startPreview",
     "()V",
     (void *)android_hardware_Camera_startPreview },
-  { "stopPreview",
+  { "_stopPreview",
     "()V",
     (void *)android_hardware_Camera_stopPreview },
   { "previewEnabled",
@@ -777,6 +812,12 @@
   { "setDisplayOrientation",
     "(I)V",
     (void *)android_hardware_Camera_setDisplayOrientation },
+  { "_startFaceDetection",
+    "(I)V",
+    (void *)android_hardware_Camera_startFaceDetection },
+  { "_stopFaceDetection",
+    "()V",
+    (void *)android_hardware_Camera_stopFaceDetection},
 };
 
 struct field {
@@ -818,6 +859,12 @@
           ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I", &fields.surfaceTexture },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
+        { "android/hardware/Camera$FaceMetadata", "face", "Landroid/graphics/Rect;", &fields.face_rectangle },
+        { "android/hardware/Camera$FaceMetadata", "score", "I", &fields.face_score },
+        { "android/graphics/Rect", "left", "I", &fields.rect_left },
+        { "android/graphics/Rect", "top", "I", &fields.rect_top },
+        { "android/graphics/Rect", "right", "I", &fields.rect_right },
+        { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom },
     };
 
     if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 50d9ca1..9be3779 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -127,7 +127,7 @@
 static int
 android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
         jint source, jint sampleRateInHertz, jint channels,
-        jint audioFormat, jint buffSizeInBytes)
+        jint audioFormat, jint buffSizeInBytes, jintArray jSession)
 {
     //LOGV(">> Entering android_media_AudioRecord_setup");
     //LOGV("sampleRate=%d, audioFormat=%d, channels=%x, buffSizeInBytes=%d",
@@ -162,6 +162,20 @@
         return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE;
     }
 
+    if (jSession == NULL) {
+        LOGE("Error creating AudioRecord: invalid session ID pointer");
+        return AUDIORECORD_ERROR;
+    }
+
+    jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
+    if (nSession == NULL) {
+        LOGE("Error creating AudioRecord: Error retrieving session id pointer");
+        return AUDIORECORD_ERROR;
+    }
+    int sessionId = nSession[0];
+    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
+    nSession = NULL;
+
     audiorecord_callback_cookie *lpCallbackData = NULL;
     AudioRecord* lpRecorder = NULL;
 
@@ -193,13 +207,24 @@
         recorderCallback,// callback_t
         lpCallbackData,// void* user
         0,             // notificationFrames,
-        true);         // threadCanCallJava)
+        true,          // threadCanCallJava)
+        sessionId);
 
     if(lpRecorder->initCheck() != NO_ERROR) {
         LOGE("Error creating AudioRecord instance: initialization check failed.");
         goto native_init_failure;
     }
 
+    nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
+    if (nSession == NULL) {
+        LOGE("Error creating AudioRecord: Error retrieving session id pointer");
+        goto native_init_failure;
+    }
+    // read the audio session ID back from AudioTrack in case a new session was created during set()
+    nSession[0] = lpRecorder->getSessionId();
+    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
+    nSession = NULL;
+
     // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field 
     // of the Java object
     env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (int)lpRecorder);
@@ -485,7 +510,7 @@
     // name,               signature,  funcPtr
     {"native_start",         "()I",    (void *)android_media_AudioRecord_start},
     {"native_stop",          "()V",    (void *)android_media_AudioRecord_stop},
-    {"native_setup",         "(Ljava/lang/Object;IIIII)I",
+    {"native_setup",         "(Ljava/lang/Object;IIIII[I)I",
                                        (void *)android_media_AudioRecord_setup},
     {"native_finalize",      "()V",    (void *)android_media_AudioRecord_finalize},
     {"native_release",       "()V",    (void *)android_media_AudioRecord_release},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index bd70dad..2929056 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -167,11 +167,11 @@
 // ----------------------------------------------------------------------------
 static int
 android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
-        jint streamType, jint sampleRateInHertz, jint channels,
+        jint streamType, jint sampleRateInHertz, jint javaChannelMask,
         jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession)
 {
-    LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
-        sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
+    LOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d",
+        sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes);
     int afSampleRate;
     int afFrameCount;
 
@@ -184,11 +184,16 @@
         return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
 
-    if (!audio_is_output_channel(channels)) {
+    // Java channel masks don't map directly to the native definition, but it's a simple shift
+    // to skip the two deprecated channel configurations "default" and "mono".
+    uint32_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
+
+    if (!audio_is_output_channel(nativeChannelMask)) {
         LOGE("Error creating AudioTrack: invalid channel mask.");
         return AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
     }
-    int nbChannels = popcount(channels);
+
+    int nbChannels = popcount(nativeChannelMask);
     
     // check the stream type
     audio_stream_type_t atStreamType;
@@ -285,7 +290,7 @@
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
-            channels,
+            nativeChannelMask,
             frameCount,
             0,// flags
             audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
@@ -306,7 +311,7 @@
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
-            channels,
+            nativeChannelMask,
             frameCount,
             0,// flags
             audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index d54981e..c22b071 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -44,7 +44,6 @@
 
 // Returns an ASCII decimal number read from the specified file, -1 on error.
 static jlong readNumber(char const* filename) {
-#ifdef HAVE_ANDROID_OS
     char buf[80];
     int fd = open(filename, O_RDONLY);
     if (fd < 0) {
@@ -62,9 +61,6 @@
     close(fd);
     buf[len] = '\0';
     return atoll(buf);
-#else  // Simulator
-    return -1;
-#endif
 }
 
 static const char* mobile_iface_list[] = {
@@ -101,7 +97,6 @@
 // Returns the sum of numbers from the specified path under /sys/class/net/*,
 // -1 if no such file exists.
 static jlong readTotal(char const* suffix) {
-#ifdef HAVE_ANDROID_OS
     char filename[PATH_MAX] = "/sys/class/net/";
     DIR *dir = opendir(filename);
     if (dir == NULL) {
@@ -123,9 +118,6 @@
 
     closedir(dir);
     return total;
-#else  // Simulator
-    return -1;
-#endif
 }
 
 // Mobile stats get accessed a lot more often than total stats.
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index e930c5c..3cbd912 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -28,6 +28,9 @@
 #define WIFI_PKG_NAME "android/net/wifi/WifiNative"
 #define BUF_SIZE 256
 
+//TODO: This file can be refactored to push a lot of the functionality to java
+//with just a few JNI calls - doBoolean/doInt/doString
+
 namespace android {
 
 static jboolean sScanModeActive = false;
@@ -315,26 +318,56 @@
     return doBooleanCommand("OK", "DRIVER STOP");
 }
 
-static jboolean android_net_wifi_startPacketFiltering(JNIEnv* env, jobject)
+/*
+    Multicast filtering rules work as follows:
+
+    The driver can filter multicast (v4 and/or v6) and broadcast packets when in
+    a power optimized mode (typically when screen goes off).
+
+    In order to prevent the driver from filtering the multicast/broadcast packets, we have to
+    add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
+
+    DRIVER RXFILTER-ADD Num
+        where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
+
+    and DRIVER RXFILTER-START
+
+    In order to stop the usage of these rules, we do
+
+    DRIVER RXFILTER-STOP
+    DRIVER RXFILTER-REMOVE Num
+        where Num is as described for RXFILTER-ADD
+
+    The  SETSUSPENDOPT driver command overrides the filtering rules
+*/
+
+static jboolean android_net_wifi_startMultiV4Filtering(JNIEnv* env, jobject)
 {
-    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 0")
-            && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 1")
-            && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3")
+    return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 2")
             && doBooleanCommand("OK", "DRIVER RXFILTER-START");
 }
 
-static jboolean android_net_wifi_stopPacketFiltering(JNIEnv* env, jobject)
+static jboolean android_net_wifi_stopMultiV4Filtering(JNIEnv* env, jobject)
 {
-    jboolean result = doBooleanCommand("OK", "DRIVER RXFILTER-STOP");
-    if (result) {
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3");
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 1");
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 0");
-    }
-
-    return result;
+    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 2")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-START");
 }
 
+static jboolean android_net_wifi_startMultiV6Filtering(JNIEnv* env, jobject)
+{
+    return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-START");
+}
+
+static jboolean android_net_wifi_stopMultiV6Filtering(JNIEnv* env, jobject)
+{
+    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3")
+        && doBooleanCommand("OK", "DRIVER RXFILTER-START");
+}
+
+
 static jint android_net_wifi_getRssiHelper(const char *cmd)
 {
     char reply[BUF_SIZE];
@@ -507,6 +540,35 @@
 }
 
 
+static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand)
+{
+    ScopedUtfChars command(env, javaCommand);
+    if (command.c_str() == NULL) {
+        return JNI_FALSE;
+    }
+    return doBooleanCommand("OK", "%s", command.c_str());
+}
+
+static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand)
+{
+    ScopedUtfChars command(env, javaCommand);
+    if (command.c_str() == NULL) {
+        return -1;
+    }
+    return doIntCommand("%s", command.c_str());
+}
+
+static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand)
+{
+    ScopedUtfChars command(env, javaCommand);
+    if (command.c_str() == NULL) {
+        return NULL;
+    }
+    return doStringCommand(env, "%s", command.c_str());
+}
+
+
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -545,8 +607,10 @@
     { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand },
     { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand },
     { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand },
-    { "startPacketFiltering", "()Z", (void*) android_net_wifi_startPacketFiltering },
-    { "stopPacketFiltering", "()Z", (void*) android_net_wifi_stopPacketFiltering },
+    { "startFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_startMultiV4Filtering},
+    { "stopFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_stopMultiV4Filtering},
+    { "startFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_startMultiV6Filtering},
+    { "stopFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_stopMultiV6Filtering},
     { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand },
     { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand },
     { "setBandCommand", "(I)Z", (void*) android_net_wifi_setBandCommand},
@@ -576,6 +640,9 @@
         (void*) android_net_wifi_setCountryCodeCommand},
     { "enableBackgroundScanCommand", "(Z)V", (void*) android_net_wifi_enableBackgroundScanCommand},
     { "setScanIntervalCommand", "(I)V", (void*) android_net_wifi_setScanIntervalCommand},
+    { "doBooleanCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand},
+    { "doIntCommand", "(Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand},
+    { "doStringCommand", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand},
 };
 
 int register_android_net_wifi_WifiManager(JNIEnv* env)
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 2297834..3a3f07e 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -27,6 +27,7 @@
 #include <sys/time.h>
 #include <errno.h>
 #include <assert.h>
+#include <ctype.h>
 
 #ifdef HAVE_MALLOC_H
 #include <malloc.h>
@@ -35,28 +36,50 @@
 namespace android
 {
 
-static jfieldID dalvikPss_field;
-static jfieldID dalvikPrivateDirty_field;
-static jfieldID dalvikSharedDirty_field;
-static jfieldID nativePss_field;
-static jfieldID nativePrivateDirty_field;
-static jfieldID nativeSharedDirty_field;
-static jfieldID otherPss_field;
-static jfieldID otherPrivateDirty_field;
-static jfieldID otherSharedDirty_field;
+enum {
+    HEAP_UNKNOWN,
+    HEAP_DALVIK,
+    HEAP_NATIVE,
+    HEAP_CURSOR,
+    HEAP_ASHMEM,
+    HEAP_UNKNOWN_DEV,
+    HEAP_SO,
+    HEAP_JAR,
+    HEAP_APK,
+    HEAP_TTF,
+    HEAP_DEX,
+    HEAP_UNKNOWN_MAP,
+
+    _NUM_HEAP,
+    _NUM_CORE_HEAP = HEAP_NATIVE+1
+};
+
+struct stat_fields {
+    jfieldID pss_field;
+    jfieldID privateDirty_field;
+    jfieldID sharedDirty_field;
+};
+
+struct stat_field_names {
+    const char* pss_name;
+    const char* privateDirty_name;
+    const char* sharedDirty_name;
+};
+
+static stat_fields stat_fields[_NUM_CORE_HEAP];
+
+static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
+    { "otherPss", "otherPrivateDirty", "otherSharedDirty" },
+    { "dalvikPss", "dalvikPrivateDirty", "dalvikSharedDirty" },
+    { "nativePss", "nativePrivateDirty", "nativeSharedDirty" }
+};
+
+jfieldID otherStats_field;
 
 struct stats_t {
-    int dalvikPss;
-    int dalvikPrivateDirty;
-    int dalvikSharedDirty;
-    
-    int nativePss;
-    int nativePrivateDirty;
-    int nativeSharedDirty;
-    
-    int otherPss;
-    int otherPrivateDirty;
-    int otherSharedDirty;
+    int pss;
+    int privateDirty;
+    int sharedDirty;
 };
 
 #define BINDER_STATS "/proc/binder/stats"
@@ -94,48 +117,71 @@
 static void read_mapinfo(FILE *fp, stats_t* stats)
 {
     char line[1024];
-    int len;
+    int len, nameLen;
     bool skip, done = false;
 
-    unsigned start = 0, size = 0, resident = 0, pss = 0;
+    unsigned size = 0, resident = 0, pss = 0;
     unsigned shared_clean = 0, shared_dirty = 0;
     unsigned private_clean = 0, private_dirty = 0;
     unsigned referenced = 0;
     unsigned temp;
 
-    int isNativeHeap;
-    int isDalvikHeap;
-    int isSqliteHeap;
+    unsigned long int start;
+    unsigned long int end = 0;
+    unsigned long int prevEnd = 0;
+    char* name;
+    int name_pos;
 
-    if(fgets(line, 1024, fp) == 0) return;
+    int whichHeap = HEAP_UNKNOWN;
+    int prevHeap = HEAP_UNKNOWN;
+
+    if(fgets(line, sizeof(line), fp) == 0) return;
 
     while (!done) {
-        isNativeHeap = 0;
-        isDalvikHeap = 0;
-        isSqliteHeap = 0;
+        prevHeap = whichHeap;
+        prevEnd = end;
+        whichHeap = HEAP_UNKNOWN;
         skip = false;
 
         len = strlen(line);
         if (len < 1) return;
         line[--len] = 0;
 
-        /* ignore guard pages */
-        if (len > 18 && line[17] == '-') skip = true;
+        if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
+            skip = true;
+        } else {
+            while (isspace(line[name_pos])) {
+                name_pos += 1;
+            }
+            name = line + name_pos;
+            nameLen = strlen(name);
 
-        start = strtoul(line, 0, 16);
-
-        if (strstr(line, "[heap]")) {
-            isNativeHeap = 1;
-        } else if (strstr(line, "/dalvik-LinearAlloc")) {
-            isDalvikHeap = 1;
-        } else if (strstr(line, "/mspace/dalvik-heap")) {
-            isDalvikHeap = 1;
-        } else if (strstr(line, "/dalvik-heap-bitmap/")) {
-            isDalvikHeap = 1;    
-        } else if (strstr(line, "/data/dalvik-cache/")) {
-            isDalvikHeap = 1;
-        } else if (strstr(line, "/tmp/sqlite-heap")) {
-            isSqliteHeap = 1;
+            if (strstr(name, "[heap]") == name) {
+                whichHeap = HEAP_NATIVE;
+            } else if (strstr(name, "/dev/ashmem/dalvik-") == name) {
+                whichHeap = HEAP_DALVIK;
+            } else if (strstr(name, "/dev/ashmem/CursorWindow") == name) {
+                whichHeap = HEAP_CURSOR;
+            } else if (strstr(name, "/dev/ashmem/") == name) {
+                whichHeap = HEAP_ASHMEM;
+            } else if (strstr(name, "/dev/") == name) {
+                whichHeap = HEAP_UNKNOWN_DEV;
+            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
+                whichHeap = HEAP_SO;
+            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
+                whichHeap = HEAP_JAR;
+            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
+                whichHeap = HEAP_APK;
+            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
+                whichHeap = HEAP_TTF;
+            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) {
+                whichHeap = HEAP_DEX;
+            } else if (nameLen > 0) {
+                whichHeap = HEAP_UNKNOWN_MAP;
+            } else if (start == prevEnd && prevHeap == HEAP_SO) {
+                // bss section of a shared library.
+                whichHeap = HEAP_SO;
+            }
         }
 
         //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
@@ -171,21 +217,9 @@
         }
 
         if (!skip) {
-            if (isNativeHeap) {
-                stats->nativePss += pss;
-                stats->nativePrivateDirty += private_dirty;
-                stats->nativeSharedDirty += shared_dirty;
-            } else if (isDalvikHeap) {
-                stats->dalvikPss += pss;
-                stats->dalvikPrivateDirty += private_dirty;
-                stats->dalvikSharedDirty += shared_dirty;
-            } else if ( isSqliteHeap) {
-                // ignore
-            } else {
-                stats->otherPss += pss;
-                stats->otherPrivateDirty += private_dirty;
-                stats->otherSharedDirty += shared_dirty;
-            }
+            stats[whichHeap].pss += pss;
+            stats[whichHeap].privateDirty += private_dirty;
+            stats[whichHeap].sharedDirty += shared_dirty;
         }
     }
 }
@@ -206,22 +240,38 @@
 static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
         jint pid, jobject object)
 {
-    stats_t stats;
-    memset(&stats, 0, sizeof(stats_t));
+    stats_t stats[_NUM_HEAP];
+    memset(&stats, 0, sizeof(stats));
     
-    load_maps(pid, &stats);
+    load_maps(pid, stats);
 
-    env->SetIntField(object, dalvikPss_field, stats.dalvikPss);
-    env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty);
-    env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty);
+    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
+        stats[HEAP_UNKNOWN].pss += stats[i].pss;
+        stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty;
+        stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
+    }
+
+    for (int i=0; i<_NUM_CORE_HEAP; i++) {
+        env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
+        env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
+        env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
+    }
     
-    env->SetIntField(object, nativePss_field, stats.nativePss);
-    env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty);
-    env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty);
+    jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
     
-    env->SetIntField(object, otherPss_field, stats.otherPss);
-    env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty);
-    env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty);
+    jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
+    if (otherArray == NULL) {
+        return;
+    }
+
+    int j=0;
+    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
+        otherArray[j++] = stats[i].pss;
+        otherArray[j++] = stats[i].privateDirty;
+        otherArray[j++] = stats[i].sharedDirty;
+    }
+
+    env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
 }
 
 static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
@@ -278,7 +328,6 @@
 jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
 
 
-#ifdef HAVE_ANDROID_OS
 /* pulled out of bionic */
 extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
     size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
@@ -414,7 +463,6 @@
 
     fprintf(fp, "END\n");
 }
-#endif /*HAVE_ANDROID_OS*/
 
 /*
  * Dump the native heap, writing human-readable output to the specified
@@ -449,13 +497,9 @@
         return;
     }
 
-#ifdef HAVE_ANDROID_OS
     LOGD("Native heap dump starting...\n");
     dumpNativeHeap(fp);
     LOGD("Native heap dump complete.\n");
-#else
-    fprintf(fp, "Native heap dump not available on this platform\n");
-#endif
 
     fclose(fp);
 }
@@ -493,19 +537,18 @@
 int register_android_os_Debug(JNIEnv *env)
 {
     jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
-    
-    dalvikPss_field = env->GetFieldID(clazz, "dalvikPss", "I");
-    dalvikPrivateDirty_field = env->GetFieldID(clazz, "dalvikPrivateDirty", "I");
-    dalvikSharedDirty_field = env->GetFieldID(clazz, "dalvikSharedDirty", "I");
 
-    nativePss_field = env->GetFieldID(clazz, "nativePss", "I");
-    nativePrivateDirty_field = env->GetFieldID(clazz, "nativePrivateDirty", "I");
-    nativeSharedDirty_field = env->GetFieldID(clazz, "nativeSharedDirty", "I");
-    
-    otherPss_field = env->GetFieldID(clazz, "otherPss", "I");
-    otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I");
-    otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I");
-    
+    for (int i=0; i<_NUM_CORE_HEAP; i++) {
+        stat_fields[i].pss_field =
+                env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
+        stat_fields[i].privateDirty_field =
+                env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I");
+        stat_fields[i].sharedDirty_field =
+                env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
+    }
+
+    otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
+
     return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 89dce89..8d65cbc 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -28,11 +28,8 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <signal.h>
-
-#if HAVE_ANDROID_OS
 #include <sys/ioctl.h>
 #include <linux/msdos_fs.h>
-#endif
 
 namespace android {
 
@@ -53,7 +50,6 @@
                                          jstring file, jint mode,
                                          jint uid, jint gid)
 {
-    #if HAVE_ANDROID_OS
     const jchar* str = env->GetStringCritical(file, 0);
     String8 file8;
     if (str) {
@@ -70,15 +66,11 @@
         }
     }
     return chmod(file8.string(), mode) == 0 ? 0 : errno;
-    #else
-    return ENOSYS;
-    #endif
 }
 
 jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
                                          jstring file, jintArray outArray)
 {
-    #if HAVE_ANDROID_OS
     const jchar* str = env->GetStringCritical(file, 0);
     String8 file8;
     if (str) {
@@ -107,9 +99,6 @@
     }
     env->ReleasePrimitiveArrayCritical(outArray, array, 0);
     return 0;
-    #else
-    return ENOSYS;
-    #endif
 }
 
 jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
@@ -119,7 +108,6 @@
 
 jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
 {
-    #if HAVE_ANDROID_OS
     if (path == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return -1;
@@ -137,9 +125,6 @@
 
     env->ReleaseStringUTFChars(path, pathStr);
     return result;
-    #else
-    return -1;
-    #endif
 }
 
 jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp
index 9ae4a63..dc16990 100644
--- a/core/jni/android_os_Power.cpp
+++ b/core/jni/android_os_Power.cpp
@@ -70,16 +70,11 @@
 
 static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
 {
-#ifdef HAVE_ANDROID_OS
     android_reboot(ANDROID_RB_POWEROFF, 0, 0);
-#else
-    sync();
-#endif
 }
 
 static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
 {
-#ifdef HAVE_ANDROID_OS
     if (reason == NULL) {
         android_reboot(ANDROID_RB_RESTART, 0, 0);
     } else {
@@ -88,9 +83,6 @@
         env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
     }
     jniThrowIOException(env, errno);
-#else
-    sync();
-#endif
 }
 
 static JNINativeMethod method_table[] = {
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index ffd0c1e..66d58cd 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -80,6 +80,38 @@
 }
 
 /*
+ * native public static long currentThreadTimeMicro();
+ */
+static jlong android_os_SystemClock_currentThreadTimeMicro(JNIEnv* env,
+        jobject clazz)
+{
+#if defined(HAVE_POSIX_CLOCKS)
+    struct timespec tm;
+
+    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
+
+    return tm.tv_sec * 1000000LL + tm.tv_nsec / 1000;
+#else
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * 1000000LL + tv.tv_nsec / 1000;
+#endif
+}
+
+/*
+ * native public static long currentTimeMicro();
+ */
+static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env,
+        jobject clazz)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * 1000000LL + tv.tv_usec;
+}
+
+/*
  * JNI registration.
  */
 static JNINativeMethod gMethods[] = {
@@ -92,6 +124,10 @@
             (void*) android_os_SystemClock_elapsedRealtime },
     { "currentThreadTimeMillis",      "()J",
             (void*) android_os_SystemClock_currentThreadTimeMillis },
+    { "currentThreadTimeMicro",       "()J",
+            (void*) android_os_SystemClock_currentThreadTimeMicro },
+    { "currentTimeMicro",             "()J",
+            (void*) android_os_SystemClock_currentTimeMicro },
 };
 int register_android_os_SystemClock(JNIEnv* env)
 {
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 2b09442..8f84b81 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -1115,7 +1115,7 @@
         LOGV("... uuid = %s", uuid);
 
         dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallBooleanMethod(nat->me, method_onAgentAuthorize,
+        env->CallVoidMethod(nat->me, method_onAgentAuthorize,
                 env->NewStringUTF(object_path), env->NewStringUTF(uuid),
                 int(msg));
 
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index c152aa8..69c6021 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -641,7 +641,7 @@
     /* name, signature, funcPtr */
     { "normalize",               "(Z)J",                                        (void*)android_text_format_Time_normalize },
     { "switchTimezone",          "(Ljava/lang/String;)V",                       (void*)android_text_format_Time_switchTimezone },
-    { "compare",                 "(Landroid/text/format/Time;Landroid/text/format/Time;)I",     (void*)android_text_format_Time_compare },
+    { "nativeCompare",           "(Landroid/text/format/Time;Landroid/text/format/Time;)I",     (void*)android_text_format_Time_compare },
     { "format1",                 "(Ljava/lang/String;)Ljava/lang/String;",      (void*)android_text_format_Time_format },
     { "format2445",              "()Ljava/lang/String;",                        (void*)android_text_format_Time_format2445 },
     { "toString",                "()Ljava/lang/String;",                        (void*)android_text_format_Time_toString },
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 0fbe0e7..2c7bb84 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -58,9 +58,6 @@
 
 static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
 {
-#ifndef HAVE_ANDROID_OS
-    return false;
-#else /* HAVE_ANDROID_OS */
     int len;
     char key[PROPERTY_KEY_MAX];
     char buf[PROPERTY_VALUE_MAX];
@@ -93,7 +90,6 @@
     len = property_get(key, buf, "");
     int logLevel = toLevel(buf);
     return (logLevel >= 0 && level >= logLevel) ? true : false;
-#endif /* HAVE_ANDROID_OS */
 }
 
 /*
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index d1ba2d1..47d343a 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -352,20 +352,12 @@
 
 jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
 {
-    #if HAVE_ANDROID_OS
     return setuid(uid) == 0 ? 0 : errno;
-    #else
-    return ENOSYS;
-    #endif
 }
 
 jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
 {
-    #if HAVE_ANDROID_OS
     return setgid(uid) == 0 ? 0 : errno;
-    #else
-    return ENOSYS;
-    #endif
 }
 
 static int pid_compare(const void* v1, const void* v2)
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index 97f9fc34..5e668b9 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -45,11 +45,6 @@
 };
 static offsets_t offsets;
 
-static int gShortSize = -1;
-static int gLongSize = -1;
-static int gOldSize = -1;
-static int gNewSize = -1;
-
 // ----------------------------------------------------------------------------
 
 static void android_view_Display_init(
@@ -68,30 +63,6 @@
     env->SetFloatField(clazz, offsets.ydpi,     info.ydpi);
 }
 
-static jint android_view_Display_getWidth(
-        JNIEnv* env, jobject clazz)
-{
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    jint w = SurfaceComposerClient::getDisplayWidth(dpy);
-    if (gShortSize > 0) {
-        jint h = SurfaceComposerClient::getDisplayHeight(dpy);
-        return w < h ? gShortSize : gLongSize;
-    }
-    return w == gOldSize ? gNewSize : w;
-}
-
-static jint android_view_Display_getHeight(
-        JNIEnv* env, jobject clazz)
-{
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    int h = SurfaceComposerClient::getDisplayHeight(dpy);
-    if (gShortSize > 0) {
-        jint w = SurfaceComposerClient::getDisplayWidth(dpy);
-        return h < w ? gShortSize : gLongSize;
-    }
-    return h == gOldSize ? gNewSize : h;
-}
-
 static jint android_view_Display_getRawWidth(
         JNIEnv* env, jobject clazz)
 {
@@ -132,10 +103,6 @@
             (void*)android_view_Display_getDisplayCount },
 	{   "init", "(I)V",
             (void*)android_view_Display_init },
-    {   "getRealWidth", "()I",
-            (void*)android_view_Display_getWidth },
-    {   "getRealHeight", "()I",
-            (void*)android_view_Display_getHeight },
     {   "getRawWidth", "()I",
             (void*)android_view_Display_getRawWidth },
     {   "getRawHeight", "()I",
@@ -156,24 +123,6 @@
 
 int register_android_view_Display(JNIEnv* env)
 {
-    char buf[PROPERTY_VALUE_MAX];
-    int len = property_get("persist.demo.screensizehack", buf, "");
-    if (len > 0) {
-        int temp1, temp2;
-        if (sscanf(buf, "%dx%d", &temp1, &temp2) == 2) {
-            if (temp1 < temp2) {
-                gShortSize = temp1;
-                gLongSize = temp2;
-            } else {
-                gShortSize = temp2;
-                gLongSize = temp1;
-            }
-        } else if (sscanf(buf, "%d=%d", &temp1, &temp2) == 2) {
-            gOldSize = temp1;
-            gNewSize = temp2;
-        }
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
             kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 681f43f..b3f2d51 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -127,6 +127,13 @@
     }
 }
 
+static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
+        Caches::FlushMode mode) {
+    if (Caches::hasInstance()) {
+        Caches::getInstance().flush(mode);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
@@ -569,18 +576,23 @@
 // ----------------------------------------------------------------------------
 
 static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
-        jobject clazz, DisplayListRenderer* renderer) {
-    return renderer->getDisplayList();
+        jobject clazz, DisplayListRenderer* renderer, DisplayList* displayList) {
+    return renderer->getDisplayList(displayList);
 }
 
-static OpenGLRenderer* android_view_GLES20Canvas_getDisplayListRenderer(JNIEnv* env,
+static jint android_view_GLES20Canvas_getDisplayListSize(JNIEnv* env,
+        jobject clazz, DisplayList* displayList) {
+    return displayList->getSize();
+}
+
+static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
+        jobject clazz) {
+    return new DisplayListRenderer;
+}
+
+static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env,
         jobject clazz, DisplayListRenderer* renderer) {
-    if (renderer == NULL) {
-        renderer = new DisplayListRenderer;
-    } else {
-        renderer->reset();
-    }
-    return renderer;
+    renderer->reset();
 }
 
 static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
@@ -714,8 +726,7 @@
 // ----------------------------------------------------------------------------
 
 static void
-android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor)
-{
+android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
 #ifdef USE_OPENGL_RENDERER
     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
     android::uirenderer::DisplayList::outputLogBuffer(fd);
@@ -735,6 +746,7 @@
     { "nIsBackBufferPreserved", "()Z",         (void*) android_view_GLES20Canvas_isBackBufferPreserved },
     { "nPreserveBackBuffer",    "()Z",         (void*) android_view_GLES20Canvas_preserveBackBuffer },
     { "nDisableVsync",          "()V",         (void*) android_view_GLES20Canvas_disableVsync },
+    { "nFlushCaches",           "(I)V",        (void*) android_view_GLES20Canvas_flushCaches },
 
     { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
@@ -804,9 +816,11 @@
     { "nGetClipBounds",     "(ILandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
 
-    { "nGetDisplayList",         "(I)I",       (void*) android_view_GLES20Canvas_getDisplayList },
+    { "nGetDisplayList",         "(II)I",      (void*) android_view_GLES20Canvas_getDisplayList },
     { "nDestroyDisplayList",     "(I)V",       (void*) android_view_GLES20Canvas_destroyDisplayList },
-    { "nGetDisplayListRenderer", "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListRenderer },
+    { "nGetDisplayListSize",     "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListSize },
+    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
+    { "nResetDisplayListRenderer", "(I)V",     (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
     { "nDrawDisplayList",        "(IIIILandroid/graphics/Rect;)Z",
                                                (void*) android_view_GLES20Canvas_drawDisplayList },
     { "nOutputDisplayList",      "(II)V",      (void*) android_view_GLES20Canvas_outputDisplayList },
@@ -859,10 +873,8 @@
 
 const char* const kActivityThreadPathName = "android/app/ActivityThread";
 
-int register_android_app_ActivityThread(JNIEnv* env)
-{
-    return AndroidRuntime::registerNativeMethods(
-            env, kActivityThreadPathName,
+int register_android_app_ActivityThread(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
             gActivityThreadMethods, NELEM(gActivityThreadMethods));
 }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 0dc9293..4c1ca31 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -22,6 +22,7 @@
 #include "android/graphics/GraphicsJNI.h"
 
 #include <binder/IMemory.h>
+#include <gui/SurfaceTexture.h>
 #include <surfaceflinger/SurfaceComposerClient.h>
 #include <surfaceflinger/Surface.h>
 #include <ui/Region.h>
@@ -38,6 +39,7 @@
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
 #include <utils/misc.h>
 
 
@@ -244,6 +246,19 @@
     setSurfaceControl(env, clazz, surface);
 }
 
+static void Surface_initFromSurfaceTexture(
+        JNIEnv* env, jobject clazz, jobject jst)
+{
+    sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
+    sp<Surface> surface(new Surface(st));
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return;
+    }
+    setSurfaceControl(env, clazz, NULL);
+    setSurface(env, clazz, surface);
+}
+
 static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
 {
     Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
@@ -761,10 +776,26 @@
         return;
     }
 
+    // The Java instance may have a SurfaceControl (in the case of the
+    // WindowManager or a system app). In that case, we defer to the
+    // SurfaceControl to send its ISurface. Otherwise, if the Surface is
+    // available we let it parcel itself. Finally, if the Surface is also
+    // NULL we fall back to using the SurfaceControl path which sends an
+    // empty surface; this matches legacy behavior.
     const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
-    SurfaceControl::writeSurfaceToParcel(control, parcel);
+    if (control != NULL) {
+        SurfaceControl::writeSurfaceToParcel(control, parcel);
+    } else {
+        sp<Surface> surface(Surface_getSurface(env, clazz));
+        if (surface != NULL) {
+            Surface::writeToParcel(surface, parcel);
+        } else {
+            SurfaceControl::writeSurfaceToParcel(NULL, parcel);
+        }
+    }
     if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
-        setSurfaceControl(env, clazz, 0);
+        setSurfaceControl(env, clazz, NULL);
+        setSurface(env, clazz, NULL);
     }
 }
 
@@ -784,6 +815,7 @@
     {"nativeClassInit",     "()V",  (void*)nativeClassInit },
     {"init",                "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V",  (void*)Surface_init },
     {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
+    {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
     {"getIdentity",         "()I",  (void*)Surface_getIdentity },
     {"destroy",             "()V",  (void*)Surface_destroy },
     {"release",             "()V",  (void*)Surface_release },
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index b046b23..9484c6b 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -19,11 +19,48 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 
+#include <ui/Region.h>
+#include <ui/Rect.h>
+
 #include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <SkBitmap.h>
+#include <SkCanvas.h>
 
 namespace android {
 
 // ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+static struct {
+    jmethodID set;
+    jfieldID left;
+    jfieldID top;
+    jfieldID right;
+    jfieldID bottom;
+} gRectClassInfo;
+
+static struct {
+    jfieldID nativeCanvas;
+    jfieldID surfaceFormat;
+} gCanvasClassInfo;
+
+static struct {
+    jfieldID nativeWindow;
+} gTextureViewClassInfo;
+
+#define GET_INT(object, field) \
+    env->GetIntField(object, field)
+
+#define SET_INT(object, field, value) \
+    env->SetIntField(object, field, value)
+
+#define INVOKEV(object, method, ...) \
+    env->CallVoidMethod(object, method, __VA_ARGS__)
+
+// ----------------------------------------------------------------------------
 // Native layer
 // ----------------------------------------------------------------------------
 
@@ -34,6 +71,118 @@
     surfaceTexture->setDefaultBufferSize(width, height);
 }
 
+static inline SkBitmap::Config convertPixelFormat(int32_t format) {
+    switch (format) {
+        case WINDOW_FORMAT_RGBA_8888:
+            return SkBitmap::kARGB_8888_Config;
+        case WINDOW_FORMAT_RGBX_8888:
+            return SkBitmap::kARGB_8888_Config;
+        case WINDOW_FORMAT_RGB_565:
+            return SkBitmap::kRGB_565_Config;
+        default:
+            return SkBitmap::kNo_Config;
+    }
+}
+
+/**
+ * This is a private API, and this implementation is also provided in the NDK.
+ * However, the NDK links against android_runtime, which means that using the
+ * NDK implementation would create a circular dependency between the libraries.
+ */
+static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
+        Rect* inOutDirtyBounds) {
+    return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds);
+}
+
+static int32_t native_window_unlockAndPost(ANativeWindow* window) {
+    return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
+}
+
+static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView,
+        jobject surface) {
+
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
+    sp<ANativeWindow> window = new SurfaceTextureClient(surfaceTexture);
+
+    window->incStrong(0);
+    SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get()));
+}
+
+static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) {
+
+    ANativeWindow* nativeWindow = (ANativeWindow*)
+            GET_INT(textureView, gTextureViewClassInfo.nativeWindow);
+
+    if (nativeWindow) {
+        sp<ANativeWindow> window(nativeWindow);
+            window->decStrong(0);
+        SET_INT(textureView, gTextureViewClassInfo.nativeWindow, 0);
+    }
+}
+
+static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
+        jint nativeWindow, jobject canvas, jobject dirtyRect) {
+
+    if (!nativeWindow) {
+        return;
+    }
+
+    ANativeWindow_Buffer buffer;
+
+    Rect rect;
+    if (dirtyRect) {
+        rect.left = GET_INT(dirtyRect, gRectClassInfo.left);
+        rect.top = GET_INT(dirtyRect, gRectClassInfo.top);
+        rect.right = GET_INT(dirtyRect, gRectClassInfo.right);
+        rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom);
+    } else {
+        rect.set(Rect(0x3FFF, 0x3FFF));
+    }
+
+    sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
+    native_window_lock(window.get(), &buffer, &rect);
+
+    ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format);
+
+    SkBitmap bitmap;
+    bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount);
+
+    if (buffer.format == WINDOW_FORMAT_RGBX_8888) {
+        bitmap.setIsOpaque(true);
+    }
+
+    if (buffer.width > 0 && buffer.height > 0) {
+        bitmap.setPixels(buffer.bits);
+    } else {
+        bitmap.setPixels(NULL);
+    }
+
+    SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format);
+    SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
+    nativeCanvas->setBitmapDevice(bitmap);
+
+    SkRect clipRect;
+    clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
+    nativeCanvas->clipRect(clipRect);
+
+    if (dirtyRect) {
+        INVOKEV(dirtyRect, gRectClassInfo.set,
+                int(rect.left), int(rect.top), int(rect.right), int(rect.bottom));
+    }
+}
+
+static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
+        jint nativeWindow, jobject canvas) {
+
+    SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
+    nativeCanvas->setBitmapDevice(SkBitmap());
+
+    if (nativeWindow) {
+        sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
+        native_window_unlockAndPost(window.get());
+    }
+}
+
 // ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
@@ -42,10 +191,47 @@
 
 static JNINativeMethod gMethods[] = {
     {   "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V",
-            (void*) android_view_TextureView_setDefaultBufferSize }
+            (void*) android_view_TextureView_setDefaultBufferSize },
+
+    {   "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V",
+            (void*) android_view_TextureView_createNativeWindow },
+    {   "nDestroyNativeWindow", "()V",
+            (void*) android_view_TextureView_destroyNativeWindow },
+
+    {   "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V",
+            (void*) android_view_TextureView_lockCanvas },
+    {   "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
+            (void*) android_view_TextureView_unlockCanvasAndPost },
 };
 
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(!var, "Unable to find class " className);
+
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+        LOG_FATAL_IF(!var, "Unable to find method " methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(!var, "Unable to find field" fieldName);
+
 int register_android_view_TextureView(JNIEnv* env) {
+    jclass clazz;
+    FIND_CLASS(clazz, "android/graphics/Rect");
+    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
+    GET_FIELD_ID(gRectClassInfo.left, clazz, "left", "I");
+    GET_FIELD_ID(gRectClassInfo.top, clazz, "top", "I");
+    GET_FIELD_ID(gRectClassInfo.right, clazz, "right", "I");
+    GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
+
+    FIND_CLASS(clazz, "android/graphics/Canvas");
+    GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I");
+    GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I");
+
+    FIND_CLASS(clazz, "android/view/TextureView");
+    GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I");
+
     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
new file mode 100644
index 0000000..830f70e
--- /dev/null
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -0,0 +1,375 @@
+/*
+ * 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_TAG "NativeLibraryHelper"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/Log.h>
+#include <ScopedUtfChars.h>
+#include <utils/ZipFileRO.h>
+
+#include <zlib.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+
+#define APK_LIB "lib/"
+#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
+
+#define LIB_PREFIX "/lib"
+#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1)
+
+#define LIB_SUFFIX ".so"
+#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
+
+#define GDBSERVER "gdbserver"
+#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
+
+#define TMP_FILE_PATTERN "/tmp.XXXXXX"
+#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1)
+
+namespace android {
+
+typedef void (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
+
+// These match PackageManager.java install codes
+typedef enum {
+    INSTALL_SUCCEEDED = 0,
+    INSTALL_FAILED_INVALID_APK = -2,
+    INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
+} install_status_t;
+
+// Equivalent to isFilenameSafe
+static bool
+isFilenameSafe(const char* filename)
+{
+    off_t offset = 0;
+    for (;;) {
+        switch (*(filename + offset)) {
+        case 0:
+            // Null.
+            // If we've reached the end, all the other characters are good.
+            return true;
+
+        case 'A' ... 'Z':
+        case 'a' ... 'z':
+        case '0' ... '9':
+        case '+':
+        case ',':
+        case '-':
+        case '.':
+        case '/':
+        case '=':
+        case '_':
+            offset++;
+            break;
+
+        default:
+            // We found something that is not good.
+            return false;
+        }
+    }
+    // Should not reach here.
+}
+
+static bool
+isFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime,
+        long zipCrc, struct stat64* st)
+{
+    if (lstat64(filePath, st) < 0) {
+        // File is not found or cannot be read.
+        LOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno));
+        return true;
+    }
+
+    if (!S_ISREG(st->st_mode)) {
+        return true;
+    }
+
+    if (st->st_size != fileSize) {
+        return true;
+    }
+
+    // For some reason, bionic doesn't define st_mtime as time_t
+    if (time_t(st->st_mtime) != modifiedTime) {
+        LOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime);
+        return true;
+    }
+
+    int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY));
+    if (fd < 0) {
+        LOGV("Couldn't open file %s: %s", filePath, strerror(errno));
+        return true;
+    }
+
+    long crc = crc32(0L, Z_NULL, 0);
+    unsigned char crcBuffer[16384];
+    ssize_t numBytes;
+    while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) {
+        crc = crc32(crc, crcBuffer, numBytes);
+    }
+    close(fd);
+
+    LOGV("%s: crc = %lx, zipCrc = %lx\n", filePath, crc, zipCrc);
+
+    if (crc != zipCrc) {
+        return true;
+    }
+
+    return false;
+}
+
+static void
+sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
+{
+    size_t* total = (size_t*) arg;
+    size_t uncompLen;
+
+    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) {
+        return;
+    }
+
+    *total += uncompLen;
+}
+
+/*
+ * Copy the native library if needed.
+ *
+ * This function assumes the library and path names passed in are considered safe.
+ */
+static void
+copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
+{
+    jstring* javaNativeLibPath = (jstring*) arg;
+    ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
+
+    size_t uncompLen;
+    long when;
+    long crc;
+    time_t modTime;
+
+    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) {
+        return;
+    } else {
+        struct tm t;
+        ZipFileRO::zipTimeToTimespec(when, &t);
+        modTime = mktime(&t);
+    }
+
+    // Build local file path
+    const size_t fileNameLen = strlen(fileName);
+    char localFileName[nativeLibPath.size() + fileNameLen + 2];
+
+    if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) {
+        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+        return;
+    }
+
+    *(localFileName + nativeLibPath.size()) = '/';
+
+    if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName)
+                    - nativeLibPath.size() - 1) != fileNameLen) {
+        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+        return;
+    }
+
+    // Only copy out the native file if it's different.
+    struct stat st;
+    if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
+        return;
+    }
+
+    char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2];
+    if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
+            != nativeLibPath.size()) {
+        LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+        return;
+    }
+
+    *(localFileName + nativeLibPath.size()) = '/';
+
+    if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
+                    TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) {
+        LOGI("Couldn't allocate temporary file name for library: %s", strerror(errno));
+        return;
+    }
+
+    int fd = mkstemp(localTmpFileName);
+    if (fd < 0) {
+        LOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
+        return;
+    }
+
+    if (!zipFile->uncompressEntry(zipEntry, fd)) {
+        LOGI("Failed uncompressing %s to %s: %s", fileName, localTmpFileName, strerror(errno));
+        close(fd);
+        unlink(localTmpFileName);
+        return;
+    }
+
+    close(fd);
+
+    // Set the modification time for this file to the ZIP's mod time.
+    struct timeval times[2];
+    times[0].tv_sec = st.st_atime;
+    times[1].tv_sec = modTime;
+    times[0].tv_usec = times[1].tv_usec = 0;
+    if (utimes(localTmpFileName, times) < 0) {
+        LOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
+        unlink(localTmpFileName);
+        return;
+    }
+
+    // Set the mode to 755
+    static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |  S_IXGRP | S_IROTH | S_IXOTH;
+    if (chmod(localTmpFileName, mode) < 0) {
+        LOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
+        unlink(localTmpFileName);
+        return;
+    }
+
+    // Finally, rename it to the final name.
+    if (rename(localTmpFileName, localFileName) < 0) {
+        LOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
+        unlink(localTmpFileName);
+        return;
+    }
+
+    LOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);
+}
+
+static install_status_t
+iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
+        iterFunc callFunc, void* callArg) {
+    ScopedUtfChars filePath(env, javaFilePath);
+    ScopedUtfChars cpuAbi(env, javaCpuAbi);
+    ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
+
+    ZipFileRO zipFile;
+
+    if (zipFile.open(filePath.c_str()) != NO_ERROR) {
+        LOGI("Couldn't open APK %s\n", filePath.c_str());
+        return INSTALL_FAILED_INVALID_APK;
+    }
+
+    const int N = zipFile.getNumEntries();
+
+    char fileName[PATH_MAX];
+
+    for (int i = 0; i < N; i++) {
+        const ZipEntryRO entry = zipFile.findEntryByIndex(i);
+        if (entry == NULL) {
+            continue;
+        }
+
+        // Make sure this entry has a filename.
+        if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) {
+            continue;
+        }
+
+        // Make sure we're in the lib directory of the ZIP.
+        if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
+            continue;
+        }
+
+        // Make sure the filename is at least to the minimum library name size.
+        const size_t fileNameLen = strlen(fileName);
+        static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
+        if (fileNameLen < minLength) {
+            continue;
+        }
+
+        const char* lastSlash = strrchr(fileName, '/');
+        if (lastSlash == NULL) {
+            LOG_ASSERT("last slash was null somehow for %s\n", fileName);
+            continue;
+        }
+
+        // Check to make sure the CPU ABI of this file is one we support.
+        const char* cpuAbiOffset = fileName + APK_LIB_LEN;
+        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
+
+        LOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
+        if (cpuAbi.size() == cpuAbiRegionSize
+                && *(cpuAbiOffset + cpuAbi.size()) == '/'
+                && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
+            LOGV("Using ABI %s\n", cpuAbi.c_str());
+        } else if (cpuAbi2.size() == cpuAbiRegionSize
+                && *(cpuAbiOffset + cpuAbi2.size()) == '/'
+                && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
+            LOGV("Using ABI %s\n", cpuAbi2.c_str());
+        } else {
+            LOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
+            continue;
+        }
+
+        // If this is a .so file, check to see if we need to copy it.
+        if (!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
+                && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
+                && isFilenameSafe(lastSlash + 1)) {
+            callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
+        } else if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+            callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
+        }
+    }
+
+    return INSTALL_SUCCEEDED;
+}
+
+static jint
+com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
+        jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
+{
+    return iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
+            copyFileIfChanged, &javaNativeLibPath);
+}
+
+static jlong
+com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
+        jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
+{
+    size_t totalSize = 0;
+
+    iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
+
+    return totalSize;
+}
+
+static JNINativeMethod gMethods[] = {
+    {"nativeCopyNativeBinaries",
+            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+            (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
+    {"nativeSumNativeBinaries",
+            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
+            (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
+};
+
+
+int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env)
+{
+    return AndroidRuntime::registerNativeMethods(env,
+                "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/core/jni/com_android_internal_graphics_NativeUtils.cpp b/core/jni/com_android_internal_graphics_NativeUtils.cpp
deleted file mode 100644
index 9cc43606..0000000
--- a/core/jni/com_android_internal_graphics_NativeUtils.cpp
+++ /dev/null
@@ -1,60 +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.
- */
-
-#define LOG_TAG "AWT"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "SkCanvas.h"
-#include "SkDevice.h"
-#include "SkPicture.h"
-#include "SkTemplates.h"
-
-namespace android
-{
-
-static jboolean scrollRect(JNIEnv* env, jobject graphics2D, jobject canvas, jobject rect, int dx, int dy) {
-    if (canvas == NULL) {
-        jniThrowNullPointerException(env, NULL);
-        return false;
-    }
-
-    SkIRect src, *srcPtr = NULL;
-    if (NULL != rect) {
-        GraphicsJNI::jrect_to_irect(env, rect, &src);
-        srcPtr = &src;
-    }
-    SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
-    const SkBitmap& bitmap = c->getDevice()->accessBitmap(true);
-    return bitmap.scrollRect(srcPtr, dx, dy, NULL);
-}
-
-static JNINativeMethod method_table[] = {
-    { "nativeScrollRect",
-      "(Landroid/graphics/Canvas;Landroid/graphics/Rect;II)Z",
-      (void*)scrollRect}
-};
-
-int register_com_android_internal_graphics_NativeUtils(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(
-        env, "com/android/internal/graphics/NativeUtils",
-        method_table, NELEM(method_table));
-}
-
-}
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 86fd9cb..7e5dede 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -27,13 +27,11 @@
 #include <JNIHelp.h>
 #include "android_runtime/AndroidRuntime.h"
 
-#ifdef HAVE_ANDROID_OS
 #include <linux/capability.h>
 #include <linux/prctl.h>
 #include <sys/prctl.h>
 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-#endif
 
 
 namespace android {
@@ -168,7 +166,6 @@
 static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
     jobject clazz, jlong permitted, jlong effective)
 {
-#ifdef HAVE_ANDROID_OS
     struct __user_cap_header_struct capheader;
     struct __user_cap_data_struct capdata;
     int err;
@@ -190,15 +187,11 @@
         jniThrowIOException(env, errno);
         return;
     }
-#endif /* HAVE_ANDROID_OS */
 }
 
 static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
     jobject clazz, jint pid)
 {
-#ifndef HAVE_ANDROID_OS
-    return (jlong)0;
-#else
     struct __user_cap_header_struct capheader;
     struct __user_cap_data_struct capdata;
     int err;
@@ -217,7 +210,6 @@
     }
 
     return (jlong) capdata.permitted;
-#endif /* HAVE_ANDROID_OS */
 }
 
 static jint com_android_internal_os_ZygoteInit_selectReadable (
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 49eaf19..92ba1d0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -292,6 +292,14 @@
         android:description="@string/permdesc_setAlarm"
         android:protectionLevel="normal" />
 
+   <!-- Allows an application to read/write the voicemails owned by its own
+        package. -->
+    <permission android:name="com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL"
+        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_readWriteOwnVoicemail"
+        android:description="@string/permdesc_readWriteOwnVoicemail" />
+
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
     <!-- ======================================= -->
@@ -385,8 +393,7 @@
         android:description="@string/permdesc_nfc"
         android:label="@string/permlab_nfc" />
 
-    <!-- Allows applications to provide VPN functionality.
-         @hide Pending API council approval -->
+    <!-- Allows applications to provide VPN functionality -->
     <permission android:name="android.permission.VPN"
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="dangerous"
@@ -1112,6 +1119,13 @@
         android:description="@string/permdesc_bindInputMethod"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a TextService (e.g. SpellCheckerService)
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_TEXT_SERVICE"
+        android:label="@string/permlab_bindTextService"
+        android:description="@string/permdesc_bindTextService"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_WALLPAPER"
@@ -1189,7 +1203,7 @@
     <permission android:name="android.permission.READ_FRAME_BUFFER"
         android:label="@string/permlab_readFrameBuffer"
         android:description="@string/permdesc_readFrameBuffer"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- Required to be able to disable the device (very dangerous!). -->
     <permission android:name="android.permission.BRICK"
@@ -1489,9 +1503,6 @@
                 android:excludeFromRecents="true">
         </activity>
 
-        <service android:name="com.android.server.LoadAverageService"
-                android:exported="true" />
-
         <service android:name="com.android.internal.service.wallpaper.ImageWallpaper"
                 android:permission="android.permission.BIND_WALLPAPER">
         </service>
diff --git a/core/res/res/anim/screen_rotate_minus_90_enter.xml b/core/res/res/anim/screen_rotate_minus_90_enter.xml
index 30518e0..61aa72a 100644
--- a/core/res/res/anim/screen_rotate_minus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_minus_90_enter.xml
@@ -19,11 +19,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="100%p" android:toXScale="100%"
-            android:fromYScale="100%p" android:toYScale="100%"
-            android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="-90" android:toDegrees="0"
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/decelerate_quint"
diff --git a/core/res/res/anim/screen_rotate_plus_90_enter.xml b/core/res/res/anim/screen_rotate_plus_90_enter.xml
index 20943c8..53b0ccd 100644
--- a/core/res/res/anim/screen_rotate_plus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_plus_90_enter.xml
@@ -19,11 +19,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="100%p" android:toXScale="100%"
-            android:fromYScale="100%p" android:toYScale="100%"
-            android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="90" android:toDegrees="0"
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/decelerate_quint"
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 8ea94e1..1b34672 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 8ea94e1..1b34672 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 6840962..71ae113 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index bee345e..739dff3 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index bee345e..26976c5 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index b3196c3..9d787f1 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index e83686a..7699c47 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index e83686a..7699c47 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index c44ae7a..1e9c9d2 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index 42e8ba4..27e7965 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index 42e8ba4..1dbabd3 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index e240a2d..12eec10 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index a24b13b..5a94b8d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index a24b13b..5a94b8d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark.9.png
index 61ea2b0..83b2bce 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light.9.png
index 83b2bce..61ea2b0 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
index daa47b7..9f3060d 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
index 6c45935..411f639 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
deleted file mode 100644
index ff6b34a..0000000
--- a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
rename to core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 5ce7321..918f972 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 5ce7321..918f972 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 9a24b9c..1ae6cf2 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 34f69d3f..0514a7c 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index 34f69d3f..8cc4daf 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index 93d9741..64496506 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 0629efe..7f44eae2 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index 0629efe..7f44eae2 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index f462d98..3e9e6c3 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index a2f411e..9df36a2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index a2f411e..7abdfde 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index 30373a6..df4927f 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index 231997a..cb70e35 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index 231997a..cb70e35 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png
deleted file mode 100644
index 41886eb..0000000
--- a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png
rename to core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..eb7ce5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..eb7ce5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
new file mode 100644
index 0000000..4e4d3d4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
new file mode 100644
index 0000000..ee291b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
new file mode 100644
index 0000000..83e5011
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
new file mode 100644
index 0000000..67f007ac
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
new file mode 100644
index 0000000..4764d1b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
new file mode 100644
index 0000000..4764d1b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
new file mode 100644
index 0000000..9f18a87
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
new file mode 100644
index 0000000..652aa3e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
new file mode 100644
index 0000000..92a7664
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
new file mode 100644
index 0000000..b949121
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
new file mode 100644
index 0000000..6a35514
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
new file mode 100644
index 0000000..9068d75
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
new file mode 100644
index 0000000..3f42693
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
new file mode 100644
index 0000000..daac2e1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
new file mode 100644
index 0000000..94f1a5a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
new file mode 100644
index 0000000..94f1a5a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
new file mode 100644
index 0000000..ecdc72b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
new file mode 100644
index 0000000..f823033
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
new file mode 100644
index 0000000..f537a6d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
new file mode 100644
index 0000000..1b11689
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
new file mode 100644
index 0000000..787ba9e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
new file mode 100644
index 0000000..74a156f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..44860dc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
index a5320a7..5b67d71 100644
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ b/core/res/res/layout-sw600dp/preference_list_content.xml
@@ -46,7 +46,6 @@
                 android:layout_weight="1"
                 android:paddingTop="16dp"
                 android:paddingBottom="16dp"
-
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
diff --git a/core/res/res/layout/activity_chooser_list_footer.xml b/core/res/res/layout/activity_chooser_list_footer.xml
deleted file mode 100644
index c05ba1a..0000000
--- a/core/res/res/layout/activity_chooser_list_footer.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android: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
deleted file mode 100644
index 0fb256f..0000000
--- a/core/res/res/layout/activity_chooser_list_header.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android: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
index ccf49fc..5d82a97 100644
--- a/core/res/res/layout/activity_chooser_view.xml
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -20,16 +20,52 @@
     android:id="@+id/activity_chooser_view_content"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
     style="?android:attr/actionButtonStyle">
 
-    <ImageButton android:id="@+id/default_activity_button"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_marginLeft="16dip" />
+    <FrameLayout
+        android:id="@+id/default_activity_button"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"
+        android:focusable="true"
+        android:addStatesFromChildren="true"
+        android:background="?android:attr/selectableItemBackground">
 
-    <ImageButton android:id="@+id/expand_activities_button"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_marginLeft="16dip" />
+        <ImageView android:id="@+id/image"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:layout_gravity="center"
+            android:layout_marginTop="4dip"
+            android:layout_marginBottom="4dip"
+            android:layout_marginLeft="8dip"
+            android:layout_marginRight="8dip"
+            android:scaleType="fitCenter"
+            android:adjustViewBounds="true" />
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/expand_activities_button"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"
+        android:focusable="true"
+        android:addStatesFromChildren="true"
+        android:background="?android:attr/selectableItemBackground">
+
+        <ImageView android:id="@+id/image"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:layout_gravity="center"
+            android:layout_marginTop="4dip"
+            android:layout_marginBottom="4dip"
+            android:layout_marginLeft="8dip"
+            android:layout_marginRight="8dip"
+            android:scaleType="fitCenter"
+            android:adjustViewBounds="true" />
+
+    </FrameLayout>
 
 </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
index 61b7e70..88498d9 100644
--- a/core/res/res/layout/activity_chooser_view_list_item.xml
+++ b/core/res/res/layout/activity_chooser_view_list_item.xml
@@ -18,26 +18,36 @@
     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">
+    android:paddingRight="16dip"
+    android:minWidth="196dip"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:orientation="vertical" >
 
-    <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" />
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        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" />
+        <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="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+            android:duplicateParentState="true"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 6ff14dd..27dd9b8 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,6 +19,10 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical"
-    android:layout_marginRight="8dip"
+    android:layout_marginLeft="8dip"
+    android:layout_marginRight="-8dip"
+    android:layout_marginTop="8dip"
+    android:layout_marginBottom="8dip"
+    android:scaleType="centerInside"
     android:duplicateParentState="true" />
 
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index fef017d..1a12c01 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -18,7 +18,6 @@
     android:layout_width="match_parent"
     android:layout_height="?android:attr/dropdownListPreferredItemHeight"
     android:minWidth="196dip"
-    android:paddingLeft="16dip"
     android:paddingRight="16dip">
     
     <!-- Icon will be inserted here. -->
@@ -29,6 +28,7 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
+        android:layout_marginLeft="16dip"
         android:duplicateParentState="true">
         
         <TextView 
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index fb898ee..4e7981a 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -44,8 +44,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="0px"
                 android:layout_weight="1"
-                android:paddingTop="16dp"
-                android:paddingBottom="16dp"
+                android:paddingTop="@dimen/preference_screen_header_vertical_padding"
+                android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 790ac6b..f6b5b53 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -66,7 +66,6 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:maxWidth="600dip"
-            android:iconifiedByDefault="false"
             android:layout_gravity="center_vertical"
             />
 
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index 53906f9..acef2cc 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -19,21 +19,21 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="4dip"
-    android:paddingRight="2dip"
+    android:paddingLeft="@dimen/dropdownitem_text_padding_left"
+    android:paddingRight="4dip"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/searchResultListItemHeight" >
 
     <!-- Icons come first in the layout, since their placement doesn't depend on
          the placement of the text views. -->
     <ImageView android:id="@android:id/icon1"
-        android:layout_width="48dip"
+        android:layout_width="@dimen/dropdownitem_icon_width"
         android:layout_height="48dip"
         android:scaleType="centerInside"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
-        android:visibility="gone" />
+        android:visibility="invisible" />
 
     <ImageView android:id="@+id/edit_query"
         android:layout_width="48dip"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index fee27eb..6b70d8d 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -22,6 +22,8 @@
     android:id="@+id/search_bar"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip"
     android:orientation="horizontal"
     >
 
@@ -30,7 +32,7 @@
         android:id="@+id/search_badge"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
+        android:gravity="center_vertical"
         android:layout_marginBottom="2dip"
         android:drawablePadding="0dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -54,12 +56,21 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip"
         android:layout_marginTop="4dip"
         android:layout_marginBottom="4dip"
         android:orientation="horizontal">
 
+        <ImageView
+            android:id="@+id/search_mag_icon"
+            android:layout_width="@dimen/dropdownitem_icon_width"
+            android:layout_height="wrap_content"
+            android:scaleType="centerInside"
+            android:layout_marginLeft="@dimen/dropdownitem_text_padding_left"
+            android:layout_gravity="center_vertical"
+            android:src="?android:attr/searchViewSearchIcon"
+            android:visibility="gone"
+        />
+
         <!-- Inner layout contains the app icon, button(s) and EditText -->
         <LinearLayout
             android:id="@+id/search_plate"
@@ -70,14 +81,6 @@
             android:orientation="horizontal"
             android:background="?android:attr/searchViewTextField">
 
-            <ImageView
-                android:id="@+id/search_app_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_gravity="center_vertical"
-                android:src="?android:attr/searchViewSearchIcon"
-            />
-
             <view class="android.widget.SearchView$SearchAutoComplete"
                 android:id="@+id/search_src_text"
                 android:layout_height="36dip"
@@ -85,8 +88,8 @@
                 android:layout_weight="1"
                 android:minWidth="@dimen/search_view_text_min_width"
                 android:layout_gravity="bottom"
-                android:paddingLeft="8dip"
-                android:paddingRight="6dip"
+                android:paddingLeft="@dimen/dropdownitem_text_padding_left"
+                android:paddingRight="@dimen/dropdownitem_text_padding_right"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
@@ -100,7 +103,7 @@
 
             <ImageView
                 android:id="@+id/search_close_btn"
-                android:layout_width="wrap_content"
+                android:layout_width="@dimen/dropdownitem_icon_width"
                 android:layout_height="match_parent"
                 android:paddingLeft="8dip"
                 android:paddingRight="8dip"
@@ -131,7 +134,7 @@
                 android:visibility="gone"
                 android:focusable="true"
             />
-    
+
             <ImageView
                 android:id="@+id/search_voice_btn"
                 android:layout_width="wrap_content"
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index ef537d9..082c5ec 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -22,6 +22,8 @@
           android:paddingTop="8dip"
           android:paddingBottom="8dip"
           android:layout_gravity="left|center_vertical"
+          android:singleLine="true"
+          android:ellipsize="marquee"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:textColor="@android:color/dim_foreground_light" />
 
diff --git a/core/res/res/layout/text_edit_suggestions_top_window.xml b/core/res/res/layout/text_edit_suggestions_window.xml
similarity index 98%
rename from core/res/res/layout/text_edit_suggestions_top_window.xml
rename to core/res/res/layout/text_edit_suggestions_window.xml
index 67faa37..824025e 100644
--- a/core/res/res/layout/text_edit_suggestions_top_window.xml
+++ b/core/res/res/layout/text_edit_suggestions_window.xml
@@ -18,6 +18,6 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_top_window">
+    android:background="@android:drawable/text_edit_suggestions_window">
 
 </LinearLayout>
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/core/res/res/layout/wifi_p2p_go_negotiation_request_alert.xml
similarity index 77%
rename from core/res/res/layout/text_edit_suggestions_bottom_window.xml
rename to core/res/res/layout/wifi_p2p_go_negotiation_request_alert.xml
index 588bfbd..41ca657 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/core/res/res/layout/wifi_p2p_go_negotiation_request_alert.xml
@@ -4,9 +4,9 @@
      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.
@@ -16,8 +16,11 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
+    android:layout_height="wrap_content">
 
+    <EditText android:id="@+id/wifi_p2p_wps_pin"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:inputType="textPassword"
+    />
 </LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 8a75bd0..e60af6d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -385,6 +385,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Laat programme toe om te sien watter sleutels jy druk, selfs wanneer jy met \'n ander program werk (soos wanneer jy \'n wagwoord intik). Behoort vir gewone programme nooit nodig te wees nie."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"bind aan \'n invoermetode"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Laat die houer toe om aan die topvlak-koppelvlak van \'n invoermetode te bind. Behoort vir gewone programme nooit nodig te wees nie."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind aan \'n muurpapier"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Stel die houer toe om aan die topvlak-koppelvlak van \'n muurpapier te bind. Behoort vir gewone programme nooit nodig te wees nie."</string>
     <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -931,6 +935,30 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <!-- no translation found for autofill_province (2231806553863422300) -->
+    <skip />
+    <!-- no translation found for autofill_postal_code (4696430407689377108) -->
+    <skip />
+    <!-- no translation found for autofill_state (6988894195520044613) -->
+    <skip />
+    <!-- no translation found for autofill_zip_code (8697544592627322946) -->
+    <skip />
+    <!-- no translation found for autofill_county (237073771020362891) -->
+    <skip />
+    <!-- no translation found for autofill_island (4020100875984667025) -->
+    <skip />
+    <!-- no translation found for autofill_district (8400735073392267672) -->
+    <skip />
+    <!-- no translation found for autofill_department (5343279462564453309) -->
+    <skip />
+    <!-- no translation found for autofill_prefecture (2028499485065800419) -->
+    <skip />
+    <!-- no translation found for autofill_parish (8202206105468820057) -->
+    <skip />
+    <!-- no translation found for autofill_area (3547409050889952423) -->
+    <skip />
+    <!-- no translation found for autofill_emirate (2893880978835698818) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lees blaaier se geskiedenis en boekmerke"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Laat die program toe om al die URL\'e te lees wat die blaaier besoek het, asook al die blaaier se boekmerke."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skryf blaaier se geskiedenis en boekmerke"</string>
@@ -938,6 +966,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Laat \'n program toe om die blaaier se geskiedenis of gestoorde boekmerke op die foon te wysig. Kwaadwillige programme kan dit gebruik om jou blaaier se data uit te vee of dit te wysig."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"stel alarm in wekker"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Laat die program toe om \'n alarm te stel in \'n geïnstalleerde wekkerprogram. Sommige wekkerprogramme sal dalk nie hierdie kenmerk implementeer nie."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Wysig blaaier se geoligging-toestemmings"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Laat \'n program toe om die blaaier se geoligging-toestemmings te wysig. Kwaadwillige programme kan dit gebruik om liggingsinligting na arbitrêre webwerwe te stuur."</string>
     <!-- no translation found for save_password_message (767344687139195790) -->
@@ -1192,6 +1224,22 @@
     <item quantity="one" msgid="1634101450343277345">"Oop Wi-Fi-netwerke beskikbaar"</item>
     <item quantity="other" msgid="7915895323644292768">"Oop Wi-Fi-netwerke beskikbaar"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Voeg karakter in"</string>
     <!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
     <skip />
@@ -1253,6 +1301,8 @@
     <skip />
     <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
     <skip />
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+    <skip />
     <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formateer USB-berging"</string>
@@ -1437,8 +1487,10 @@
     <skip />
     <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+    <skip />
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 52745b9..716d19f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -385,6 +385,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"ትግበራዎች ከሌላ ትግበራዎች ጋር እንኳ ሲገናኙ የሚጫኑትን ቁልፎች ለመመልከት ይፈቅዳሉ።ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"በግቤት ሜተድ ጠርዝ"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"ያዡ ግቤት ሜተዱን ወደ ከፍተኛ-ደረጃ በይነገጽ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"በልጣፍ ጠርዝ"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"ያዡ ግቤት ሜተዱን ወደ ከፍተኛ-ደረጃ ልጣፍ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
     <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -931,6 +935,30 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"፣ "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <!-- no translation found for autofill_province (2231806553863422300) -->
+    <skip />
+    <!-- no translation found for autofill_postal_code (4696430407689377108) -->
+    <skip />
+    <!-- no translation found for autofill_state (6988894195520044613) -->
+    <skip />
+    <!-- no translation found for autofill_zip_code (8697544592627322946) -->
+    <skip />
+    <!-- no translation found for autofill_county (237073771020362891) -->
+    <skip />
+    <!-- no translation found for autofill_island (4020100875984667025) -->
+    <skip />
+    <!-- no translation found for autofill_district (8400735073392267672) -->
+    <skip />
+    <!-- no translation found for autofill_department (5343279462564453309) -->
+    <skip />
+    <!-- no translation found for autofill_prefecture (2028499485065800419) -->
+    <skip />
+    <!-- no translation found for autofill_parish (8202206105468820057) -->
+    <skip />
+    <!-- no translation found for autofill_area (3547409050889952423) -->
+    <skip />
+    <!-- no translation found for autofill_emirate (2893880978835698818) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"የአሳሽ ታሪኮች እና ዕልባቶች አንብብ።"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ትግበራው ማሰሻው የጎበኛቸውን ሁሉ URL ኦች፣ እና የማሰሻውን ዕልባቶች ሁሉ  ለማንበብ ይፈቅዳል።"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"የአሳሾች ታሪክ እና ዕልባቶች ፃፍ"</string>
@@ -938,6 +966,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"ትግበራ በስልክዎ ላይ የተከማቹትንታሪኮች እና ዕልባቶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለማጥፋት ወይም ለመቀየር ይህን መጠቀም ይችላሉ።"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"በማንቂያ ሰዓት ውስጥ ማንቂያ አዘጋጅ"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"ትግበራ በተጫነ የማንቂያ ሰዓት ትግበራ ማንቂያ ለማዘጋጀትይፈቅዳል። አንዳንድ የማንቂያ ሰዓት ትግበራዎች ይህን ገፅታ ላይተገብሩ ይችላሉ።"</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"የአሳሽ ገፀ ሥፍራ ፍቃዶችን ቀይር"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ትግበራ የአሳሹን ገፀ ሥፍራ ፈቃዶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች ይህን በመጠቀም የሥፍራ መረጃን ወደ ድረ ገፆች ለመላክ ይችላሉ።"</string>
     <!-- no translation found for save_password_message (767344687139195790) -->
@@ -1192,6 +1224,22 @@
     <item quantity="one" msgid="1634101450343277345">"አውታረ መረብ ሲኖር Wi-Fi ክፈት"</item>
     <item quantity="other" msgid="7915895323644292768">"አውታረ መረቦች ሲኖሩ Wi-Fi ክፈት"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"ቁምፊ አስገባ"</string>
     <!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
     <skip />
@@ -1253,6 +1301,8 @@
     <skip />
     <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
     <skip />
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+    <skip />
     <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"የUSB ማከማቻ ቅረፅ"</string>
@@ -1437,8 +1487,10 @@
     <skip />
     <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+    <skip />
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f37410b..12a240a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"للسماح للتطبيقات بمراقبة الأحرف التي تضغط عليها حتى عند التفاعل مع تطبيق آخر (مثل إدخال كلمة مرور). لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"الالتزام بطريقة إرسال ما"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لطريقة الإرسال. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"الالتزام بخلفية ما"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للخلفية. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"الإقليم"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"الرمز البريدي"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"الولاية"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"الرمز البريدي"</string>
+    <string name="autofill_county" msgid="237073771020362891">"المقاطعة"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"جزيرة"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"المنطقة"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"القسم"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"المحافظة"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"الدائرة"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"المنطقة"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"الإمارة"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"قراءة سجل المتصفح والإشارات"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"للسماح للتطبيق بقراءة جميع عناوين URL التي انتقل إليها المتصفح. وجميع إشارات المتصفح."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"كتابة سجل المتصفح والإشارات"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"للسماح لتطبيق ما بتعديل سجل المتصفح أو الإشارات في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات المتصفح أو تعديلها."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"تعيين المنبه في ساعة المنبه"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"للسماح للتطبيق بضبط المنبه في تطبيق ساعة منبه مثبّت. ربما لا تنفذ بعض تطبيقات المنبه هذه الميزة."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"تعديل أذونات الموقع الجغرافي للمتصفح"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"للسماح لتطبيق ما بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع ويب عشوائية."</string>
     <string name="save_password_message" msgid="767344687139195790">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"هناك شبكة Wi-Fi مفتوحة متاحة"</item>
     <item quantity="other" msgid="7915895323644292768">"هناك شبكات Wi-Fi مفتوحة متاحة"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"تطبيق غير معروف"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"إرسال رسائل قصيرة SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"التوصيل كجهاز وسائط"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"التوصيل ككاميرا"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"التوصيل كأداة تثبيت"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"المس للاطلاع على خيارات USB الأخرى"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"هل تريد تهيئة وحدة تخزين USB، ومحو كل الملفات المخزنة بها؟ لا يمكن عكس هذا الإجراء!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الدخول"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"تم تنشيط الشبكة الظاهرية الخاصة (VPN)."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"تم تنشيط الشبكة الظاهرية الخاصة (VPN) بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"الرقم المسلسل:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"بصمات الأصابع:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"بصمة أصبع SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"بصمة أصبع SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"عرض الكل..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"تحديد نشاط"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"مشاركة مع..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9147fb5..f20ef1b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Разрешава на приложенията да наблюдават кои клавиши натискате дори и когато взаимодействате с друго приложение (например когато въвеждате парола). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"обвързване с метод на въвеждане"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на метод на въвеждане. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обвързване с тапет"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на тапет. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Провинция"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Пощенски код"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Щат"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Пощенски код"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Окръг"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Остров"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Област"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Департамент"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Община"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Район"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Емирство"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"четене на историята и отметките на браузъра"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешава на приложението да чете всички URL адреси, посетени от браузъра, и всички негови отметки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис в историята и отметките на браузъра"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени на телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят данните на браузъра ви."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"навиване на будилника"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Промяна на разрешенията за местоположение в браузъра"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string>
     <string name="save_password_message" msgid="767344687139195790">"Искате ли браузърът да запомни тази парола?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Има достъпна отворена Wi-Fi мрежа"</item>
     <item quantity="other" msgid="7915895323644292768">"Има достъпни отворени Wi-Fi мрежи"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Вмъкване на знак"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Неизвестно приложение"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Изпращане на SMS съобщения"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Свързан като медийно устройство"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Свързан като камера"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Свързан като инсталационна програма"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Докоснете за други опции за USB"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Да се форматира ли USB хранилището, изтривайки всички файлове в него? Действието не може да бъде отменено!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Достъпност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN е активирана."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Сериен номер:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Пръстови отпечатъци:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Пръстов отпечатък SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Пръстов отпечатък SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Вижте всички..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b7117b9..cb57c33 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permet a les aplicacions fer un seguiment de les tecles que premeu, fins i tot quan s\'interactua amb una altra aplicació (com ara introduir una contrasenya). No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a un mètode d\'entrada"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permet al titular vincular amb la interfície de nivell superior d\'un mètode d\'entrada. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un empaperat"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permet al titular vincular amb la interfície de nivell superior d\'un empaperat. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Província"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Codi postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Codi postal"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Comtat"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Illa"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Districte"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Districte"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Àrea"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"llegir l\'historial i les adreces d\'interès del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permet a l\'aplicació llegir tots els URL que ha visitat el navegador i totes les adreces d\'interès del navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escriure l\'historial i les adreces d\'interès del navegador"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet a una aplicació modificar l\'historial o les adreces d\'interès del navegador emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades del navegador."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"defineix l\'alarma com a despertador"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica els permisos d\'ubicació geogràfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet a una aplicació modificar els permisos d\'ubicació geogràfica del navegador. Les aplicacions malicioses poden utilitzar-ho per permetre l\'enviament d\'informació d\'ubicació a llocs web arbitraris."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voleu que el navegador recordi aquesta contrasenya?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Xarxa Wi-fi oberta disponible"</item>
     <item quantity="other" msgid="7915895323644292768">"Xarxes Wi-fi obertes disponibles"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Insereix un caràcter"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicació desconeguda"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"S\'estan enviant missatges SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a dispositiu multimèdia"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connectat com a càmera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connectat com a instal·lador"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Toca per obtenir altres opcions d\'USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vols formatar l\'emmagatzematge USB i esborrar tots els fitxers que hi ha emmagatzemats? L\'acció no es podrà desfer."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN activada."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Número de sèrie:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Empremtes"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Empremta SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empremta SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra-ho tot"</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Selecció d\'activitat"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Ús compartit amb..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ecd83dd..c074e7b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Umožňuje aplikacím sledovat, které klávesy používáte, a to i při práci s jinými aplikacemi (například při zadávání hesla). Běžné aplikace by toto nastavení nikdy neměly vyžadovat."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vazba k metodě zadávání dat"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Umožňuje držiteli vázat se na nejvyšší úroveň rozhraní pro zadávání dat. Běžné aplikace by toto nastavení nikdy neměly využívat."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vazba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní tapety. Běžné aplikace by toto oprávnění nikdy neměly potřebovat."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"PSČ"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Stát"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"PSČ"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Okres"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ostrov"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Okres"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Department"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Farnost"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Oblast"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirát"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čtení historie a záložek Prohlížeče"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikaci číst všechny navštívené adresy URL a záložky Prohlížeče."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zápis do historie a záložek Prohlížeče"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umožní aplikaci změnit historii či záložky prohlížeče uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit data Prohlížeče."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"nastavit budík v budíku"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Dovoluje aplikaci nastavit budík v nainstalované aplikaci budíku. Některé budíkové aplikace nemusí tuto funkci implementovat."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikaci změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze. Škodlivé aplikace mohou toto nastavení použít k odesílání informací o umístění na libovolné webové stránky."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"K dispozici je veřejná síť WiFi"</item>
     <item quantity="other" msgid="7915895323644292768">"Jsou k dispozici veřejné sítě WiFi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Vkládání znaků"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznámá aplikace"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odesílání zpráv SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Připojeno jako mediální zařízení"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Připojeno jako fotoaparát"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Připojeno jako instalátor"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Dotykem zobrazíte další možnosti USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete úložiště USB zformátovat a tím smazat všechny soubory, které v něm jsou uloženy? Tuto akci nelze vrátit zpět."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Síť VPN je aktivována."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Sériové číslo:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Digitální otisky:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Digitální otisk SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Digitální otisk SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Zobrazit vše..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Vybrat činnost"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Sdílet..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 67de2aa..0038b29 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Tillader, at en applikation registrerer taster, du trykker på, selv når du interagerer med andre applikationer (f.eks. ved indtastning af adgangskode). Bør aldrig være nødvendigt til normale applikationer."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"forpligt til en inputmetode"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Tillader, at brugeren forpligter sig til en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendig til normale applikationer."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"forpligt til et tapet"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Tillader, at brugeren forpligter sig til et tapets grænseflade på øverste niveau. Bør aldrig være nødvendig til normale applikationer."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Stat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Amt"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ø"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Afdeling"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Præfektur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Sogn"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og bogmærker"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at applikationen læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Tillader, at en applikation ændrer browseroversigten eller bogmærker, der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at slette eller ændre din browsers data."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"angiv alarm i alarmprogram"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillader, at applikationen angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Skift browsertilladelser for geografisk placering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Giver en applikation tilladelse til at ændre browserens tilladelser for geografisk placering. Skadelige applikationer kan bruge dette til at tillade, at placeringsoplysninger sendes til vilkårlige websteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Åbent Wi-Fi-netværk tilgængeligt"</item>
     <item quantity="other" msgid="7915895323644292768">"Der er åbne Wi-Fi-netværk tilgængelige"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukendt applikation"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilsluttet som en medieenhed"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilsluttet som et kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilsluttet som et installationsprogram"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Tryk for at se andre valgmuligheder for USB-tilslutning"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lager og slette alle filer, som er gemt der? Handlingen kan ikke fortrydes!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN er aktiveret."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingeraftryk:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeraftryk:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeraftryk:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Se alle..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Vælg aktivitet"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b4203b6..508b65d 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Ermöglicht Anwendungen, die von Ihnen gedrückten Tasten zu überwachen (etwa die Eingabe eines Passworts). Dies gilt auch für die Interaktion mit anderen Anwendungen. Sollte für normale Anwendungen nicht benötigt werden."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"An eine Eingabemethode binden"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Anwendungen benötigt werden."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"An einen Hintergrund binden"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Anwendungen benötigt werden."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provinz"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postleitzahl"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Bundesstaat/-land"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postleitzahl"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Landkreis"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Insel"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Bezirk"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Distrikt"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Präfektur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Gemeinde"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Gebiet"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Browserverlauf und Lesezeichen lesen"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der App, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Browserverlauf und Lesezeichen schreiben"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ermöglicht einer App, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"Alarm im Wecker festlegen"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ermöglicht dieser Anwendung, einen Alarm mithilfe eines installierten Weckers festzulegen. Einige Weckeranwendungen verfügen möglicherweise nicht über diese Funktion."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ermöglicht einer App, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Anwendungen können dies nutzen, um das Senden von Standortinformationen an willkürliche Websites zuzulassen."</string>
     <string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Verfügbares WLAN-Netzwerk öffnen"</item>
     <item quantity="other" msgid="7915895323644292768">"Verfügbare WLAN-Netzwerke öffnen"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Unbekannte Anwendung"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Kurznachrichten werden gesendet"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Als Mediengerät angeschlossen"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Als Kamera angeschlossen"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Als Installationsprogramm angeschlossen"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Zum Anzeigen weiterer USB-Optionen tippen"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-Speicher formatieren und alle darin befindlichen Dateien löschen? Diese Aktion kann nicht rückgängig gemacht werden!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN ist aktiviert."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Seriennummer:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingerabdrücke:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-Fingerabdruck:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-Fingerabdruck:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Alle anzeigen..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index ae72132..1bf806a 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Επιτρέπει σε εφαρμογές να παρακολουθούν τα πλήκτρα που πατάτε, ακόμη και σε μια άλλη εφαρμογή (όπως π.χ. η καταχώρηση ενός κωδικού πρόσβασης). Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"δέσμευση σε μέθοδο εισόδου"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας μεθόδου εισόδου. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"δέσμευση σε ταπετσαρία"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας ταπετσαρίας. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Επαρχία"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Ταχυδρομικός κώδικας"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Πολιτεία"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Ταχυδρομικός κώδικας"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Κομητεία"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Νησί"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Περιφέρεια"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Τμήμα"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Νομός"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Ενορία"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Περιοχή"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Εμιράτο"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ανάγνωση ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Επιτρέπει σε μια εφαρμογή να τροποποιήσει το ιστορικό ή τους σελιδοδείκτες του προγράμματος περιήγησης που βρίσκονται αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα του προγράμματος περιήγησης."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"ρύθμιση ειδοποίησης σε ξυπνητήρι"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Επιτρέπει στην εφαρμογή να ρυθμίσει μια ειδοποίηση σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Κάποιες εφαρμογές ξυπνητηριού ενδέχεται να μην περιλαμβάνουν αυτή τη λειτουργία."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Τροποποίηση δικαιωμάτων γεωγραφικής θέσης προγράμματος περιήγησης"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των δικαιωμάτων γεωγραφικής θέσης του προγράμματος περιήγησης. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή στοιχείων τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
     <string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Εισαγωγή χαρακτήρα"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Άγνωστη εφαρμογή"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Αποστολή μηνυμάτων SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Συνδεδεμένο ως συσκευή πολυμέσων"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Συνδεδεμένο ως φωτογραφική μηχανή"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Συνδεδεμένο ως πρόγραμμα εγκατάστασης"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Αγγίξτε για άλλες επιλογές USB"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Να γίνει διαγραφή του αποθηκευτικού χώρου USB, η οποία θα διαγράψει όλα τα αρχεία που έχετε αποθηκεύσει εκεί; Η ενέργεια είναι μη αναστρέψιμη!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Προσβασιμότητα"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Το VPN είναι ενεργοποιημένο."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Σειριακός αριθμός:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Αποτυπώματα"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Αποτύπωμα SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Αποτύπωμα SHA-1"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Εμφάνιση όλων..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d26628c..a22fafc 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"bind to an input method"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Province"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postcode"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"State"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Zip code"</string>
+    <string name="autofill_county" msgid="237073771020362891">"County"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Island"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Department"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefecture"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Parish"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Area"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirate"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"read Browser\'s history and bookmarks"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"write Browser\'s history and bookmarks"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"set alarm in alarm clock"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modify Browser geo-location permissions"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Allows an application to modify the browser\'s geo-location permissions. Malicious applications can use this to allow the sending of location information to arbitrary websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Do you want the browser to remember this password?"</string>
@@ -860,12 +880,9 @@
     <string name="launch_warning_title" msgid="8323761616052121936">"Application redirected"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> is now running."</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> was originally launched."</string>
-    <!-- no translation found for screen_compat_mode_scale (3202955667675944499) -->
-    <skip />
-    <!-- no translation found for screen_compat_mode_show (4013878876486655892) -->
-    <skip />
-    <!-- no translation found for screen_compat_mode_hint (2953716574198046484) -->
-    <skip />
+    <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scale"</string>
+    <string name="screen_compat_mode_show" msgid="4013878876486655892">"Always show"</string>
+    <string name="screen_compat_mode_hint" msgid="2953716574198046484">"Reenable this with Settings &gt; Applications &gt; Manage applications."</string>
     <string name="smv_application" msgid="295583804361236288">"The application <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced StrictMode policy."</string>
     <string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
@@ -899,24 +916,34 @@
     <item quantity="one" msgid="1634101450343277345">"Open available Wi-Fi network"</item>
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Insert character"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Unknown application"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sending SMS messages"</string>
     <string name="sms_control_message" msgid="1289331457999236205">"A large number of SMS messages are being sent. Select \"OK\" to continue or \"Cancel\" to stop sending."</string>
     <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
     <string name="sms_control_no" msgid="1715320703137199869">"Cancel"</string>
-    <!-- no translation found for sim_removed_title (6227712319223226185) -->
-    <skip />
-    <!-- no translation found for sim_removed_message (2064255102770489459) -->
-    <skip />
-    <!-- no translation found for sim_done_button (827949989369963775) -->
-    <skip />
-    <!-- no translation found for sim_added_title (3719670512889674693) -->
-    <skip />
-    <!-- no translation found for sim_added_message (1209265974048554242) -->
-    <skip />
-    <!-- no translation found for sim_restart_button (4722407842815232347) -->
-    <skip />
+    <string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
+    <string name="sim_removed_message" msgid="2064255102770489459">"The mobile network will be unavailable until you replace the SIM card."</string>
+    <string name="sim_done_button" msgid="827949989369963775">"Done"</string>
+    <string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
+    <string name="sim_added_message" msgid="1209265974048554242">"You must restart your device to access the mobile network."</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
@@ -944,14 +971,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connected as a media device"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connected as a camera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connected as an installer"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Touch for other USB options"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format USB storage, erasing all files stored there? Action cannot be reversed!"</string>
@@ -1015,10 +1040,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN is activated."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1118,13 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serial number:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingerprints:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 fingerprint"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 fingerprint"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"See all..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Select activity"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Share with..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 305b131..7c61d39 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Admite que las aplicaciones observen las teclas que presionas, incluso al interactuar con otra aplicación (como el ingreso de una contraseña). Se debe evitar utilizarlo en aplicaciones normales."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a un método de entrada"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite al propietario vincularse a la interfaz de nivel superior de un método de entrada. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Se debe evitar utilizarlo en aplicaciones normales."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Condado"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Isla"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Circunscripción"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer historial y marcadores del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los marcadores del navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir historial y marcadores del navegador"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite a una aplicación modificar el historial y los marcadores del navegador almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"configurar alarma en reloj alarma"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que la aplicación configure una alarma en una aplicación instalada de reloj alarma. Es posible que algunas aplicaciones de reloj alarma no implementen esta función."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizarlos para permitir el envío de información sobre la ubicación a sitos web de forma arbitraria."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Abrir red disponible de Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Abrir redes disponibles de Wi-Fi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Insertar caracteres"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicación desconocida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como un instalador"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Toca para otras opciones de USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Deseas formatear el almacenamiento USB y borrar todos los archivos almacenados aquí? ¡Esta acción no se puede cambiar!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN está activado."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Número de serie:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Huellas digitales:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleccionar actividad"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f3d1d66..1179764 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permite que las aplicaciones observen las teclas que pulsas incluso cuando interactúas con otra aplicación (como, por ejemplo, al introducir una contraseña). No debería ser necesario nunca para las aplicaciones normales."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"enlazar con un método de introducción de texto"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite enlazar con la interfaz de nivel superior de un método de introducción de texto. No debe ser necesario para las aplicaciones normales."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enlazar con un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite enlazar con la interfaz de nivel superior de un fondo de pantalla. No debe ser necesario para las aplicaciones normales."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string>
@@ -519,7 +523,7 @@
     <item msgid="7897544654242874543">"Trabajo"</item>
     <item msgid="1103601433382158155">"Fax del trabajo"</item>
     <item msgid="1735177144948329370">"Fax de casa"</item>
-    <item msgid="603878674477207394">"Buscapersonas"</item>
+    <item msgid="603878674477207394">"Busca"</item>
     <item msgid="1650824275177931637">"Otro"</item>
     <item msgid="9192514806975898961">"Personalizar"</item>
   </string-array>
@@ -562,7 +566,7 @@
     <string name="phoneTypeWork" msgid="8863939667059911633">"Trabajo"</string>
     <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax del trabajo"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax de casa"</string>
-    <string name="phoneTypePager" msgid="7582359955394921732">"Buscapersonas"</string>
+    <string name="phoneTypePager" msgid="7582359955394921732">"Busca"</string>
     <string name="phoneTypeOther" msgid="1544425847868765990">"Otro"</string>
     <string name="phoneTypeCallback" msgid="2712175203065678206">"Devolución de llamada"</string>
     <string name="phoneTypeCar" msgid="8738360689616716982">"Coche"</string>
@@ -574,7 +578,7 @@
     <string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
     <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Móvil del trabajo"</string>
-    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Buscapersonas del trabajo"</string>
+    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Busca del trabajo"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistente"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
     <string name="eventTypeCustom" msgid="7837586198458073404">"Personalizados"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Condado"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Isla"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Distrito"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer información de marcadores y del historial del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir en marcadores y en el historial del navegador"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"establecer alarma en un reloj"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite a la aplicación establecer una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden utilizar este permiso para permitir el envío de información sobre la ubicación a sitios web arbitrarios."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Deseas que el navegador recuerde esta contraseña?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Red Wi-Fi abierta disponible"</item>
     <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abiertas disponibles"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Insertar carácter"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicación desconocida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS..."</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como instalador"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Tocar para acceder a otras opciones de USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Quieres formatear el USB y borrar todos los archivos? Esta acción no se puede deshacer."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN activada"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Número de serie:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Huellas digitales:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleccionar actividad"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index aae9760..35fc0b9 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"به برنامه های کاربردی اجازه می دهد حتی زمانی که با برنامه دیگری در حال ارتباط هستید (مانند وارد کردن یک رمز ورود)، بتوانند کلیدهایی را که فشار می دهید ببینند. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"پیوند شده به روش ورودی"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"به نگهدارنده اجازه می دهد به رابط سطح بالای یک روش ورودی متصل شود. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"پیوند شده به تصویر زمینه"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"به نگهدارنده اجازه می دهد که به رابط سطح بالای تصویر زمینه متصل شود. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"استان"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"کد پستی"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"ایالت"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"کد پستی"</string>
+    <string name="autofill_county" msgid="237073771020362891">"بخش"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"جزیره"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"حوزه"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"اداره"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"حوزه اداری"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"ناحیه"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"منطقه"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"امارات"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"خواندن سابقه و نشانک های مرورگر"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"به برنامه کاربردی اجازه می دهد تا تمام URL های بازدید شده توسط مرورگر و تمام نشانک های آن را بخواند."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"نوشتن سابقه مرورگر و نشانک ها"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"به یک برنامه کاربردی اجازه می دهد سابقه مرورگر یا نشانک ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر داده های مرورگر شما استفاده کنند."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"تنظیم هشدار در ساعت زنگ دار"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"به برنامه کاربردی برای تنظیم یک هشدار در یک برنامه ساعت زنگ دار نصب شده اجازه می دهد. در برخی از برنامه های ساعت زنگ دار ممکن است این ویژگی اجرا نشود."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"اصلاح کردن مجوزهای مکان جغرافیایی مرورگر"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"به یک برنامه کاربردی اجازه می دهد مجوزهای مکان جغرافیایی مرورگر را تغییر دهد. برنامه های مضر می توانند از این گزینه استفاده کرده و اطلاعات مربوط به مکان را به وب سایت های غیر قانونی ارسال کنند."</string>
     <string name="save_password_message" msgid="767344687139195790">"می خواهید مرورگر این رمز ورود را به خاطر داشته باشد؟"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"شبکه Wi-Fi موجود را باز کنید"</item>
     <item quantity="other" msgid="7915895323644292768">"شبکه های Wi-Fi موجود را باز کنید"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"برنامه ناشناس"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه ای"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به عنوان دوربین"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به عنوان نصب کننده"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"برای سایر گزینه های USB لمس کنید"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"فرمت کردن حافظه USB، همه فایل های ذخیره شده در آنجا پاک شود؟ عملکرد قابل بازگشت نیست!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"قابلیت دسترسی"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN فعال است."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <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>
@@ -1067,7 +1099,7 @@
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"از حد مجاز حذف فراتر رفت"</string>
     <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> مورد حذف شده برای <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>، حساب <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> وجود دارد. می خواهید چه کاری انجام دهید؟"</string>
     <string name="sync_really_delete" msgid="8933566316059338692">"موارد را حذف کنید."</string>
-    <string name="sync_undo_deletes" msgid="8610996708225006328">"واگرد موارد حذف شده."</string>
+    <string name="sync_undo_deletes" msgid="8610996708225006328">"لغو موارد حذف شده."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"اکنون هیچ کاری انجام نشود."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"انتخاب یک حساب"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"افزایش"</string>
@@ -1093,20 +1125,15 @@
     <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="issued_on" msgid="5895017404361397232">"صادر شده در:"</string>
     <string name="expires_on" msgid="3676242949915959821">"تاریخ انقضا:"</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) -->
+    <string name="serial_number" msgid="758814067660862493">"شماره سریال:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"اثر انگشت:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"اثر انگشت SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"اثر انگشت SHA-1"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"مشاهده همه..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"انتخاب فعالیت"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"اشتراک گذاری با..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 962383a..2e3f921 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Antaa sovelluksien tarkkailla painamiasi näppäimiä jopa toisten sovellusten käytön yhteydessä (kuten salasanoja syötettäessä). Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"sitoudu syöttötapaan"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Antaa sovelluksen sitoutua syöttötavan ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Antaa sovelluksen sitoutua taustakuvan ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provinssi"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postinumero"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Osavaltio"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postinumero"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Lääni"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Saari"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Piiri"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Osasto"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektuuri"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Kunta"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Alue"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emiraatti"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lue selaimen historiaa ja kirjanmerkkejä"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Antaa sovelluksen lukea kaikki selaimen käyttämät URL-osoitteet ja selaimen kirjanmerkit."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"kirjoita selaimen historiaa ja kirjanmerkkejä"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Antaa sovelluksen muokata puhelimeen tallennettuja selaimen historia- ja kirjanmerkkitietoja. Haitalliset sovellukset voivat käyttää tätä pyyhkiäkseen tai muokatakseen selaimen tietoja."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"aseta herätys herätyskelloon"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Antaa sovelluksen asettaa herätyksen asennettuun herätyskellosovellukseen. Kaikki herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"muokkaa selaimen maantieteellisen sijainnin lupia"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Antaa sovelluksen muokata selaimen maantieteellisen sijainnin lupia. Haitalliset sovellukset saattavat käyttää tätä sijaintitietojen lähettämiseen satunnaisiin verkkosivustoihin."</string>
     <string name="save_password_message" msgid="767344687139195790">"Haluatko selaimen muistavan tämän salasanan?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Avoin wifi-verkko käytettävissä"</item>
     <item quantity="other" msgid="7915895323644292768">"Avoimia wifi-verkkoja käytettävissä"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Lisää merkki"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Tuntematon sovellus"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Tekstiviestien lähettäminen"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Kytketty medialaitteena"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kytketty kamerana"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Kytketty asennusohjelmana"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Käytä muita USB-vaihtoehtoja koskettamalla"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Haluatko alustaa USB-tilan ja poistaa kaikki siellä olevat tiedostot? Toimintoa ei voi peruuttaa!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN on aktivoitu."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Sarjanumero"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Tunnistetiedostot:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-tunnistetiedosto"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-tunnistetiedosto"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Näytä kaikki..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f9aa46e..a10b203 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permet à des applications d\'identifier les touches sur lesquelles vous appuyez même lorsque vous utilisez une autre application (lors de la saisie d\'un mot de passe, par exemple). Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"Association à un mode de saisie"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permet au support de se connecter à l\'interface de plus haut niveau d\'un mode de saisie. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Se fixer sur un fond d\'écran"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permet au support de se fixer sur l\'interface de plus haut niveau d\'un fond d\'écran. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Province"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Code postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"État"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Code postal"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Comté"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Île"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Département"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Préfecture"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Commune"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Région"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Émirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lire l\'historique et les favoris du navigateur"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet à une application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonction pour effacer ou modifier les données de votre navigateur."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"régler le réveil"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet à l\'application de définir une alarme dans un utilitaire faisant office de réveil. Certains réveils risquent ne pas prendre en charge cette fonctionnalité."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifier les autorisations de géolocalisation du navigateur"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet à une application de modifier les autorisations de géolocalisation du navigateur. Les applications malveillantes peuvent se servir de cette fonctionnalité pour envoyer des informations de lieu à des sites Web arbitraires."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Réseau Wi-Fi ouvert disponible"</item>
     <item quantity="other" msgid="7915895323644292768">"Réseaux Wi-Fi ouverts disponibles"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Insérer un caractère"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Application inconnue"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Envoi de messages SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'appareil multimédia"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Appuyez pour accéder aux autres options USB."</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formater la mémoire de stockage USB en effaçant tous les fichiers ? Cette action est irréversible."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN activé"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1090,23 +1122,20 @@
     <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="org_unit" msgid="7265981890422070383">"Unité organisationnelle :"</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) -->
+    <string name="serial_number" msgid="758814067660862493">"Numéro de série :"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Empreintes :"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Empreinte SHA-256 :"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte SHA-1 :"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tout afficher..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index acb7f27..72ea506 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Aplikacijama omogućuje praćenje pritisnutih tipki kod interakcije s drugom aplikacijom (primjerice kod unosa zaporke). Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vezano uz način unosa"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Nositelju omogućuje da se veže uz sučelje najviše razine za metodu unosa. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezano s pozadinskom slikom"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Nositelju omogućuje da se veže uz sučelje najviše razine za pozadinsku sliku. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Pokrajina"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Poštanski broj"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Država"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Poštanski broj"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Županija"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Otok"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Okrug"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Odjel"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Župa"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Područje"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čitanje povijesti i oznaka preglednika"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Aplikaciji omogućuje čitanje svih URL-ova koje je preglednik posjetio i svih oznaka iz preglednika."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje povijesti i oznaka preglednika"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Aplikaciji omogućuje izmjenu povijesti ili oznaka preglednika koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu podataka o pregledniku."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"namjesti alarm na budilici"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Omogućuje aplikaciji da namjesti alarm u instaliranoj aplikaciji budilice. Neke aplikacije budilice možda neće primijeniti ovu značajku."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Izmijeni dopuštenja za geo-lociranje u pregledniku"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Aplikaciji omogućuje izmjenu dopuštenja za geolokaciju u pregledniku. Zlonamjerne aplikacije to mogu koristiti za omogućavanje slanja informacija o lokaciji na proizvoljne web-lokacije."</string>
     <string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu zaporku?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Omogućavanje otvaranja Wi-Fi mreže"</item>
     <item quantity="other" msgid="7915895323644292768">"Omogućavanje otvaranja Wi-Fi mreža"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Nepoznata aplikacija"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Spojen kao medijski uređaj"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Spojen kao fotoaparat"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Spojen kao instalacijski program"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Dodirnite za ostale opcije USB-a"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatirati USB memoriju uz brisanje svih pohranjenih datoteka? Radnja se ne može poništiti!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN je aktiviran."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <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>
@@ -1094,19 +1126,16 @@
     <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) -->
+    <string name="expires_on" msgid="3676242949915959821">"Istječe dana:"</string>
+    <string name="serial_number" msgid="758814067660862493">"Serijski broj:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Otisci prstiju:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 otisak prsta:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 otisak prsta:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Prikaži sve..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b27fb83..3a5fd40 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Lehetővé teszi az alkalmazások számára, hogy figyeljék a lenyomott billentyűket még másik alkalmazás használata esetén is (például jelszó beírásakor). A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"összekapcsolás egy beviteli módszerrel"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Lehetővé teszi a használó számára a beviteli módszer legfelső szintű kezelőfelületéhez való csatlakozást. A normál alkalmazások soha nem használják ezt."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"összekapcsolás háttérképpel"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Lehetővé teszi a használó számára, hogy csatlakozzon egy háttérkép legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Tartomány"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Irányítószám"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Állam"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Irányítószám"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Ország"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Sziget"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Körzet"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Osztály"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektúra"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Közösség"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Terület"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirátus"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"böngészési előzmények és könyvjelzők olvasása"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lehetővé teszi az alkalmazás számára a böngésző által felkeresett összes URL, valamint az összes könyvjelző olvasását."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"böngészési előzmények és könyvjelzők írása"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt böngészési előzményeket és könyvjelzőket. A rosszindulatú alkalmazások felhasználhatják ezt a böngésző adatainak törlésére vagy módosítására."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"ébresztő beállítása az ébresztőórában"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Lehetővé teszi az alkalmazások számára, hogy beállítsanak egy ébresztőt egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"A böngésző helymeghatározási engedélyeinek módosítása"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a böngésző helymeghatározási engedélyeit. A rosszindulatú alkalmazások kihasználhatják ezt arra, hogy helyadatokat küldjenek tetszőleges webhelyeknek."</string>
     <string name="save_password_message" msgid="767344687139195790">"Szeretné, hogy a böngésző megjegyezze a jelszót?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Nyílt Wi-Fi hálózat elérhető"</item>
     <item quantity="other" msgid="7915895323644292768">"Nyílt Wi-Fi hálózatok elérhetők"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Karakter beszúrása"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ismeretlen alkalmazás"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-ek küldése"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Csatlakoztatva médiaeszközként"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Csatlakoztatva kameraként"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Csatlakoztatva telepítőként"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Érintse meg a további USB-opciókért"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formázza az USB-tárat, törölve az összes ott tárolt fájlt? A művelet nem vonható vissza!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN aktiválva."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Sorozatszám:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Ujjlenyomatok:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ujjlenyomat:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ujjlenyomat:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Összes megtekintése..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Tevékenység kiválasztása"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Megosztás..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2bfb6ce..85b8012 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Mengizinkan aplikasi melihat tombol yang Anda tekan bahkan ketika berinteraksi dengan aplikasi lain (seperti memasukkan sandi). Tidak pernah diperlukan untuk aplikasi normal."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"mengikat ke metode masukan"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi pada suatu metode masukan. Tidak diperlukan untuk aplikasi normal."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"mengikat ke wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu wallpaper. Tidak diperlukan untuk aplikasi normal."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provinsi"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Kode pos"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Negara Bagian"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Kode pos"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Wilayah"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Pulau"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrik"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departemen"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Kampung"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Area"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Peramban"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Izinkan aplikasi membaca semua URL yang telah dikunjungi Peramban, dam semua bookmark Peramban."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Peramban"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Mengizinkan aplikasi mengubah riwayat atau bookmark Peramban yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data Peramban."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"setel alarm di jam alarm"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Perbolehkan aplikasi untuk menyetel alarm di aplikasi jam alarm yang terpasang. Beberapa aplikasi jam alarm tidak dapat menerapkan fitur ini."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ubah izin geolokasi Peramban"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Mengizinkan aplikasi mengubah izin geolokasi Peramban. Aplikasi hasad dapat menggunakan ini untuk mengizinkan pengiriman informasi lokasi ke situs web sembarangan."</string>
     <string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Jaringan Wi-Fi terbuka tersedia"</item>
     <item quantity="other" msgid="7915895323644292768">"Jaringan Wi-Fi terbuka tersedia"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Sisipkan huruf"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplikasi tidak dikenal"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Mengirim pesan SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Terhubung sebagai perangkat media"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Terhubung sebagai kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Terhubung sebagai pemasang"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk opsi USB lainnya"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format penyimpanan USB, menghapus semua berkas yang disimpan di sana? Tindakan tidak dapat diurungkan!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN diaktifkan."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Nomor seri:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Sidik jari:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Sidik jari SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Sidik jari SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Lihat semua..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index fcb4e3a..147cb70 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Consente il rilevamento da parte delle applicazioni dei tasti premuti anche durante l\'interazione con un\'altra applicazione (come nel caso di inserimento di una password). Non dovrebbe essere mai necessario per le normali applicazioni."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"associaz. a un metodo di inserimento"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Consente l\'associazione all\'interfaccia principale di un metodo di inserimento. Non dovrebbe essere mai necessario per le normali applicazioni."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"associazione a sfondo"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Consente l\'associazione di uno sfondo all\'interfaccia principale. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string>
@@ -491,8 +495,8 @@
     <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="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica calcolo dell\'utilizzo della rete"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Consente di modificare le modalità di calcolo dell\'utilizzo della rete da parte delle 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>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Codice postale"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Stato"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Codice postale"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Contea"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Isola"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distretto"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Reparto"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefettura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Parrocchia"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Area"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lettura cronologia e segnalibri del browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Consente all\'applicazione di leggere tutti gli URL visitati e tutti i segnalibri del browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"creazione cronologia e segnalibri del browser"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Consente a un\'applicazione di modificare la cronologia o i segnalibri del browser memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del browser."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"impostazione allarmi nella sveglia"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. Alcune applicazioni sveglia potrebbero non supportare questa funzione."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica le autorizzazioni di localizzazione geografica del browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Consente a un\'applicazione di modificare le autorizzazioni di localizzazione geografica del browser. Le applicazioni dannose possono utilizzare questa autorizzazione per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string>
     <string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Rete Wi-Fi aperta disponibile"</item>
     <item quantity="other" msgid="7915895323644292768">"Reti Wi-Fi aperte disponibili"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Inserisci carattere"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Applicazione sconosciuta"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Invio SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Collegato come dispositivo multimediale"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Collegato come fotocamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Collegato come installer"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Tocca per altre opzioni USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formattare l\'archivio USB cancellando tutti i file memorizzati al suo interno? Questa azione è irreversibile."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"La VPN è attiva."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Numero di serie:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingerprint:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Fingerprint SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra tutto..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleziona attività"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Condividi con..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 31ae61f..159af64 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"מאפשר ליישומים לצפות במקשים שעליהם אתה לוחץ בעת אינטראקציה עם יישום אחר (כגון הזנת סיסמה). לא אמור להיות דרוש לעולם ליישום רגילים."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"הכפפה לשיטת קלט"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"מאפשר למחזיק להכפיף לממשק ברמה עליונה של שיטת קלט. לא אמור להידרש לעולם ביישומים רגילים."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"קשור לטפט"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"מאפשר למחזיק לקשור לממשק ברמה עליונה של טפט. לא אמור להידרש לעולם ביישומים רגילים."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"הכפפה לשירות Widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"פרובינציה"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"מיקוד"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"מדינה"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"מיקוד"</string>
+    <string name="autofill_county" msgid="237073771020362891">"מחוז"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"אי"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"רובע"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"מחלקה"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"תחום שיפוט"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"קהילה"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"אזור"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"אמירות"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"קרא היסטוריה וסימניות של דפדפן"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"מאפשר ליישום לקרוא את כל כתובות האתרים שבהן ביקר הדפדפן, ואת כל הסימניות של הדפדפן."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתיבת היסטוריה וסימניות של דפדפן"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר התראה בשעון המעורר"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"מאפשר ליישום להגדיר התראה ביישום מותקן של שעון מעורר. חלק מיישומי השעון המעורר עשויים שלא ליישם תכונה זו."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"שנה את ההרשאות של מיקום גיאוגרפי בדפדפן"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"מאפשר ליישום לשנות את הרשאות היעד הגיאוגרפי של הדפדפן. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לאפשר שליחה של פרטי מיקום לאתרי אינטרנט אקראיים."</string>
     <string name="save_password_message" msgid="767344687139195790">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"רשת Wi-Fi פתוחה זמינה"</item>
     <item quantity="other" msgid="7915895323644292768">"רשתות Wi-Fi פתוחות זמינות"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"הוסף תו"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"יישום לא ידוע"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"שולח הודעות SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"מחובר כמכשיר מדיה"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"מחובר כמצלמה"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"מחובר כמתקין"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"גע לקבלת אפשרויות USB נוספות"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"לפרמט את אמצעי האחסון מסוג USB, תוך מחיקת כל הקבצים? הפעולה בלתי הפיכה!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"נגישות"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN מופעל."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"מספר סידורי:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"טביעות אצבע:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"טביעת אצבע SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"טביעת אצבע SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"הצג הכל..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9b7e80e..c2b6dd2 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"別のアプリケーションへの入力(パスワードなど)でもキー入力を監視することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"入力方法に関連付ける"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"入力方法のトップレベルインターフェースに関連付けることを所有者に許可します。通常のアプリケーションにはまったく必要ありません。"</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"壁紙にバインド"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"壁紙のトップレベルインターフェースへのバインドを所有者に許可します。通常のアプリケーションでは不要です。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"、 "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"地方"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"郵便番号"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"州"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"郵便番号"</string>
+    <string name="autofill_county" msgid="237073771020362891">"郡"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"島"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"地区"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"県"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"都道府県"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"行政区"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"地域"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"首長国"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ブラウザの履歴とブックマークを読み取る"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"携帯電話に保存されているブラウザの履歴やブックマークの修正をアプリケーショに許可します。これにより悪意のあるアプリケーションが、ブラウザのデータを消去または変更する恐れがあります。"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"アラームの設定"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"インストール済みアラームアプリケーションのアラーム設定をアプリケーションに許可します。この機能が実装されていないアラームアプリケーションもあります。"</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"ブラウザの位置情報へのアクセス権を変更"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ブラウザの位置情報に対するアクセス権の変更をアプリケーションに許可します。この設定では、悪意のあるアプリケーションが任意のウェブサイトに位置情報を送信する可能性があります。"</string>
     <string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Wi-Fiオープンネットワークが利用できます"</item>
     <item quantity="other" msgid="7915895323644292768">"Wi-Fiオープンネットワークが利用できます"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"文字を挿入"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"不明なアプリケーション"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMSメッセージの送信中"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"メディアデバイスとして接続"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"カメラとして接続"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"インストーラとして接続"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"他のUSBオプションをタップしてください"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USBストレージをフォーマットして、保存されているすべてのファイルを消去しますか?この操作は元に戻せません。"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ユーザー補助"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPNが有効化されました。"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"シリアル番号:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"指紋:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256指紋:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1指紋:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"すべて見る..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 15b3240..0c4c4b8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"애플리케이션이 다른 애플리케이션과 상호작용할 때에도 사용자가 누르는 키(예: 비밀번호 입력)를 볼 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"입력 방법 연결"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"권한을 가진 프로그램이 입력 방법에 대한 최상위 인터페이스를 사용하도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"배경화면 연결"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"권한을 가진 프로그램이 배경화면에 대한 최상위 인터페이스를 사용하도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"도"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"우편번호"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"시/도"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"우편번호"</string>
+    <string name="autofill_county" msgid="237073771020362891">"구/군"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"섬"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"구"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"지역"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"현"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"군"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"구역"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"에미리트"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"브라우저의 기록 및 북마크 읽기"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"애플리케이션이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"애플리케이션이 휴대전화에 저장된 브라우저 기록 또는 북마크를 수정할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 브라우저의 데이터를 지우거나 수정할 수 있습니다."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"알람 시계에 알람 설정"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"실치된 알람 시계 애플리케이션에 알람을 설정하도록 허용합니다. 일부 알람 시계 애플리케이션은 이 기능을 구현하지 않을 수 있습니다."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"브라우저 위치 정보 수정 권한"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"애플리케이션이 브라우저의 위치 정보 권한을 수정할 수 있도록 합니다. 악성 애플리케이션이 이를 사용하여 임의의 웹사이트에 위치 정보를 보낼 수도 있습니다."</string>
     <string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"개방형 Wi-Fi 네트워크 사용 가능"</item>
     <item quantity="other" msgid="7915895323644292768">"개방형 Wi-Fi 네트워크 사용 가능"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"문자 삽입"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"알 수 없는 애플리케이션"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS 메시지를 보내는 중"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"미디어 기기로 연결됨"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"카메라로 연결됨"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"설치 프로그램으로 연결됨"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"다른 USB 옵션을 보려면 터치하세요."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB 저장소를 포맷하여 저장된 파일을 모두 지우시겠습니까? 수행한 후에는 작업을 취소할 수 없습니다."</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"접근성"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN이 활성화되어 있습니다."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"일련번호:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"지문:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 지문:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 지문:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"전체 보기..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"활동 선택"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index ec2313c..388eb38 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -25,8 +25,6 @@
     <dimen name="password_keyboard_key_height_numeric">60dip</dimen>
     <!-- Default correction for the space key in the password keyboard -->
     <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
-    <dimen name="preference_screen_side_margin">16dp</dimen>
-    <dimen name="preference_screen_side_margin_negative">-20dp</dimen>
     <dimen name="preference_widget_width">72dp</dimen>
 
     <!-- Default height of an action bar. -->
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b57455f..1e18e3c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Leidžia programoms žiūrėti jūsų paspaustus klavišus sąveikaujant su kita programa (pvz., įvedant slaptažodį). Neturėtų reikėti įprastoms programoms."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"susaistyti įvesties būdą"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Leidžia savininkui susisaistyti su įvesties būdo aukščiausio lygio sąsaja. Neturėtų reikėti įprastoms programoms."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"susaistyti su darbalaukio fonu"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Leidžia savininkui susisaistyti su aukščiausio lygio darbalaukio fono sąsaja. Neturėtų reikėti įprastose programose."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincija"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Pašto kodas"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Valstija"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Pašto kodas"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Apskritis"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Sala"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Rajonas"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departamentas"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektūra"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Parapija"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Sritis"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emyratas"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"skaityti naršyklės istoriją ir žymes"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Leidžia programai skaityti visus URL, kuriuose apsilankė naršyklė, ir visas naršyklės žymas."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rašyti naršyklės istoriją ir žymes"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Leidžia programai keisti naršyklės istoriją ar žymes, išsaugotus jūsų telefone. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų naršyklės duomenis."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"nustatyti žadintuvo signalą"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose šios funkcijos gali nebūti."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Keisti naršyklės geografinės vietovės leidimus"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Leidžia programai keisti geografinių naršyklės vietų leidimus. Kenkėjiškos programos tai gali naudoti siunčiant vietos informaciją atsitiktinėms svetainėms."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ar norite, kad naršyklė atsimintų šį slaptažodį?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Atidaryti galimą „Wi-Fi“ tinklą"</item>
     <item quantity="other" msgid="7915895323644292768">"Atidaryti galimus „Wi-Fi“ tinklus"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Įterpti simbolį"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Nežinoma programa"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS pranešimų siuntimas"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Prij. kaip medijos įrenginys"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Prij. kaip fotoap."</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Prij. kaip diegimo programa"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Jei norite matyti kitas USB parinktis, palieskite"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatuoti USB atmintinę ištrinant visus joje saugomus failus? Veiksmo nebus galima atšaukti!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN suaktyvintas."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serijos numeris:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Kontroliniai kodai"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 kontrolinis kodas"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 kontrolinis kodas"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Žr. viską..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Pasirinkti veiklą"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Bendrinti su..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 6fed017..43d640b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Ļauj lietojumprogrammām sekot līdzi nospiestajiem taustiņiem, mijiedarbojoties ar citu lietojumprogrammu (piemēram, ievadot paroli). Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"saistīt ar ievades metodi"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ļauj īpašniekam saistīt ar ievades metodes augšējā līmeņa saskarni. Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"saistīt ar tapeti"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ļauj īpašniekam saistīties ar tapetes augšējā līmeņa saskarni. Parastajās lietojumprogrammās nekad nav nepieciešama."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Province"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Pasta indekss"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Štats"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Pasta indekss"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Apgabals"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Sala"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Rajons"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departaments"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektūra"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Pagasts"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Reģions"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirāts"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lasīt pārlūkprogrammas vēsturi un grāmatzīmes"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ļauj lietojumprogrammai lasīt visus URL, kas ir apmeklēti pārlūkprogrammā, un visas pārlūkprogrammas grāmatzīmes."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rakstīt pārlūkprogrammas vēsturi un grāmatzīmes"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ļauj lietojumprogrammai pārveidot tālrunī saglabāto pārlūkprogrammas vēsturi un grāmatzīmes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu pārlūkprogrammas datus."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"iestatīt trauksmi modinātājpulkstenī"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ļauj lietojumprogrammai iestatīt trauksmi instalētajā modinātājpulksteņa lietojumprogrammā. Dažās modinātājpulksteņu lietojumprogrammās šī funkcija var nebūt īstenojama."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ļauj lietojumprogrammai pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vai vēlaties, lai pārlūkprogrammā tiktu saglabāta šī parole?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Ir pieejams atvērts Wi-Fi tīkls"</item>
     <item quantity="other" msgid="7915895323644292768">"Ir pieejami atvērti Wi-Fi tīkli."</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Ievietojiet rakstzīmi"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Nezināma lietojumprogramma"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Īsziņu sūtīšana"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pievienots kā multivides ierīce"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pievienots kā kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pievienots kā instalēšanas programma"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Pieskarieties, lai skatītu citas USB opcijas."</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vai formatēt USB krātuvi, dzēšot visus tajā saglabātos failus? Šo darbību nevar atcelt."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN ir aktivizēts."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Sērijas numurs:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Identifikatori"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 identifikators"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 identifikators:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Skatīt visas"</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Darbību atlasīšana"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Kopīgot ar..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 87b169d..3921be9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -46,8 +46,7 @@
     <string name="badPuk" msgid="5702522162746042460">"Kod PUK yang anda taipkan tidak betul."</string>
     <string name="mismatchPin" msgid="3695902225843339274">"PIN yang anda masukkan tidak sepadan."</string>
     <string name="invalidPin" msgid="3850018445187475377">"Taipkan PIN yang mengandungi 4 hingga 8 nombor."</string>
-    <!-- no translation found for invalidPuk (8761456210898036513) -->
-    <skip />
+    <string name="invalidPuk" msgid="8761456210898036513">"Taipkan PUK yang mempunyai 8 nombor atau lebih panjang."</string>
     <string name="needPuk" msgid="919668385956251611">"Kad SIM anda dikunci PUK. Taipkan kod PUK untuk membuka kuncinya."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Taipkan PUK2 untuk menyahsekat kad SIM."</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID Pemanggil Masuk"</string>
@@ -153,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mod Pesawat DIHIDUPKAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mod Pesawat DIMATIKAN"</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 selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string>
@@ -192,10 +191,8 @@
     <string name="permdesc_receiveSms" msgid="6298292335965966117">"Membolehkan aplikasi untuk menerima dan memproses mesej SMS. aplikasi berbahaya boleh memantau mesej atau memadamkannya tanpa menunjukkan kepada anda."</string>
     <string name="permlab_receiveMms" msgid="8894700916188083287">"terima MMS"</string>
     <string name="permdesc_receiveMms" msgid="4563346832000174373">"Membenarkan aplikasi menerima dan memproses mesej MMS. Aplikasi berniat jahat mungkin memantau mesej anda atau memadamkannya tanpa menunjukkan kepada anda."</string>
-    <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
-    <skip />
-    <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
-    <skip />
+    <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"terima siaran kecemasan"</string>
+    <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Membenarkan aplikasi menerima dan memproses mesej siaran kecemasan. Kebenaran ini hanya tersedia kepada aplikasi sistem."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"hantar mesej SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Membolehkan aplikasi menghantar mesej SMS. Aplikasi berniat jahat boleh merugikan wang anda dengan menghantar mesej tanpa pengesahan anda."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"baca SMS atau MMS"</string>
@@ -226,10 +223,8 @@
     <string name="permdesc_forceBack" msgid="6534109744159919013">"Membenarkan aplikasi memaksa sebarang aktiviti dalam latar depan untuk ditutup dan pergi ke belakang. Seharusnya tidak diperlukan untuk aplikasi nomal."</string>
     <string name="permlab_dump" msgid="1681799862438954752">"mendapatkan semula keadaan dalaman sistem"</string>
     <string name="permdesc_dump" msgid="2198776174276275220">"Membenarkan aplikasi mendapatkan semula keadaan dalaman sistem. Aplikasi berniat jahat boleh mendapatkan semula pelbagai maklumat sulit dan dilindungi yang ia tidak seharusnya memerlukannya."</string>
-    <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
-    <skip />
-    <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
-    <skip />
+    <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dapatkan semula kandungan skrin"</string>
+    <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Membenarkan aplikasi untuk mendapatkan kembali kandungan tetingkap aktif. Aplikasi berniat jahat boleh mendapatkan kembali kandungan keseluruhan tetingkap dan memeriksa semua teksnya kecuali kata laluan."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
@@ -250,10 +245,8 @@
     <string name="permdesc_batteryStats" msgid="5847319823772230560">"Membenarkan pengubahsuaian statistik bateri yang dikumpulkan. Bukan untuk kegunaan biasa aplikasi."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sandaran dan pemulihan sistem kawalan"</string>
     <string name="permdesc_backup" msgid="4837493065154256525">"Membenarkan aplikasi mengawal mekanisme sandaran dan pemulihan sistem. Bukan untuk kegunaan aplikasi biasa."</string>
-    <!-- no translation found for permlab_confirm_full_backup (5557071325804469102) -->
-    <skip />
-    <!-- no translation found for permdesc_confirm_full_backup (9005017754175897954) -->
-    <skip />
+    <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"sahkan penyandaran penuh atau pemulihan operasi"</string>
+    <string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Membenarkan aplikasi melancarkan UI pengesahan sandaran penuh. Bukan untuk digunakan oleh mana-mana aplikasi."</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"memapaparkan tetingkap yang tiada kebenaran"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Membenarkan pewujudan tetingkap yang dimaksudkan untuk digunakan oleh antara muka pengguna sistem dalaman. Bukan untuk kegunaan oleh aplikasi biasa."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"paparkan amaran peringkat sistem"</string>
@@ -269,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Membenarkan aplikasi melihat kekunci yang anda tekan walaupun semasa berinteraksi dengan aplikasi lain (seperti memasukkan kata laluan). Seharusnya tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"terikat kepada kaedah input"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kaedah input itu. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
@@ -277,10 +274,8 @@
     <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Membenarkan pemegang menghantar tujuan kepada pentadbir peranti. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"tukar orientasi skrin"</string>
     <string name="permdesc_setOrientation" msgid="6335814461615851863">"Membolehkan aplikasi untuk menukar putaran skrin pada bila-bila masa. Tidak seharusnya diperlukan untuk aplikasi biasa."</string>
-    <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
-    <skip />
-    <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
-    <skip />
+    <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"tukar kelajuan penuding"</string>
+    <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Membenarkan aplikasi menukar kelajuan penuding tetikus atau pad jejak pada bila-bila masa sahaja. Seharusnya tidak diperlukan untuk aplikasi biasa."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"hantar isyarat Linux kepada aplikasi"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Membenarkan aplikasi meminta isyarat yang dibekalkan dihantar kepada semua proses gigih."</string>
     <string name="permlab_persistentActivity" msgid="8659652042401085862">"buatkan aplikasi sentiasa berjalan"</string>
@@ -328,14 +323,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"tulis data kenalan"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Membenarkan aplikasi mengubah suai data (alamat) kenalan yang disimpan pada tablet anda. Aplikasi yang berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data kenalan anda."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Membenarkan aplikasi mengubah suai data (alamat) kenalan yang disimpan pada telefon anda. Aplikasi yang berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai 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">"Membenarkan aplikasi membaca semua maklumat profil peribadi anda. Aplikasi berniat jahat boleh menggunakannya untuk mengenal pasti anda dan menghantar maklumat peribadi anda kepada orang lain."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"menulis data profil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Membenarkan aplikasi mengubah suai maklumat profil peribadi anda. Aplikasi berniat jahat boleh menggunakan ini untuk memadamkan atau mengubah suai data profil anda."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"baca acara kalendar"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Membenarkan aplikasi membaca semua acara kalendar yang disimpan pada tablet anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar acara kalendar anda kepada orang lain."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Membenarkan aplikasi membaca semua acara kalendar yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar acara kalendar anda kepada orang lain."</string>
@@ -472,10 +463,8 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Membenarkan aplikasi melihat konfigurasi telefon Bluetooth setempat dan membuat dan menerima sambungan dengan peranti yang dipasangkan."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"mengawal Komunikasi Medan Dekat"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Membenarkan aplikasi berkomunikasi dengan teg, kad dan pembaca Komunikasi Medan Dekat (NFC)."</string>
-    <!-- no translation found for permlab_vpn (8345800584532175312) -->
-    <skip />
-    <!-- no translation found for permdesc_vpn (7093963230333602420) -->
-    <skip />
+    <string name="permlab_vpn" msgid="8345800584532175312">"memintas dan mengubah suai semua trafik rangkaian"</string>
+    <string name="permdesc_vpn" msgid="7093963230333602420">"Membenarkan aplikasi memintas dan memeriksa semua trafik rangkaian untuk mewujudkan sambungan VPN. Aplikasi berniat jahat boleh memantau, menghalakan semula atau mengubah suai bingkisan rangkaian tanpa pengetahuan anda."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"lumpuhkan kunci kekunci"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Membenarkan aplikasi melumpuhkan kunci kekunci anda dan sebarang keselamatan kata laluan yang berkaitan. Contoh yang berkaitan adalah telefon melumpuhkan kunci kekunci apabila menerima panggilan telefon masuk kemudian mendayakan semula kunci kekunci apabila panggilan selesai."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"membaca tetapan penyegerakan"</string>
@@ -502,14 +491,10 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Membenarkan aplikasi membaca dan menulis cache sistem fail."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"membuat/menerima panggilan Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Membenarkan aplikasi menggunakan perkhidmatan SIP untuk membuat/menerima panggilan 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 sejarah penggunaan rangkaian"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Membenarkan aplikasi membaca sejarah penggunaan rangkaian untuk rangkaian dan aplikasi khusus."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"urus dasar rangkaian"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Membenarkan aplikasi mengurus dasar rangkaian dan menentukan peraturan khusus aplikasi."</string>
     <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
     <skip />
     <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
@@ -532,10 +517,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Mengawal kekerapan penukaran kata laluan kunci skrin"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tetapkan penyulitan storan"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Memerlukan data aplikasi yang disimpan itu disulitkan"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Lumpuhkan kamera"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Menghalang penggunaan semua kamera peranti"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Laman Utama"</item>
     <item msgid="869923650527136615">"Mudah alih"</item>
@@ -650,12 +633,9 @@
     <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>
-    <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
-    <skip />
-    <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
-    <skip />
-    <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
-    <skip />
+    <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Masukkan PUK dan kod PIN baru"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kod PUK"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Kod PIN Baru"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Sentuh untuk memasukkan kata laluan"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Masukkan kata laluan untuk membuka kunci"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Masukkan PIN untuk membuka kunci"</string>
@@ -680,10 +660,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tiada kad SIM dalam tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Kad SIM tiada dalam telefon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sila masukkan kad 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">"Kad SIM tiada atau tidak boleh dibaca. Sila masukkan kad SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kad SIM anda dilumpuhkan secara kekal."\n" Sila hubungi pembekal perkhidmatan wayarles anda untuk mendapatkan kad SIM lain."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan kecemasan sahaja"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rangkaian dikunci"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kad SIM dikunci dengan PUK."</string>
@@ -729,6 +707,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Wilayah"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Poskod"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Negeri"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Poskod"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Wilayah"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Pulau"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Daerah"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Jabatan"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Wilayah"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Kariah"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Kawasan"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emiriah"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca sejarah dan penanda halaman Penyemak imbas"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Membenarkan aplikasi membaca semua URL yang telah dilawati oleh Penyemak Imbas dan semua penanda halaman Penyemak Imbas."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tulis sejarah dan penanda halaman Penyemak Imbas"</string>
@@ -736,6 +726,10 @@
     <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 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>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <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>
     <string name="save_password_message" msgid="767344687139195790">"Adakah anda mahu penyemak imbas mengingati kata laluan ini?"</string>
@@ -927,6 +921,22 @@
     <item quantity="one" msgid="1634101450343277345">"Rangkaian Wi-Fi terbuka tersedia"</item>
     <item quantity="other" msgid="7915895323644292768">"Rangkaian Wi-Fi terbuka tersedia"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Masukkan aksara"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplikasi tidak dikenali"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Menghantar mesej SMS"</string>
@@ -972,14 +982,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Disambungkan sebagai peranti media"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Disambungkan sebagai kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Disambungkan sebagai pemasang"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk mendapatkan pilihan USB yang lain"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format storan USB, memadamkan semua fail yang disimpan? Tindakan tidak boleh dibalikkan!"</string>
@@ -1043,14 +1051,10 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- 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_title" msgid="8219003246858087489">"VPN diaktifkan."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
+    <string name="vpn_text" msgid="1610714069627824309">"Ketik untuk mengurus rangkaian."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Bersambung kepada <xliff:g id="SESSION">%s</xliff:g>. Ketik untuk mengurus rangkaian."</string>
     <string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
@@ -1102,32 +1106,19 @@
     <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>
-    <!-- no translation found for action_bar_home_description (5293600496601490216) -->
-    <skip />
-    <!-- no translation found for action_bar_up_description (2237496562952152589) -->
-    <skip />
-    <!-- no translation found for action_menu_overflow_description (2295659037509008453) -->
-    <skip />
-    <!-- no translation found for storage_internal (7556050805474115618) -->
-    <skip />
-    <!-- no translation found for storage_sd_card (8921771478629812343) -->
-    <skip />
-    <!-- no translation found for storage_usb (3017954059538517278) -->
-    <skip />
-    <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
-    <skip />
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
-    <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
-    <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
-    <skip />
+    <string name="action_bar_home_description" msgid="5293600496601490216">"Navigasi laman utama"</string>
+    <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi ke atas"</string>
+    <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lagi pilihan"</string>
+    <string name="storage_internal" msgid="7556050805474115618">"Storan Dalaman"</string>
+    <string name="storage_sd_card" msgid="8921771478629812343">"Kad SD"</string>
+    <string name="storage_usb" msgid="3017954059538517278">"Storan USB"</string>
+    <string name="extract_edit_menu_button" msgid="302060189057163906">"Edit..."</string>
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Amaran 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 dilumpuhkan"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Data 4G dilumpuhkan"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Data mudah alih dilumpuhkan"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"ketik untuk mendayakan"</string>
     <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>
@@ -1138,18 +1129,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Nombor siri:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Cap jari:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Cap jari SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Cap jari SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Lihat semua..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ca40558..7db3f31 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Lar applikasjonen overvåke tastetrykk selv når interaksjonen er med et annet program (som å skrive inn et passord). Vanlige applikasjoner bør aldri trenge dette."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"binde til en inndatametode"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Lar applikasjonen binde til toppnivågrensesnittet for en inndatametode. Vanlige applikasjoner bør aldri trenge dette."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind til bakgrunnsbilde"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunnsbilder. Skal ikke være nødvendig for vanlige programmer."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind til modultjenste"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Delstat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Fylke"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Øy"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departement"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Sogn"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lese nettleserens logg og bokmerker"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skrive til nettleserens logg og bokmerker"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Lar applikasjonen endre nettleserens logg og bokmerker lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å fjerne eller redigere nettleserens data."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"angi alarm i alarmklokke"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Lar programmet angi en alarm i et installert alarmklokkeprogram. Det kan hende at enkelte alarmklokkeprogrammer ikke implementerer denne funksjonen."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Endre nettleserens tillatelser for geografisk posisjonering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillater programmet å endre nettleserens tillatelser for geografisk posisjonering. Skadelige programmer kan bruke denne funksjonen til å sende posisjonsopplysninger til vilkårlige nettsteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Åpent trådløsnett i nærheten"</item>
     <item quantity="other" msgid="7915895323644292768">"Åpne trådløsnett i nærheten"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Sett inn tegn"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukjent applikasjon"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender SMS-meldinger"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilkoblet som medieenhet"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilkoblet som kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilkoblet som installasjonsprogram"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Berør for andre USB-alternativer"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lagring og slette alle lagrede filer? Handlingen kan ikke angres!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN er aktivert."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingeravtrykk"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeravtrykk"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeravtrykk"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Se alle"</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 757091f..52873e1 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -262,6 +262,10 @@
     <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 apps."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <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 apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postcode"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Staat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postcode"</string>
+    <string name="autofill_county" msgid="237073771020362891">"County"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Eiland"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departement"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectuur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Gemeente"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Gebied"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emiraat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"browsergeschiedenis en bladwijzers lezen"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Hiermee kan een app de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"browsergeschiedenis en bladwijzers schrijven"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Hiermee kan een app de op uw telefoon opgeslagen browsergeschiedenis of bladwijzers wijzigen. Schadelijke apps kunnen hiermee uw browsergegevens verwijderen of wijzigen."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"alarm instellen in wekker"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolocatierechten voor browser aanpassen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Staat een app toe de geolocatierechten van de browser aan te passen. Schadelijke apps kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Open Wi-Fi-netwerk beschikbaar"</item>
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi-netwerken beschikbaar"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Onbekende app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Gekoppeld als media-apparaat"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Gekoppeld als camera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Gekoppeld als installatieprogramma"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Raak aan voor andere USB-opties"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-opslag formatteren en alle opgeslagen bestanden wissen? Actie kan niet ongedaan worden gemaakt."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN is geactiveerd."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Vingerafdrukken:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-vingerafdruk"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-vingerafdruk:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Alle bekijken..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Activiteit selecteren"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Delen met..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 85f2bad..eedf51a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Pozwala aplikacjom na śledzenie naciskanych klawiszy, nawet podczas pracy z innym programem (na przykład podczas wpisywania hasła). Nigdy nie powinno być potrzebne normalnym aplikacjom."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"powiązanie ze sposobem wprowadzania tekstu"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Pozwala na powiązanie wybranego sposobu wprowadzania tekstu z interfejsem najwyższego poziomu. To uprawnienie nie powinno być nigdy wymagane przez zwykłe aplikacje."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"powiązanie z tapetą"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umożliwia posiadaczowi powiązać interfejs najwyższego poziomu dla tapety. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Województwo"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Kod pocztowy"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Stan"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Kod pocztowy"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Powiat"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Wyspa"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Dystrykt"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Gmina"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Obszar"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"odczyt historii i zakładek przeglądarki"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zapis historii i zakładek przeglądarki"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umożliwia aplikacji modyfikowanie historii lub zakładek przeglądarki zapisanych w telefonie. Złośliwe aplikacje mogą używać tej opcji do usuwania lub modyfikowania danych przeglądarki."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"ustaw alarm w budziku"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Umożliwia aplikacji ustawienie alarmu w zainstalowanej aplikacji budzika. W niektórych aplikacjach budzika funkcja ta może nie być zaimplementowana."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Zezwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn internetowych."</string>
     <string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
@@ -726,11 +746,11 @@
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Ponad 1 miesiąc temu"</string>
   <plurals name="num_seconds_ago">
     <item quantity="one" msgid="4869870056547896011">"sekundę temu"</item>
-    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sekund temu"</item>
+    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sek. temu"</item>
   </plurals>
   <plurals name="num_minutes_ago">
     <item quantity="one" msgid="3306787433088810191">"1 minutę temu"</item>
-    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minut temu"</item>
+    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> min. temu"</item>
   </plurals>
   <plurals name="num_hours_ago">
     <item quantity="one" msgid="9150797944610821849">"godzinę temu"</item>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Otwórz dostępne sieci Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Otwórz dostępne sieci Wi-Fi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Wstaw znak"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Nieznana aplikacja"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Wysyłanie wiadomości SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Podłączono jako urządzenie multimedialne."</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Podłączono jako aparat."</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Podłączono jako nośnik instalacyjny."</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Dotknij, aby wyświetlić inne opcje USB."</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Czy sformatować nośnik USB i wymazać wszystkie zapisane na nim pliki? Tej czynności nie można cofnąć."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Obsługa sieci VPN została włączona"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Numer seryjny:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Odciski cyfrowe:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Odcisk cyfrowy SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Odcisk cyfrowy SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Pokaż wszystkie"</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Wybierz czynność"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Udostępnij..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 9761b71..c89577d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permite às aplicações verificar as teclas que o utilizador prime, mesmo ao interagir com outras aplicações (como, por exemplo, ao introduzir uma palavra-passe). Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a um método de entrada"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite ao titular vincular a interface de nível superior a um método de entrada de som. Nunca deve ser necessário para aplicações normais."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a uma imagem de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite ao titular vincular a interface de nível superior de uma imagem de fundo. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Província"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Concelho"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ilha"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Município"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Freguesia"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirado"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e marcadores do browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que a aplicação leia todos os URLs visitados pelo browser e todos os marcadores do browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e marcadores do browser"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que uma aplicação modifique o histórico e os marcadores do browser armazenados no telefone. As aplicações maliciosas podem utilizar esta permissão para apagar ou modificar os dados do browser."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar permissões de localização geográfica do Navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite a uma aplicação modificar as permissões de localização geográfica do Navegador. As aplicações mal intencionadas podem utilizar isto para enviar informações de localização para Web sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
     <item quantity="other" msgid="7915895323644292768">"Abrir redes Wi-Fi disponíveis"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Introduzir carácter"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicação desconhecida"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"A enviar mensagens SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um aparelho multimédia"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ligado como uma câmara"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ligado como um instalador"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Toque para outras opções USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar armazenamento USB e apagar todos os ficheiros armazenados? Não é possível reverter a acção!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"A VPN está ativa"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Número de série:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Impressões digitais:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Impressão digital SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Impressão digital SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver tudo..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Selecionar atividade"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Partilhar com..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a56523f..1a7e0a8 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permite que os aplicativos vejam as teclas que você pressiona, mesmo quando estiver interagindo com outro aplicativo (como ao digitar uma senha). Aplicativos normais não devem precisar disso em momento algum."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a um método de entrada"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite que o detentor se sujeite à interface de nível superior de um método de entrada. Aplicativos normais não devem precisar disso em momento algum."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite que o detentor se sujeite à interface de nível superior de um plano de fundo. Aplicativos normais não devem precisar disso em momento algum."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Distrito"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Código Postal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"CEP"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Condado"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ilha"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Município"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Paróquia"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirado"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e favoritos do Navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que o aplicativo leia todos os URLs visitados pelo Navegador e todos os favoritos do Navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e favoritos do Navegador"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que um aplicativo modifique o histórico ou os favoritos do Navegador armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do seu Navegador."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que o aplicativo defina um alarme em um aplicativo de despertador instalado. Talvez alguns aplicativos de despertador não implementem esse recurso."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifique as permissões de geolocalização do seu navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que um aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações de localização a sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
     <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abertas disponíveis"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicativo desconhecido"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como um dispositivo de mídia"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectadas como uma câmera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectados como um instalador"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Toque para obter outras opções USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar o armazenamento USB, apagando todos os arquivos armazenados? A ação não pode ser revertida!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"A VPN está ativada."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Número de série:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Impressões digitais"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Impressão digital SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Impressão digital SHA-1"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todos..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 7048c69..4f0e385 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -275,6 +275,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"\"Permetta ad ina applicaziun dad identifitgar las tastas che Vus smatgais, era durant l\'utilisaziun dad in auter program (durant l\'endataziun dad in pled-clav, per exempel). Applicaziuns normalas na duessan betg avair access a questa funcziun.\""</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"associar cun ina metoda d\'endataziun"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permetta da sa fixar al nivel d\'interfatscha pli aut dad ina metoda d\'endataziun. Betg previs per applicaziuns normalas."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sa fixar vid in fund davos"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permetta da sa fixar al nivel d\'interfatscha pli aut dad ina metoda d\'endataziun. Betg previs per applicaziuns normalas."</string>
     <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -781,6 +785,30 @@
     <skip />
     <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
     <skip />
+    <!-- no translation found for autofill_province (2231806553863422300) -->
+    <skip />
+    <!-- no translation found for autofill_postal_code (4696430407689377108) -->
+    <skip />
+    <!-- no translation found for autofill_state (6988894195520044613) -->
+    <skip />
+    <!-- no translation found for autofill_zip_code (8697544592627322946) -->
+    <skip />
+    <!-- no translation found for autofill_county (237073771020362891) -->
+    <skip />
+    <!-- no translation found for autofill_island (4020100875984667025) -->
+    <skip />
+    <!-- no translation found for autofill_district (8400735073392267672) -->
+    <skip />
+    <!-- no translation found for autofill_department (5343279462564453309) -->
+    <skip />
+    <!-- no translation found for autofill_prefecture (2028499485065800419) -->
+    <skip />
+    <!-- no translation found for autofill_parish (8202206105468820057) -->
+    <skip />
+    <!-- no translation found for autofill_area (3547409050889952423) -->
+    <skip />
+    <!-- no translation found for autofill_emirate (2893880978835698818) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leger la cronologia ed ils segnapaginas dal navigatur"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"\"Permetta a l\'applicaziun da leger tut las URLs visitadas, sco era ils segnapaginas dal navigatur.\""</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"scriver en la cronologia ed en ils segnapaginas dal navigatur"</string>
@@ -790,6 +818,10 @@
     <skip />
     <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
     <skip />
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifitgar las autorisaziuns da geolocalisaziun dal navigatur"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permetta ad ina applicaziun da modifitgar las permissiuns da geolocalisaziun dal navigatur. Applicaziuns donnegiusas pon utilisar questa funcziun per trametter datas da posiziun a websites arbitraras."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vulais Vus ch\'il navigatur memorisescha quest pled-clav?"</string>
@@ -986,6 +1018,22 @@
     <item quantity="one" msgid="1634101450343277345">"Rait WLAN averta disponibla"</item>
     <item quantity="other" msgid="7915895323644292768">"Raits WLAN avertas disponiblas"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Inserir in caracter"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Applicaziun nunenconuschenta"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Trametter messadis SMS"</string>
@@ -1039,6 +1087,8 @@
     <skip />
     <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
     <skip />
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+    <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>
@@ -1251,8 +1301,10 @@
     <skip />
     <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+    <skip />
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 69b111e..61a0d7b 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permite unei aplicaţii să monitorizeze tastele pe care le apăsaţi când interacţionaţi cu o altă aplicaţie (cum ar fi introducerea unei parole). Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"conectare la o metodă de intrare"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite deţinătorului să se conecteze la interfaţa de nivel superior a unei metode de intrare. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Cod poştal"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Stat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Cod ZIP"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Judeţ"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Insulă"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectură"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Cartier"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Zonă"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"citire istoric şi marcaje în browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite aplicaţiei să citească toate adresele URL vizitate din browser şi toate marcajele din acesta."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"citire istoric şi marcaje în browser"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite unei aplicaţii să modifice istoricul şi marcajele din browser, stocate pe telefonul dvs. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din browser."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"setare alarmă pentru ceasul cu alarmă"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas de alarmă instalată. Este posibil ca unele aplicaţii de ceas de alarmă să nu implementeze această funcţie."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificare permisiuni pentru locaţia geografică a browserului"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite unei aplicaţii să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri Web arbitrare."</string>
     <string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Reţea Wi-Fi deschisă disponibilă"</item>
     <item quantity="other" msgid="7915895323644292768">"Reţele Wi-Fi deschise disponibile"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicaţie necunoscută"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectat ca dispozitiv media"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectat ca aparat foto"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectat ca program de instalare"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Atingeţi pentru alte opţiuni USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formataţi stocarea USB, ştergând toate fişierele stocate aici? Acţiunea nu poate fi anulată!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN este activată."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Număr de serie:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Amprente:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Amprentă SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Amprentă SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Afişaţi-le pe toate..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 95d4077..d2907ae 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Позволяет приложению распознавать нажатые пользователем клавиши даже при работе с другим приложением (например, при вводе пароля). Не требуется для обычных приложений."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"связывать с методом ввода"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Позволяет выполнять привязку к интерфейсу ввода верхнего уровня. Не требуется для обычных приложений."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"связать с фоновым рисунком"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Разрешает выполнять привязку к интерфейсу фонового рисунка верхнего уровня. Не требуется для обычных приложений."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"привязка к службе виджетов"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Провинция"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Почтовый индекс"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Штат"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Почтовый индекс"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Округ"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Остров"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Район"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Департамент"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Округ"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Область"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Эмират"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"считывать историю и закладки браузера"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Разрешает приложению изменять историю и закладки браузера, сохраненные в вашем телефоне. Вредоносное ПО может пользоваться этим, чтобы стирать или изменять данные вашего браузера."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"настраивать сигнал будильника"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Позволяет настраивать сигнал установленного приложения будильника. Для некоторых приложений будильника эта функция может быть недоступна."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Изменить разрешения браузера для доступа к географическому местоположению"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Позволяет программе изменять разрешения браузера для доступа к географическому положению. Вредоносные программы могут пользоваться этим для отправки информации о местоположении на некоторые сайты."</string>
     <string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Найдена доступная сеть Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Найдены доступные сети Wi-Fi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Введите символ"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Неизвестное приложение"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Отправка SMS-сообщений"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Подключен как устройство хранения данных"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Подключен как камера"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Подключен как установщик"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Нажмите, чтобы увидеть другие параметры USB"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматирование USB-накопителя безвозвратно удалит все файлы на нем! Продолжить?"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Спец. возможности"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Сеть VPN активна."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Серийный номер:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Отпечатки:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Отпечаток SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Отпечаток SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Просмотреть все"</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e622cf1..4af1a79 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Umožňuje aplikáciám sledovať, ktoré klávesy používate, a to aj pri práci s inými aplikáciami (napríklad pri zadávaní hesla). Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"väzba na metódu vstupu"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania metódy vstupu. Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie vôbec nemali využívať."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"PSČ"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Štát"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"PSČ"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Kraj"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ostrov"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Okres"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Oddelenie"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektúra"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Farnosť"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Oblasť"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirát"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Čítanie histórie a záložiek prehliadača"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikácii čítať všetky adresy URL navštívené prehliadačom a záložky prehliadača."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Zapisovať históriu a záložky prehliadača"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umožňuje aplikácii zmeniť históriu prehliadača alebo záložky uložené v telefóne. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť údaje prehliadača."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"nastaviť budík"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Umožní aplikácii nastaviť budík v nainštalovanej aplikácii budíka. Niektoré aplikácie budíka nemusia túto funkciu obsahovať."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Zmeniť oprávnenia prehliadača poskytovať informácie o zemepisnej polohe"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikácii zmeniť oprávnenie prehliadača poskytovať informácie o zemepisnej polohe. Škodlivé aplikácie môžu toto nastavenie použiť na odosielanie informácií o umiestnení na ľubovoľné webové stránky."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prehliadač zapamätal toto heslo?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"K dispozícii je verejná sieť Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"K dispozícii sú verejné siete Wi-Fi"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Vkladanie znakov"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznáma aplikácia"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odosielanie správ SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pripojené ako mediálne zariadenie"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pripojené ako fotoaparát"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pripojené ako inštalátor"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Dotykom zobrazíte ďalšiu možnosť USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete ukladací priestor USB naformátovať a vymazať tak všetky súbory, ktoré sú v ňom uložené? Túto akciu nie je možné vrátiť späť."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Sieť VPN je aktivovaná."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Sériové číslo:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Digitálne odtlačky:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Digitálny odtlačok SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Digitálny odtlačok SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Zobraziť všetko..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d68a3a5..9b45470 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Programu dovoljuje spremljanje tipk, ki jih pritisnete med interakcijo z drugim programom (na primer vnos gesla). Navadni programi tega nikoli ne potrebujejo."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"povezovanje z načinom vnosa"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Dovoljuje lastniku, da se poveže z vmesnikom načina vnosa najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezovanje z ozadjem"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Dovoljuje, da se lastnik poveže z vmesnikom ozadja najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string>
@@ -492,7 +496,7 @@
     <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="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Omogoča spreminjanje načina obračunavanja uporabe omrežja za posamezne programe. Ni za uporabo 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>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provinca"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Poštna številka"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Zvezna država"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Poštna številka"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Okrožje"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Otok"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Okraj"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Departma"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Župnija"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Območje"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"branje zgodovine in zaznamkov brskalnika"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Programu dovoljuje branje vseh URL-jev, ki jih je brskalnik obiskal, in vseh brskalnikovih zaznamkov."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje zgodovine in zaznamkov brskalnika"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Programu dovoljuje spreminjanje zgodovine brskalnika ali zaznamkov, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov brskalnika."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"nastavitev alarma budilke"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Programu omogoča nastavitev alarma v nameščeni budilki. Nekatere budilke morda ne bodo uporabile te funkcije."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Spreminjanje dovoljenj za geolokacijo brskalnika"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Programu dovoljuje spreminjanje dovoljenja brskalnika za geografske lokacije. Zlonamerni programi lahko s tem dovoljenjem dovolijo pošiljanje podatkov o lokaciji poljubnim spletnim mestom."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ali želite, da si brskalnik zapomni to geslo?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Odpiranje razpoložljivega brezžičnega omrežja"</item>
     <item quantity="other" msgid="7915895323644292768">"Odpiranje razpoložljivih brezžičnih omrežij"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Vstavljanje znaka"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznan program"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Pošiljanje sporočil SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Povezan kot predstavnostna naprava"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Povezan kot fotoaparat"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Povezan kot namestitveni program"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Dotaknite se, če želite izbrati druge možnosti za USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ali želite formatirati pomnilnik USB in izbrisati vse datoteke, shranjene na njem? Dejanje je dokončno."</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN je aktiviran."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serijska številka:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Prstni odtisi:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Prstni odtis SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Prstni odtis SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Prikaži vse ..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Izberite dejavnost"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Skupna raba z ..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 1604a94..4d25343 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Омогућава да апликације виде које тастере притискате чак и док радите у некој другој апликацији (нпр. када уносите лозинку). Нормалне апликације никада не би требало да је користе."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"обавезивање на методу уноса"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Омогућава власнику да се обавеже на интерфејс методе уноса највишег нивоа. Обичне апликације никада не би требало да је користе."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обавезивање на позадину"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Омогућава власнику да се обавеже на интерфејс позадине највишег нивоа. Обичне апликације никада не би требало да је користе."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Покрајина"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Поштански број"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Држава"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Поштански број"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Округ"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Острво"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Дистрикт"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Одељење"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Парохија"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Област"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Емират"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читање историје и обележивача у прегледачу"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Омогућава да апликација чита све URL адресе које су посећене у прегледачу, као и све обележиваче у њему."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"уписивање историје и обележивача из прегледача"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Омогућава да апликација измени историју и обележиваче у прегледачу сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке у прегледачу."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"подешавање аларма у будилнику"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозвољава да апликација подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Измена дозвола за географске локације прегледача"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Омогућава да апликација измени дозволе за утврђивање географске локације у прегледачу. Злонамерне апликације то могу да злоупотребе и искористе за слање информација о локацији насумичним веб сајтовима."</string>
     <string name="save_password_message" msgid="767344687139195790">"Желите ли да прегледач запамти ову лозинку?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Доступна је отворена Wi-Fi мрежа"</item>
     <item quantity="other" msgid="7915895323644292768">"Доступне су отворене Wi-Fi мреже"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Уметање знака"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Непозната апликација"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Слање SMS порука"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Повезан као медијски уређај"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Повезан као камера"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Повезан као инсталациони програм"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Додирните за друге USB опције"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Желите да форматирате USB меморију и избришете све датотеке у њој? Ову радњу није могуће опозвати!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Приступачност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN је активиран."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Серијски број:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Дигитални отисци:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 дигитални отисак:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 дигитални отисак:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Прикажи све..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d3e3848..3de0006b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Tillåter att program övervakar knapparna som du trycker på, till och med när du använder andra program (till exempel när du anger ett lösenord). Ska inte behövas för vanliga program."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"binda till en metod för indata"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en inmatningsmetod. Ska inte behövas för vanliga program."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binda till en bakgrund"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en bakgrund. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Delstat"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Kommun"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ö"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Department"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Församling"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"läsa webbläsarhistorik och bokmärken"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillåter att program läser alla webbadresser som webbläsaren har öppnat och alla webbläsarens bokmärken."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriva webbläsarhistorik och bokmärken"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Tillåter att ett program ändrar webbläsarhistoriken och bokmärkena i din telefon. Skadliga program kan använda detta för att ta bort eller ändra data i webbläsaren."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"ställa in alarm i alarmklocka"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillåter att programmet ställer in ett alarm i ett installerat alarmprogram. Vissa alarmprogram har inte den här funktionen."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ändra geografisk plats för webbläsaren"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillåter att ett program ändrar webbläsarens behörigheter för geografisk plats. Skadliga program kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
     <item quantity="other" msgid="7915895323644292768">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Infoga tecken"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Okänd app"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Skickar SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ansluten som en mediaenhet"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ansluten som en kamera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ansluten som installationsprogram"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Tryck för andra USB-alternativ"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatera SD-kort och radera alla filer? Åtgärden kan inte ångras!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN är aktiverad."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Fingeravtryck:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeravtryck"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeravtryck:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Visa alla..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Välj aktivitet"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Dela med..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0bf9ddf..d2c62bf 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -385,6 +385,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Huruhusu programu kutazama vitufe unavyobofya hata wakati unaingiliana na programu nyingine ya kompyuta (kama vile kuingiza nenosiri). Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"funganisha kwa mbinu ya uingizaji"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mbinu ya uingizaji. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa pazia"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha pazia. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
     <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -931,6 +935,30 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <!-- no translation found for autofill_province (2231806553863422300) -->
+    <skip />
+    <!-- no translation found for autofill_postal_code (4696430407689377108) -->
+    <skip />
+    <!-- no translation found for autofill_state (6988894195520044613) -->
+    <skip />
+    <!-- no translation found for autofill_zip_code (8697544592627322946) -->
+    <skip />
+    <!-- no translation found for autofill_county (237073771020362891) -->
+    <skip />
+    <!-- no translation found for autofill_island (4020100875984667025) -->
+    <skip />
+    <!-- no translation found for autofill_district (8400735073392267672) -->
+    <skip />
+    <!-- no translation found for autofill_department (5343279462564453309) -->
+    <skip />
+    <!-- no translation found for autofill_prefecture (2028499485065800419) -->
+    <skip />
+    <!-- no translation found for autofill_parish (8202206105468820057) -->
+    <skip />
+    <!-- no translation found for autofill_area (3547409050889952423) -->
+    <skip />
+    <!-- no translation found for autofill_emirate (2893880978835698818) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"soma historia na alamisho za Kivinjari"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Huruhusu programu kusoma URL zote ambazo Kivinjari imetembelea, na alamisho zile zingine zote za Kivinjari."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"andika historia ya Kivinjari na alamisho"</string>
@@ -938,6 +966,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Huruhusu programu kurekebisha historia au alamisho za Kivinjari zilizohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kufuta au kurekebisha data ya Kivinjari chako."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"weka kengele kwenye saa ya kengele"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Huruhusu programu kuweka kengele kwenye programu iliyosakinishwa ya saa ya kengele. Baadhi ya programu zasaa ya kengele hazingeweza kurekebisha kipengele hiki."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Rekebisha vibali vya Kivinjari cha eneo la jiografia"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Huruhusu programu kwa kurekebisha vibali vya Kivinjari cha eneo la jeo. Programu hasidi zinaweza kutumia hii kwa kuruhusu utumaji wa habari ya eneo kwa tovuti mbadala."</string>
     <!-- no translation found for save_password_message (767344687139195790) -->
@@ -1192,6 +1224,22 @@
     <item quantity="one" msgid="1634101450343277345">"Fungua mtandao wa Wi-Fi unaopatikana"</item>
     <item quantity="other" msgid="7915895323644292768">"Fungua mitandao ya Wi-Fi inayopatikana"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Ingiza kibambo"</string>
     <!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
     <skip />
@@ -1253,6 +1301,8 @@
     <skip />
     <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
     <skip />
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+    <skip />
     <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fomati hifadhi ya USB"</string>
@@ -1437,8 +1487,10 @@
     <skip />
     <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+    <skip />
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index d73ff99..a453ac1 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -17,4 +17,5 @@
 <resources>
     <bool name="preferences_prefer_dual_pane">true</bool>
     <bool name="show_ongoing_ime_switcher">false</bool>
+    <bool name="action_bar_expanded_action_views_exclusive">false</bool>
 </resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 9ffe6b1..553632b 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -44,5 +44,14 @@
     <!-- Size of status line font in LockScreen. -->
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
 
+    <!-- Preference activity, vertical padding for the header list -->
+    <dimen name="preference_screen_header_vertical_padding">16dp</dimen>
+
+    <!-- Reduce the margin when using dual pane -->
+    <!-- Preference activity side margins -->
+    <dimen name="preference_screen_side_margin">0dp</dimen>
+    <!-- Preference activity side margins negative-->
+    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
+
 </resources>
 
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 2d5b249..0e1e8c1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"อนุญาตให้แอปพลิเคชันดูปุ่มที่คุณกดแม้ในระหว่างที่ทำงานร่วมกับแอปพลิเคชันอื่น (เช่น ป้อนรหัสผ่าน) ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"เชื่อมโยงกับวิธีป้อนข้อมูล"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"อนุญาตให้ผู้ถือเชื่อมโยงกับอินเทอร์เฟซระดับสูงสุดของวิธีป้อนข้อมูล ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"เชื่อมโยงกับวอลเปเปอร์"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"อนุญาตให้ผู้ถือเชื่อมโยงกับอินเทอร์เฟซระดับสูงสุดของวอลเปเปอร์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"จังหวัด"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"รหัสไปรษณีย์"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"รัฐ"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"รหัสไปรษณีย์"</string>
+    <string name="autofill_county" msgid="237073771020362891">"อำเภอ"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"เกาะ"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"เขต"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"แผนก"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"เขตปกครอง"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"เขตการปกครองท้องถิ่น"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"พื้นที่"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"เอมิเรต"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"อ่านประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"อนุญาตให้แอปพลิเคชันอ่าน URL ทั้งหมดที่เบราว์เซอร์เคยเข้าชมและบุ๊กมาร์กของเบราว์เซอร์ทั้งหมด"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"เขียนประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"อนุญาตให้แอปพลิเคชันแก้ไขประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลเบราว์เซอร์ของคุณได้"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"ตั้งเวลาปลุกในนาฬิกาปลุก"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"อนุญาตให้แอปพลิเคชันนี้ตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้งไว้ แอปพลิเคชันนาฬิกาปลุกบางประเภทอาจไม่ใช้คุณลักษณะนี้"</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้อนุญาตให้ส่งข้อมูลตำแหน่งไปที่เว็บไซต์อื่นได้โดยพลการ"</string>
     <string name="save_password_message" msgid="767344687139195790">"คุณต้องการให้เบราว์เซอร์จำรหัสผ่านนี้หรือไม่"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
     <item quantity="other" msgid="7915895323644292768">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"ใส่อักขระ"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"ไม่ทราบแอปพลิเคชัน"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"กำลังส่งข้อความ SMS"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"เชื่อมต่อเป็นอุปกรณ์สื่อ"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"เชื่อมต่อเป็นกล้องถ่ายรูป"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"เชื่อมต่อเป็นตัวติดตั้ง"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"แตะสำหรับตัวเลือก USB อื่นๆ"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"ฟอร์แมตที่เก็บข้อมูล USB โดยลบไฟล์ทั้งหมดที่จัดเก็บอยู่ในนั้นหรือไม่ การทำงานนี้ไม่สามารถย้อนกลับได้"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"การเข้าถึง"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN เปิดใช้งานแล้ว"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"หมายเลขซีเรียล:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"ลายนิ้วมือ"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"ลายนิ้วมือ SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"ลายนิ้วมือ SHA-1"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"ดูทั้งหมด..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"เลือกกิจกรรม"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"แบ่งปันกับ..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 5b3eed0..12c14c3 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Pinapayagan ang mga application na panoorin ang mga pinipindot mong key maging kapag nakikipag-ugnay sa isa pang application (gaya ng pagpasok ng password). Hindi dapat na kailanganin kailanman para sa mga normal na application."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"sumailalim sa isang pamamaraan ng pag-input"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Pinapayagan ang holder na sumailalim sa nangungunang antas na interface ng pamamaraan ng pag-input. Hindi dapat kailanmang kailanganin para sa mga normal na application."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sumailalim sa wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Pinapayagan ang holder na sumailalim sa interface na nasa nangungunang antas ng wallpaper. Hindi kailanman dapat na kailanganin para sa mga normal na application."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Lalawigan"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Postal code"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"ZIP code"</string>
+    <string name="autofill_county" msgid="237073771020362891">"County"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Pulo"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Kagawaran"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Prefecture"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Parokya"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Lugar"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirate"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"basahin ang kasaysayan at mga bookmark ng Browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Pinapayagan ang application na basahin ang lahat ng URL na binisita ng Browser, at lahat ng bookmark ng Browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"isulat ang kasaysayan ng Browser at mga bookmark"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Pinapayagan ang isang application na baguhin ang kasaysayan o mga bookmark ng Browser na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng Browser."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"itakda ang alarm sa alarm clock"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Pinapayagan ang application na magtakda ng alarm sa isang naka-install na application ng alarm clock. Maaaring hindi ipatupad ng ilang application ng alarm clock ang tampok na ito."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Baguhin ang mga pahintulot ng Browser geolocation"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Pinapayagan ang isang application na baguhin ang mga pahintulot sa geolocation ng Browser. Magagamit ito ng mga nakakahamak na application upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi saklaw na web site."</string>
     <string name="save_password_message" msgid="767344687139195790">"Gusto mo bang tandaan ng browser ang password na ito?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Available ang bukas na Wi-Fi network"</item>
     <item quantity="other" msgid="7915895323644292768">"Buksan ang mga available na Wi-Fi network"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Magpasok ng character"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Hindi kilalang application"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Nagpapadala ng mga SMS na mensahe"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Nakakonekta bilang isang media device"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Nakakonekta bilang isang camera"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Nakakonekta bilang isang installer"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"I-touch para sa mga ibang pagpipilian sa USB"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"I-format ang imbakan na USB, na binubura ang lahat ng mga file na nakaimbak doon? Hindi maaaring maibalik ang pagkilos!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Isinaaktibo ang VPN."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Serial number:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Mga fingerprint:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 na fingerprint:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 na fingerprint:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tingnan lahat..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Pumili ng aktibidad"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Ibahagi sa..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8aea16d..ca29d65 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Uygulamaların, başka bir uygulama ile etkileşim halindeyken (örneğin bir şifre girerken) bile bastığınız tuşları izlemesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"bir giriş yöntemine bağla"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Tutucunun bir giriş yönteminin en üst düzey arayüzüne bağlanmasına izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bir duvar kağıdına tabi kıl"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Hesap sahibine bir duvar kağıdının en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Vilayet"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Posta kodu"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Eyalet"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Posta kodu"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Belde"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Ada"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"İlçe"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Bölüm"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"İdari Bölge"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Mahalle"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Alan"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Emirlik"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Tarayıcı geçmişini ve favorileri oku"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Uygulamaya Tarayıcının ziyaret etmiş olduğu tüm URL\'leri ve Tarayıcının tüm favorilerini okuma izni verir."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Tarayıcı geçmişini ve favorileri yaz"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Uygulamaya telefonunuzda depolanan Tarayıcı geçmişini veya favorileri değiştirme izni verir. Kötü amaçlı uygulamalar bunu Tarayıcı verilerinizi silmek veya değiştirmek için kullanabilir."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"çalar saatte alarm ayarla"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Uygulamanın yüklü bir çalar saat uygulamasında bir alarm ayarlamasına izin verir. Bazı çalar saat uygulamaları bu özelliği kullanmayabilir."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Bir uygulamanın, Tarayıcı\'nın coğrafi konum izinlerini değiştirmesine izin verir. Kötü amaçlı uygulamalar, bu özelliği konum bilgilerini rastgele web sitelerine göndermek için kullanabilir."</string>
     <string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Kullanılabilir kablosuz ağı aç"</item>
     <item quantity="other" msgid="7915895323644292768">"Kullanılabilir kablosuz ağları aç"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Bilinmeyen uygulama"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Medya cihazı olarak bağlandı"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera olarak bağlandı"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Yükleyici olarak bağlandı"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Diğer USB seçenekleri için dokunun"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB depolama birimi biçimlendirilsin mi? Depolama biriminde saklanan tüm dosyalar silinir. İşlem geri alınamaz!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN etkinleştirildi."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"Seri numara:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Parmak izleri:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 parmak izi:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 parmak izi:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tümünü göster..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5f50208..5a4a34c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Дозволяє програмі переглядати клавіші, які ви натискаєте, навіть під час роботи з іншою програмою (наприклад, під час вводу пароля). Ніколи не потрібний для звичайних програм."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"прив\'яз. до методу введ."</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Дозволяє власнику прив\'язувати до інтерфейсу верхнього рівня методу введення. Ніколи не потрібний для звичайних програм."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"прив\'зати до фон. мал."</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Дозволяє власнику прив\'язувати до інтерфейсу верхнього рівня фон. малюнка. Ніколи не потрібний для звичайних програм."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Провінція"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Поштовий код"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Штат"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Поштовий індекс"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Округ"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Острів"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Район"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Відділ"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Община"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Область"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Емірат"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читати історію та закладки переглядача"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Дозволяє програмі зчитувати всі URL-адреси, на які заходив переглядач, і всі закладки переглядача."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис. історію та закладки переглядача"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Дозволяє програмі змінювати історію чи закладки переглядача, збережені у вашому тел. Шкідливі програми можуть викор. це, щоб видаляти чи змінювати дані переглядача."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"налашт. сигнал у будильн."</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Змін. дозволи геогр. місцезн. перегладача"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Дозволяє програмі змін. дозволи географ. місцезн. переглядача. Шкідливі програми можуть використ. це, щоб дозволяти надсилати інф-ю про місцезн. випадковим веб-сайтам."</string>
     <string name="save_password_message" msgid="767344687139195790">"Хочете, щоб переглядач запам\'ятав цей пароль?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Відкрита Wi-Fi мережа доступна"</item>
     <item quantity="other" msgid="7915895323644292768">"Відкриті Wi-Fi мережі доступні"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Вставл-ня символу"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Невідома програма"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Надсил. SMS повідомлень"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Під’єднано як носій"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Під’єднано як камеру"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Під’єднано як програму встановлення"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Торкніться, щоб побачити інші параметри USB"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматувати носій USB, видаляючи всі збережені файли? Дію не можна скасувати!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Доступність"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фон. мал."</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"Мережу VPN активовано."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Серійний номер:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Відбитки:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Відбиток SHA-256"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Відбиток SHA-1"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Показати всі..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Вибрати дію"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Надіслати..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 38e33e3..a754a5c 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Cho phép ứng dụng xem các phím bạn nhấn ngay cả khi tương tác với ứng dụng khác (chẳng hạn như nhập mật khẩu). Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"liên kết với phương thức nhập"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Cho phép chủ nhân ràng buộc với giao diện cấp cao nhất của phương thức nhập. Không cần thiết cho các ứng dụng thông thường."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"liên kết với hình nền"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Cho phép chủ nhân ràng buộc với giao diện cấp cao nhất của hình nền. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"Tỉnh"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"Mã bưu chính"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"Tiểu bang"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"Mã ZIP"</string>
+    <string name="autofill_county" msgid="237073771020362891">"Hạt"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"Đảo"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"Quận"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"Khu hành chính"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"Quận"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"Giáo xứ"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"Khu vực"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"Tiểu vương quốc Ả rập"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"đọc lịch sử và dấu trang của Trình duyệt"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Cho phép ứng dụng đọc tất cả các URL mà Trình duyệt đã truy cập và tất cả các dấu trang của Trình duyệt."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"xem lịch sử và dấu trang của Trình duyệt"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt đượ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 Trình duyệt của bạn."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"đặt báo thức trong đồng hồ báo thức"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không sử dụng tính năng này."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Sửa đổi quyền về vị trí địa lý của Trình duyệt"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Cho phép ứng dụng sửa đổi các quyền về vị trí địa lý của Trình duyệt. Các ứng dụng độc hại có thể sử dụng quyền này để cho phép gửi thông tin vị trí đến trang web bất kỳ."</string>
     <string name="save_password_message" msgid="767344687139195790">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"Mở mạng Wi-Fi khả dụng"</item>
     <item quantity="other" msgid="7915895323644292768">"Mở mạng Wi-Fi khả dụng"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <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>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Đã kết nối là thiết bị truyền thông"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Đã kết nối như máy ảnh"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Được kết nối như trình cài đặt"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"Chạm để có các tùy chọn USB khác"</string>
     <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>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Định dạng bộ nhớ USB, xóa tất cả tệp được lưu trữ tại đây? Không thể hoàn tác tác vụ!"</string>
@@ -1015,10 +1049,8 @@
     <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>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN được kích hoạt."</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <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>
@@ -1095,18 +1127,13 @@
     <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 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) -->
+    <string name="serial_number" msgid="758814067660862493">"Số sê-ri:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"Tệp tham chiếu:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Tệp tham chiếu SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Tệp tham chiếu SHA-1:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Xem tất cả..."</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Chọn hoạt động"</string>
+    <string name="share_action_provider_share_with" msgid="1791316789651185229">"Chia sẻ với..."</string>
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/core/res/res/values-w1024dp/dimens.xml
similarity index 67%
copy from core/res/res/layout/text_edit_suggestions_bottom_window.xml
copy to core/res/res/values-w1024dp/dimens.xml
index 588bfbd..4d6a4da 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/core/res/res/values-w1024dp/dimens.xml
@@ -4,9 +4,9 @@
      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.
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
-
-</LinearLayout>
+<resources>
+    <!-- Increase size (used to be 0 for dual pane -->
+    <!-- Preference activity side margins -->
+    <dimen name="preference_screen_side_margin">48dp</dimen>
+    <!-- Preference activity side margins negative-->
+    <dimen name="preference_screen_side_margin_negative">-52dp</dimen>
+</resources>
diff --git a/core/res/res/values-w1280dp/dimens.xml b/core/res/res/values-w1280dp/dimens.xml
index e67b3a9..28aea55 100644
--- a/core/res/res/values-w1280dp/dimens.xml
+++ b/core/res/res/values-w1280dp/dimens.xml
@@ -18,6 +18,7 @@
 -->
 <resources>
     <dimen name="preference_screen_side_margin">96dp</dimen>
+    <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative -->
     <dimen name="preference_screen_side_margin_negative">-100dp</dimen>
     <dimen name="preference_widget_width">64dp</dimen>
     <!-- Preference fragment padding, bottom -->
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 863e3fa..6daa793 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"允许应用程序查看您按的键,即使在与其他应用程序交互(例如输入密码)时也不例外。普通应用程序从不需要使用此权限。"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"绑定至输入法"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允许手机用户绑定至输入法的顶级界面。普通应用程序从不需要使用此权限。"</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允许手机用户绑定到壁纸的顶级界面。应该从不需要将此权限授予普通应用程序。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到窗口小部件服务"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"省/直辖市/自治区"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"邮政编码"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"州"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"邮政编码"</string>
+    <string name="autofill_county" msgid="237073771020362891">"郡"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"岛"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"地区"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"省"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"县/府/都/道"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"行政区"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"区域"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"酋长国"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"允许应用程序修改存储在手机中的浏览器历史记录或书签。恶意应用程序可借此清除或修改浏览器数据。"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"在闹钟中设置警报"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"允许应用程序在安装的闹钟应用程序中设置警报。某些闹钟应用程序没有实现此功能。"</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改浏览器的地理位置权限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允许应用程序修改浏览器的地理位置权限。恶意应用程序会利用这一点将位置信息发送到任意网站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
     <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"插入字符"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"未知的应用程序"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"作为媒体设备连接"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"作为相机连接"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"作为安装程序连接"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"触摸可显示其他 USB 选项"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"确定要格式化 USB 存储设备,清除其中存储的全部文件吗?该操作将无法撤消!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN 已激活。"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"序列号:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"指纹:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指纹:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指纹:"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"查看全部..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a9a6e4e..411b24f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -262,6 +262,10 @@
     <string name="permdesc_readInputState" msgid="5132879321450325445">"允許應用程式在使用者操作其他程式時 (例如:輸入密碼),仍可監看輸入的按鍵。一般應用程式應不需要此功能。"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"連結至輸入法"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允許擁有人連結至輸入法的最頂層介面。一般應用程式不需使用此選項。"</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允許擁有人連結至桌布的最頂層介面,一般應用程式不需使用此選項。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
@@ -701,6 +705,18 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <string name="autofill_province" msgid="2231806553863422300">"省"</string>
+    <string name="autofill_postal_code" msgid="4696430407689377108">"郵遞區號"</string>
+    <string name="autofill_state" msgid="6988894195520044613">"州/省"</string>
+    <string name="autofill_zip_code" msgid="8697544592627322946">"郵遞區號"</string>
+    <string name="autofill_county" msgid="237073771020362891">"縣/市"</string>
+    <string name="autofill_island" msgid="4020100875984667025">"島"</string>
+    <string name="autofill_district" msgid="8400735073392267672">"行政區"</string>
+    <string name="autofill_department" msgid="5343279462564453309">"省"</string>
+    <string name="autofill_prefecture" msgid="2028499485065800419">"縣"</string>
+    <string name="autofill_parish" msgid="8202206105468820057">"教區"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"區"</string>
+    <string name="autofill_emirate" msgid="2893880978835698818">"大公國"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"讀取瀏覽器的記錄與書籤"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
@@ -708,6 +724,10 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"在鬧鐘應用程式中設定鬧鈴"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允許應用程式修改瀏覽器的地理位置權限,惡意應用程式可能會透過此方式允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
@@ -899,6 +919,22 @@
     <item quantity="one" msgid="1634101450343277345">"開啟可用 Wi-Fi 網路"</item>
     <item quantity="other" msgid="7915895323644292768">"開啟可用 Wi-Fi 網路"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"插入字元"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"未知的應用程式"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"傳送 SMS 簡訊"</string>
@@ -944,14 +980,12 @@
     <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_mtp_notification_title (3699913097391550394) -->
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"已視為媒體裝置連線"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"已視為相機連線"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"已視為安裝程式連線"</string>
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
     <skip />
-    <!-- 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="usb_notification_message" msgid="4447869605109736382">"輕觸即可顯示其他 USB 選項"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"格式化 USB 儲存裝置時,是否清除其中儲存的所有檔案?這項動作無法復原!"</string>
@@ -1015,10 +1049,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"協助工具"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
-    <!-- no translation found for vpn_title (8219003246858087489) -->
-    <skip />
-    <!-- no translation found for vpn_title_long (6400714798049252294) -->
-    <skip />
+    <string name="vpn_title" msgid="8219003246858087489">"VPN 已啟用。"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <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>
@@ -1095,18 +1127,15 @@
     <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) -->
+    <string name="serial_number" msgid="758814067660862493">"序號:"</string>
+    <string name="fingerprints" msgid="4516019619850763049">"指紋"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指紋"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋"</string>
+    <string name="activity_chooser_view_see_all" msgid="180268188117163072">"查看所有活動..."</string>
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
     <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) -->
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e712d7b..f224e63 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -191,8 +191,8 @@
     <!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
     <skip />
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Kunokususa <xliff:g id="CONTENT_TYPE">%s</xliff:g> okuningi kakhulu."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
-    <!-- outdated translation 2292820184396262278 -->     <string name="low_memory" product="default" msgid="6632412458436461203">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Isitoreji sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
+    <!-- outdated translation 2292820184396262278 -->     <string name="low_memory" product="default" msgid="6632412458436461203">"Isitoreji sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
     <!-- no translation found for me (6545696007631404292) -->
     <skip />
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Okukhethwa kukho kwethebhulethi"</string>
@@ -265,8 +265,8 @@
     <!-- no translation found for permgrouplab_developmentTools (3446164584710596513) -->
     <skip />
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Izici zidingeka kuphela konjiniyela bohlelo lokusebenza."</string>
-    <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukugcina"</string>
-    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kukugcina nge-USB."</string>
+    <string name="permgrouplab_storage" msgid="1971118770546336966">"Isitoreji"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kwisitoreji se-USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Finyelela ikhadi le-SD."</string>
     <!-- no translation found for permlab_statusBar (7417192629601890791) -->
     <skip />
@@ -298,7 +298,7 @@
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ivumela uhlelo lokusebena ukufunda imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zifunde imiyalezo eyimfihlo."</string>
     <!-- no translation found for permlab_writeSms (6881122575154940744) -->
     <skip />
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezi-malicious zingase zisuse imiyalezo yakho."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string>
     <!-- no translation found for permlab_receiveWapPush (8258226427716551388) -->
     <skip />
@@ -322,7 +322,7 @@
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"vumela imodi yemoto"</string>
     <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Ivumela uhlelo lokusebenza ukuvumela imodi yemoto."</string>
     <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"bulala izinqubo zasemuva"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ivumela uhlelo lokusebenza ukubulala izinqubo zasemuva zezinye izinhlelo zokusebenza, ngisho noma inkumbulo iphansi kakhulu."</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ivumela uhlelo lokusebenza ukubulala izinqubo zasemuva zezinye izinhlelo zokusebenza, ngisho noma imemori iphansi kakhulu."</string>
     <string name="permlab_forceStopPackages" msgid="1447830113260156236">"phoqelela ukumisa ezinye izinhlelo zokusebenza"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Ivumela uhlelo lokusebenza ukumisa ngokuphoqelela ezinye izinhlelo zokusebenza."</string>
     <!-- no translation found for permlab_forceBack (1804196839880393631) -->
@@ -341,7 +341,7 @@
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Igwema umsebenzisi ukuba ashintshele kolunye uhlelo lokusebenza."</string>
     <!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) -->
     <skip />
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezi-malicious zingase zonakalise ngokuphelele uhlelo. Le mvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezinonya zingase zonakalise ngokuphelele uhlelo. Le mvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string>
     <!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) -->
     <skip />
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ivumela uhlelo lokusebenza ukusakaza isaziso sokuthi iphakheji yohlelo lokusebenza ikhishiwe. Izinhlelo ezinonya zingasebenzisa lokhu ukubulala olunye uhlelo lokusebenza olusebenzayo."</string>
@@ -369,7 +369,7 @@
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ivumela ukwenziwa kwemawindi ehloselwe ukusebenziswa uxhumano lomsebenzisi wohlelo lwangaphakathi. Ayisebenziswa izinhlelo zokusebenza ezivamile"</string>
     <!-- no translation found for permlab_systemAlertWindow (3372321942941168324) -->
     <skip />
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezi-malicious zingase zithathe isikrini sonke."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezinonya zingase zithathe isikrini sonke."</string>
     <!-- no translation found for permlab_setAnimationScale (2805103241153907174) -->
     <skip />
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ivumela uhlelo lokusebenza ukushintsha isivinini sokugqwayiza jikelele (ukugqwayiza okusheshayo noma okulengayo) nganoma isiphi isikhathi."</string>
@@ -378,13 +378,17 @@
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Ivumela izinhlelo zokusebenza ukwenza nokuphatha amathokhini awo, ngokudlula ukuhleleka kuka-Z. Akusoze kwadingeka ezinhlelweni ezivamile."</string>
     <!-- no translation found for permlab_injectEvents (1378746584023586600) -->
     <skip />
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebenza. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthatha ithebhulethi."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebenza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ithebhulethi."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebeza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ifoni."</string>
     <!-- no translation found for permlab_readInputState (469428900041249234) -->
     <skip />
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Ivumela izinhlelo zokusebenza ukufunda izinkinobho ozicindezela ngisho noma uxhumana nolunye uhlelo lokusebenza (njengokufaka iphasiwedi). Akusoze kwadingeka ezinhlelweni zokusebenza ezivamile."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"hlanganisa indlela yokufakwayo"</string>
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ivumela isimeli ukuhlanganisa uxhumano nomsebenzisi wezinga eliphezulu lendlela yokufaka. Ayisoze yadingeka kwizinhlelo ezivamile."</string>
+    <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+    <skip />
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"hlanganisa kwiphephadonga"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwephephadonga. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
     <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -422,8 +426,8 @@
     <string name="permdesc_installPackages" msgid="526669220850066132">"Ivumela uhlelo lokusebenza ukufaka amaphakheji amasha noma abuyekeziwe. Izinhlelo ezinonya zingasebenzisa lokhu ukufaka izinhelo zokusebenza ezintsha ngezimvume zomthetho onamandla."</string>
     <!-- no translation found for permlab_clearAppCache (4747698311163766540) -->
     <skip />
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ivumela uhlelo lokusebenza ukukhulula ukugcina kwethebhulethii ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yohlelo."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ivumela uhlelo lokusebenza ukukhulula ukugcina kwefoni ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yohlelo."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ivumela uhlelo lokusebenza ukukhulula isitoreji sethebhulethi ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yesistimu."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ivumela uhlelo lokusebenza ukukhulula isitoreji sefoni ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqutshweni yesitimu."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Hambisa izinsiza zohlelo lokusebenza"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Ivumela uhlelo lokusebenza ukukhipha izinsiza zohlelo lokusebenza kwimidiya yangaphakathi iziyisa kweyangaphandle nangokuguquka."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"funda idatha yefayela lokungena ebucayi"</string>
@@ -434,8 +438,8 @@
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ivumela uhlolo lokusebenza ukufunda nokubhala kunoma yimuphi umthombo weqembu ledayegi; ngokwesibonle, amafayela akwi/dev. Lokhu kungase kuthinte kakhulu ukuba nokuphepha kohlelo. Lokhu kumele kusebenziselwe KUPHELA ukuhlola ihadiwe okucacile ngumkhiqizi noma u-opheretha."</string>
     <!-- no translation found for permlab_changeComponentState (79425198834329406) -->
     <skip />
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
-    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
     <!-- no translation found for permlab_setPreferredApplications (3393305202145172005) -->
     <skip />
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ivumela uhlelo lokusebenza ukuguqula izinhlelo zakho ezikhethwayo. Lokhu kungavumela izinhlelo ezinonya ukushintsha ngokuthulile izinhlelo zokusebenza ezisebenziswayo, ukushintsha izinhlelo zakho zokusebenza ezikhona kakade ukuqoqa idatha yangasese kuwe."</string>
@@ -453,15 +457,15 @@
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ivumela uhlelo lokusebenza ukuba luziqalele ngokushesha nje emva kokuba uhlelo luqede ukuqala. Lokhu kungenza kuthathe isikhathi ukuqalisa ifoni futhi kuvumele uhlelo lokusebenza ukwehlisa ifoni yonke ngokusebenza njalo."</string>
     <!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
     <skip />
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezi-malicious zingenza ithebhulethii ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ithebhulethii ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ivumela uhlelo lokusebenza ukuthumela imisakazo engazwakali kahle, esala emuva kokuthi ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingasebenzi kahle ngokuyibangela ukuthi isebenzise imemori eningi kakhulu."</string>
     <!-- no translation found for permlab_readContacts (6219652189510218240) -->
     <skip />
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo zokusebenza zonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
     <!-- no translation found for permlab_writeContacts (644616215860933284) -->
     <skip />
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
     <!-- no translation found for permlab_readProfile (2211941946684590103) -->
     <skip />
@@ -472,7 +476,7 @@
     <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
     <skip />
     <string name="permlab_readCalendar" msgid="6898987798303840534">"funda izenzakalo zekhalenda"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"Yengeza noma guqula izenzakalo zekhalenda bese uthumelela izivakashi i-imeyli"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ivumela uhlelo lokusebenza ukufaka noma ukushintsha izenzakalo ekhalendeni yakho, okungase kuthumele i-imeyli kubavakashi. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula izenzakalo zekhalenda noma ukuthumela abavakashi i-imeyli."</string>
@@ -486,11 +490,11 @@
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Yenza imithombo yokudlala ukuhlola. Izinhlelo ezinonya zingase zisebenzise lokhu ukukhipha indawo futhi/noma isimo esibuyiswe imithombo yendawo yangempela njenge-GPS noma abahlinzeki Benethiwekhi noma zigade futhi zibike indawo yakho njengomthombo wangaphandle."</string>
     <!-- no translation found for permlab_accessFineLocation (8116127007541369477) -->
     <skip />
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kwimithombo ecocekile Njegesistimu Yokumisa Jikelele kwithebhulethi, lapho itholakala. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kwimithombo ecocekile Njegesistimu Yokumisa Jikelele kwithebhulethi, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Finyelela kumithombo ecocekile Njegesistimu Yokumisa Jikelele efonini, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
     <!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) -->
     <skip />
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela indawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola endaweni elungile yethebhulethi, lapho itholakala khona. Izinhlelo zokusebenza ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela indawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola endaweni elungile yethebhulethi, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Finyelela kundawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola indawo elungile yefoni, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
     <!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) -->
     <skip />
@@ -516,19 +520,19 @@
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Ivumela uhlelo lokusebenza ukuphoqelela ifoni ukuqalisa phansi."</string>
     <!-- no translation found for permlab_mount_unmount_filesystems (1761023272170956541) -->
     <skip />
-    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ivumela izinhlelo ukukhweza nokukwehlisa izinhlelo zefayela zokugcina okukhiphekayo."</string>
-    <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"fometha ukugcina kwangaphandle"</string>
-    <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ivumela uhlelo lokusebenza ukufometha ukugcina okukhiphekayo."</string>
-    <string name="permlab_asec_access" msgid="3411338632002193846">"thola ukwaziswa ekugcineni kwangaphakathi"</string>
-    <string name="permdesc_asec_access" msgid="8820326551687285439">"Ivumela uhlelo lokusebenza ukuthola ukwaziswa ekugcineni kwangaphakathi."</string>
-    <string name="permlab_asec_create" msgid="6414757234789336327">"dala ukugcina kwangaphakathi"</string>
-    <string name="permdesc_asec_create" msgid="2621346764995731250">"Ivumela uhlelo lokusebenza ukwenza ukugcina kwangaphakathi."</string>
-    <string name="permlab_asec_destroy" msgid="526928328301618022">"yonakalisa ukugcina kwanaphakathi"</string>
-    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ivumela uhlelo lokusebenza ukonakalisa ukugcina kwangaphakathi."</string>
-    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"khweza / yehlisa ukugcina kwangaphakathi"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ivumela uhlelo lokusebenza ukukhuphula / ukwehlisa ukugcina kwangaphakathi."</string>
-    <string name="permlab_asec_rename" msgid="7496633954080472417">"qamba kabusha ukugcina kwangaphakathi"</string>
-    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ivumela uhlelo lokusebenza ukuqamba kabusha ukugcina kwangaphakathi."</string>
+    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ivumela izinhlelo ukukhweza nokukwehlisa amasistimu wefayela lesitoreji esikhiphekayo."</string>
+    <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"fometha isitoreji sangaphandle"</string>
+    <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ivumela uhlelo lokusebenza ukufometha isitoreji esikhiphekayo."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"thola ulwazi ngesitoreji sangaphakathi"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Ivumela uhlelo lokusebenza ukuthola ulwazi ngesitoreji sangaphakathi."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"dala isitoreji sangaphakathi"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Ivumela uhlelo lokusebenza ukudala isitoreji sangaphakathi."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"yonakalisa isitoreji sangaphakathi"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ivumela uhlelo lokusebenza ukonakalisa isitoreji sangaphakathi."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"khweza / yehlisa isitoreji sangaphakathi"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ivumela uhlelo lokusebenza ukukhweza / ukwehlisa isitoreji sangaphakathi."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"yetha kabusha isitoreji sangaphakathi"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ivumela uhlelo lokusebenza ukwetha kabusha isitoreji sangaphakathi."</string>
     <!-- no translation found for permlab_vibrate (7768356019980849603) -->
     <skip />
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Ivumela uhlelo lokusebenza ukulawula isidlidlizi."</string>
@@ -550,8 +554,8 @@
     <!-- no translation found for permlab_callPrivileged (4198349211108497879) -->
     <skip />
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Ivumela uhlelo lokusebenza ukushayela noma iyiphi inombolo yocingo, kuhlanganise izinombolo eziphuthumayo, ngaphandle kokungenela kwakho. Izinhlelo zokusebenza ezinonya zingase zenze izincingo ezingadingeki nezingekho ezimthethweni kwizinsizakalo eziphuthumayo."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukuhlela ithebhulethi nge-CDMA"</string>
-    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukuhlela ifoni nge-CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukumisa ithebhulethi nge-CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukumisa ifoni nge-CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Ivumela uhlelo lokusebenza ukuqalisa amalungiselelo e-CDMA. Izinhlelo ezinonya ngokungadingekile zingaqalisa amalungiselelo e-CDMA."</string>
     <!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
     <skip />
@@ -580,7 +584,7 @@
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Sebenzise njengokuhlola komkhiqizi wezinga eliphansi, uvumela ukufinyelela okugcwele ihadiwe yefoni. Itholakala kuphela lapho ifoni isebenza kwimodi yokuhlola yomkhiqizi."</string>
     <!-- no translation found for permlab_setWallpaper (6627192333373465143) -->
     <skip />
-    <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ivumela uhlelo lokusebenza ukuhlela iphephadonga lohlelo."</string>
+    <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ivumela uhlelo lokusebenza ukuhlela iphephadonga lesistimu."</string>
     <!-- no translation found for permlab_setWallpaperHints (3600721069353106851) -->
     <skip />
     <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Ivumela uhlelo lokusebenza ukuhlela izihlawumbisela zosayizi wephephadonga lohlelo."</string>
@@ -667,12 +671,12 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ivumela uhlelo lokusebenza ukufunda noma yimaphi amagama ayimfihlo, amagama nemisho leyo umsebenzisi ayigcine kwisichazamazwi somsebenzisi."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"bhala kwisichazamazwi esicacisiwe somsebenzisi"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ivumela uhlelo lokusebenza ukubhala amagama amasha kwisichazamazwi somsebenzisi."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe kokugcina nge-USB"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe isitoreji se-USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"guqula/susa okuqukethwe kwekhadi le-SD"</string>
-    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala ekugcineni nge-USB."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala kwisitoreji se-USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ivumela uhlelo lokusebenza ukubhala ekhadini le-SD."</string>
-    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"guqula/susa okuqukethwe kokugcina imidiya yangaphakathi"</string>
-    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ivumela uhlelo lokusebenza ukuguqula okuqukethwe kokugcina kwemidiya yangaphakathi."</string>
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"guqula/susa okuqukethwe kwisitoreji semidiya yangaphakathi"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ivumela uhlelo lokusebenza ukuguqula okuqukethwe kwisitoreji semidiya yangaphakathi."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"finyelela kunqolobane yesistimu yefayela"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Ivumela uhlelo lokusebenza ukufunda nokubhala uhlelo lwesistimu lwenqolobane."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"yena/thola amakholi e-Inthanethi"</string>
@@ -705,7 +709,7 @@
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Misa iphrokzi jikelele yedivaysi ukusebenzisa ngenkathi inqumbomgomo ivunyelwa. Idivaysi yokuqala kuphela yokuphatha emisa ummeleli jikelele esebenzayo."</string>
     <!-- outdated translation 2314569545488269564 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Hlela ukuphelelwa isikhathi kwephasiwedi."</string>
     <!-- outdated translation 7276906351852798814 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Lawula ukuthi iphasiwedi yokuvala isikrini kumele ishintshwe nini"</string>
-    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setha umbhalo wemfihlo wokugcina"</string>
+    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setha umbhalo wemfihlo yesitoreji"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Idinga ukuba idatha yohlelo lokusebenza olugciniwe ibhalwe ngokufihlekileyo"</string>
     <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
     <skip />
@@ -915,7 +919,7 @@
     <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <!-- no translation found for factorytest_failed (5410270329114212041) -->
     <skip />
-    <string name="factorytest_not_system" msgid="4435201656767276723">"Isenzo SOKUHLOLA KWASEMBONINI sisekelwa kuphela amaphakheji afakwi kwisistimu/uhlelo."</string>
+    <string name="factorytest_not_system" msgid="4435201656767276723">"Isenzo SOKUHLOLA_KWASEMBONINI sisekelwa kuphela amaphakheji afakwe kwisistimu/uhlelokusebenza."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Ayikho iphakheji etholakele enikeze isenzo SOKUHLOLA KWASEMBONINI."</string>
     <!-- no translation found for factorytest_reboot (6320168203050791643) -->
     <skip />
@@ -931,13 +935,41 @@
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+    <!-- no translation found for autofill_province (2231806553863422300) -->
+    <skip />
+    <!-- no translation found for autofill_postal_code (4696430407689377108) -->
+    <skip />
+    <!-- no translation found for autofill_state (6988894195520044613) -->
+    <skip />
+    <!-- no translation found for autofill_zip_code (8697544592627322946) -->
+    <skip />
+    <!-- no translation found for autofill_county (237073771020362891) -->
+    <skip />
+    <!-- no translation found for autofill_island (4020100875984667025) -->
+    <skip />
+    <!-- no translation found for autofill_district (8400735073392267672) -->
+    <skip />
+    <!-- no translation found for autofill_department (5343279462564453309) -->
+    <skip />
+    <!-- no translation found for autofill_prefecture (2028499485065800419) -->
+    <skip />
+    <!-- no translation found for autofill_parish (8202206105468820057) -->
+    <skip />
+    <!-- no translation found for autofill_area (3547409050889952423) -->
+    <skip />
+    <!-- no translation found for autofill_emirate (2893880978835698818) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"funda umlando Wesiphequluli namabhukimakhi"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ivumela uhlelo lokusebenza ukufunda wonke ama-URL lawo Isiphequluli esiwavakashele, ngisho nawo wonke amabhukimakhi Esiphequluli."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"bhala umlando Wesiphequluli namabhukhimaki"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"misa i-alamu ewashini le-alamu"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ivumela uhlelo lokusebenza ukumisa i-alamu kuhlelo lokusebenza lewashi le-alawmu elifakiwe. Ezinye izinhlelo zokusebenza zewashi le-alamu zingase zingasebenzisi lesi sici."</string>
+    <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+    <skip />
+    <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+    <skip />
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Gugula izimvume zendawo Yesiphequluli"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ivumela uhlelo lokusebenza ukuguqula izimvume zendawo Yesiphequluli. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvumela ukuthumela ukwaziswa kwendawo kwamanye amasayithi ewebhu."</string>
     <!-- no translation found for save_password_message (767344687139195790) -->
@@ -1094,8 +1126,8 @@
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
     <!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
     <skip />
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Isikhala sokugcina sethebhulethi siya ngokuphela."</string>
-    <!-- outdated translation 4231085657068852042 -->     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Isikhala sokugcina sethebhulethi siya ngokuphela."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Isitoreji sethebhulethi siya ngokuphela."</string>
+    <!-- outdated translation 4231085657068852042 -->     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Isitoreji sethebhulethi siya ngokuphela."</string>
     <!-- no translation found for ok (5970060430562524910) -->
     <skip />
     <!-- no translation found for cancel (6442560571259935130) -->
@@ -1192,6 +1224,22 @@
     <item quantity="one" msgid="1634101450343277345">"Vula inethiwekhi ye-Wi-Fi etholakalayo"</item>
     <item quantity="other" msgid="7915895323644292768">"Vula amanethiwekhi we-Wi-Fi atholakalayo"</item>
   </plurals>
+    <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+    <skip />
+    <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
     <!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
     <skip />
@@ -1224,27 +1272,27 @@
     <skip />
     <string name="perms_hide" msgid="7283915391320676226"><b>"Fihla "</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Bonisa konke"</b></string>
-    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Ukugcina Okukhulu nge-USB"</string>
+    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Isitoreji Sokukhulu se-USB"</string>
     <!-- no translation found for usb_storage_title (5901459041398751495) -->
     <skip />
-    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Uxhumeke kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nokugcina nge-Android USB yakho."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Uxhumeke kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nesitoreji se-Android USB yakho."</string>
     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Uxhume kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nekhadi lakho le-SD."</string>
-    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Vula ukuginca nge-USB"</string>
-    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kunenkinga yokusebenzisa ikhadi lakho le-SD lokugcina nge-USB."</string>
-    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kunenkinga yokusebenzisa ikhadi lakho le-SD lokugcina nge-USB."</string>
+    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Vula isitoreji se-USB"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kunenkinga yokusebenzisa ikhadi lakho le-SD njengesitoreji se-USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kunenkinga yokusebenzisa ikhadi lakho le-SD njengesitoreji se-USB."</string>
     <!-- no translation found for usb_storage_notification_title (8175892554757216525) -->
     <skip />
     <!-- no translation found for usb_storage_notification_message (7380082404288219341) -->
     <skip />
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vala ukugcina nge-USB"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Khetha ukuvala ukugcina nge-USB."</string>
-    <string name="usb_storage_stop_title" msgid="660129851708775853">"Ukugcina nge-USB kuyasebenza"</string>
-    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Ngaphambi kokuvala ukugcina nge-USB, qiniseka ukuthi wehlise (\"ukhiphe\") ukugcina nge-USB ye-Android yakho kwikhompyutha yakho."</string>
-    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Ngaphambi kokuvala ukugcina nge-USB, qiniseka ukuthi wehlise (\"ukhiphe\" ikhadi lakho le-Android SD kwikhompyutha yakho."</string>
-    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vala ukugcina nge-USB"</string>
-    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kube nenkinga yokuvala ukugcina nge-USB. Hlola ukuqiniseka ukuthi wehlise isikhungo se-USB, bese uzama futhi."</string>
-    <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Vula ukugcina nge-USB"</string>
-    <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="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vala isitoreji se-USB"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Khetha ukuvala isitoreji se-USB."</string>
+    <string name="usb_storage_stop_title" msgid="660129851708775853">"Isitoreji se-USB siyasebenza"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Ngaphambi kokuvala kwisitoreji se-USB, qiniseka ukuthi wehlise (\"ukhiphe\") isitoreji se-USB se-Android yakho kwikhompyutha yakho."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Ngaphambi kokuvala isitoreji se-USB, qiniseka ukuthi wehlise (\"ukhiphe\" ikhadi lakho le-Android SD kwikhompyutha yakho."</string>
+    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vala isitoreji se-USB"</string>
+    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kube nenkinga yokuvala isitoreji se-USB. Hlola ukuqiniseka ukuthi wehlise isikhungo se-USB, bese uzama futhi."</string>
+    <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Vula isitoreji se-USB"</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Uma uvula isitoreji se-USB, ezinye izinhlelo zokusebenza ozisebenzisayo zizoma futhi zingase zingatholakali kuze kube yilapho uvala isitoreji se-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_mtp_notification_title (3699913097391550394) -->
@@ -1253,11 +1301,13 @@
     <skip />
     <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
     <skip />
+    <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+    <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="nosdcard" msgid="7980995592595097841">"Fometha isitoreji se-USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fometha ikhadi le=SD"</string>
-    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Fometha ukugcina nge-USB, usule wonke amafayela agcinwe lapho? Isinyathelo asikwazi ukuguqulwa?"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Fometha isitoreji se-USB, usule wonke amafayela agcinwe lapho? Isinyathelo asikwazi ukuguqulwa?"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Uqinisekile ukuthi ufuna ukufometha ikhadi le-SD? Yonke idatha esekhadini lakho izolahleka."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Ifomethi"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
@@ -1268,28 +1318,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string>
-    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungiselela ukugcina nge-USB"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungiselela isitoreji se-USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Ilungisa ikhadi le-SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Ihlola amaphutha"</string>
-    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Ukugcina nge-USB okungenalutho"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Isitoreji se-USB esingenalutho"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Ikhadi le-SD elingenalutho"</string>
-    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Ukugcina nge-USB akunalutho noma kunohlelo lwefayela olungasekelwa."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311"></string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Ikhadi le-SD alinalutho noma lunohlelo lwesistimu olungasekelwa."</string>
-    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Ukugcina nge-USB okonakele"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Isitoreji se-USB esonakele"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Ikhadi le-SD elonakele"</string>
-    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Ukugcina nge-USB konakele. Kungase kudingeke ukufa ulifomethe futhi."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Isitoreji se-USB konakele. Kungase kudingeke ulifomethe kabusha."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Ikhadi le-SD lonakele. Kungase kudingeke ukuba uyifomethe futhi."</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Ukugcina nge-USB kukhishwe ngokungalindelekile"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Isitoreji se-USB sikhishwe ngokungalindelekile"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Ikhadi le-SD likhishwe ngokungalindelekile"</string>
-    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha ukugwema ukulahleka kwedatha."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha isitoreji se-USB ukugwema ukulahleka kwedatha."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha ukugwema ukulahleka kwedatha."</string>
-    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kuvikelekile ukukhipha ukugcina nge-USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Sekuphephile ukukhipha isitoreji se-USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kuphephile ukukhipha ikhadi le-SD"</string>
-    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ungakhipha ngokuvikelekile ukugcina nge-USB."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ungakhipha ngokuvikelekile isitoreji se-USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Ungakhipha ngokuphephile ikhadi le-SD."</string>
-    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ukugcina nge-USB kukhishiwe"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Isitoreji se-USB sikhishiwe"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Ikhadi le-SD elikhishiwe"</string>
-    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Ukugcina nge-USB kukhishiwe. Faka imidiya entsha."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Isitoreji se-USB sikhishiwe. Faka imidiya entsha."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Ikhadi le-SD likhishiwe. Faka elisha."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Ayikho imisebenzi efanayo etholakele"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"buyekeza izibalo zokusebenzisa ingxenye"</string>
@@ -1297,7 +1347,7 @@
     <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Ivumela uhlelo lokusebenza ukucelela insizakalo yesiqukathi esimisiwe ukukopisha kokuqukethwe. Ayisebenziswa izinhlelo zokusebenza ezivamile."</string>
     <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Ivumela ukucelela insizakalo yesiqukathi esimisiwe ukukopisha kokuqukethwe. Ayisebenziselwa izinhlelo zokusebenza ezivamile."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Thepha kabili ukuthola ukulawula ukusondeza"</string>
-    <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Iphutha lesinqunjwana"</string>
+    <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Iphutha lewijethi"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Iya"</string>
     <string name="ime_action_search" msgid="658110271822807811">"Sesha"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Thumela"</string>
@@ -1317,7 +1367,7 @@
     <string name="input_method_binding_label" msgid="1283557179944992649">"Indlela yokufakwayo"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"Vumelanisaa"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ukufinyeleleka"</string>
-    <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphepha donga"</string>
+    <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
     <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
@@ -1349,17 +1399,17 @@
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ku-<xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Kwenziwe"</string>
-    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Yehlisa ukugcina nge-USB..."</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Yehlisa isitoreji se-USB..."</string>
     <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Yehlisa ikhadi le-SD..."</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Isula ukugcina nge-USB."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Isula isitoreji se-USB."</string>
     <string name="progress_erasing" product="default" msgid="2115214724367534095">"Isula ikhadi le-SD..."</string>
-    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Yehlulekile ukusula ukugcina nge-USB"</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Yehlulekile ukusula isitoreji se-USB"</string>
     <string name="format_error" product="default" msgid="1343380371925238343">"Yehlulekile ukususa ikhadi le-SD."</string>
     <string name="media_bad_removal" msgid="7960864061016603281">"Ikhadi le-SD likhishwe ngaphambi kokuba lehliswe."</string>
-    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Ukugcina nge-USB okwamanje kusahlolwa."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Isitoreji se-USB sisahlolwa."</string>
     <string name="media_checking" product="default" msgid="7334762503904827481">"Ikhadi le-SD okwamanje liyahlolwa."</string>
     <string name="media_removed" msgid="7001526905057952097">"Ikhadi le-SD likhishiwe."</string>
-    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Ukugcina nge-USB okwamanje kusetshenziswa ikhompyutha."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Isitoreji se-USB sisasetshenziswa yikhompyutha."</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"Ikhadi le-SD okwamanje lisetshenziswa ikhompyutha."</string>
     <string name="media_unknown_state" msgid="729192782197290385">"Imidiya yangaphakathi kwisimo esingaziwa."</string>
     <string name="share" msgid="1778686618230011964">"Yabelana"</string>
@@ -1437,8 +1487,10 @@
     <skip />
     <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
     <skip />
-    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+    <skip />
+    <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
     <skip />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 0f04a67..bcf1991 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -22,6 +22,15 @@
     <!-- Do not translate. These are all of the drawable resources that should be preloaded by
          the zygote process before it starts forking application processes. -->
     <array name="preloaded_drawables">
+       <item>@drawable/spinner_black_16</item>
+       <item>@drawable/spinner_black_20</item>
+       <item>@drawable/spinner_black_48</item>
+       <item>@drawable/spinner_black_76</item>
+       <item>@drawable/spinner_white_16</item>
+       <item>@drawable/spinner_white_48</item>
+       <item>@drawable/spinner_white_76</item>
+       <item>@drawable/toast_frame</item>
+       <item>@drawable/toast_frame_holo</item>
        <item>@drawable/btn_check_on_selected</item>
        <item>@drawable/btn_check_on_pressed_holo_light</item>
        <item>@drawable/btn_check_on_pressed_holo_dark</item>
@@ -109,6 +118,11 @@
        <item>@drawable/btn_default_disabled_holo_dark</item>
        <item>@drawable/btn_default_disabled_focused_holo_light</item>
        <item>@drawable/btn_default_disabled_focused_holo_dark</item>
+       <item>@drawable/btn_dropdown_disabled</item>
+       <item>@drawable/btn_dropdown_disabled_focused</item>
+       <item>@drawable/btn_dropdown_normal</item>
+       <item>@drawable/btn_dropdown_pressed</item>
+       <item>@drawable/btn_dropdown_selected</item>
        <item>@drawable/btn_toggle_on_pressed_holo_light</item>
        <item>@drawable/btn_toggle_on_pressed_holo_dark</item>
        <item>@drawable/btn_toggle_on_normal_holo_light</item>
@@ -141,6 +155,10 @@
        <item>@drawable/edit_text_holo_light</item>
        <item>@drawable/edit_text_holo_dark</item>
        <item>@drawable/edit_text</item>
+       <item>@drawable/expander_close_holo_dark</item>
+       <item>@drawable/expander_close_holo_light</item>
+       <item>@drawable/expander_ic_maximized</item>
+       <item>@drawable/expander_ic_minimized</item>
        <item>@drawable/expander_group</item>
        <item>@drawable/expander_group_holo_dark</item>
        <item>@drawable/expander_group_holo_light</item>
@@ -157,6 +175,8 @@
        <item>@drawable/menu_background_fill_parent_width</item>
        <item>@drawable/menu_submenu_background</item>
        <item>@drawable/menu_selector</item>
+       <item>@drawable/overscroll_edge</item>
+       <item>@drawable/overscroll_glow</item>
        <item>@drawable/panel_background</item>
        <item>@drawable/popup_bottom_bright</item>
        <item>@drawable/popup_bottom_dark</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cfc5041..f6bf76b 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -711,12 +711,6 @@
         <!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. -->
         <attr name="textEditSideNoPasteWindowLayout" format="reference" />
 
-        <!-- Layout of a the view that is used to create the text suggestions popup window in an
-             EditText. This window will be displayed below the text line. -->
-        <attr name="textEditSuggestionsBottomWindowLayout" format="reference" />
-        <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed
-             above the current line of text instead of below. -->
-        <attr name="textEditSuggestionsTopWindowLayout" format="reference" />
         <!-- Layout of the TextView item that will populate the suggestion popup window. -->
         <attr name="textEditSuggestionItemLayout" format="reference" />
 
@@ -2281,6 +2275,8 @@
             <flag name="feedbackVisual" value="0x00000008" />
             <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
             <flag name="feedbackGeneric" value="0x00000010" />
+            <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_ALL_MASK} feedback. -->
+            <flag name="feedbackAllMask" value="0xffffffff" />
         </attr>
         <!-- 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
@@ -2302,6 +2298,8 @@
         <!-- Flag whether the accessibility service wants to be able to retrieve the
              active window content. This setting cannot be changed at runtime. -->
         <attr name="canRetrieveWindowContent" format="boolean" />
+        <!-- Short description of the accessibility serivce purpose or behavior.-->
+        <attr name="description" />
     </declare-styleable>
 
     <!-- =============================== -->
@@ -3078,12 +3076,6 @@
         <!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. -->
         <attr name="textEditSideNoPasteWindowLayout" />
 
-        <!-- Layout of a the view that is used to create the text suggestions popup window in an
-             EditText. This window will be displayed below the text line. -->
-        <attr name="textEditSuggestionsBottomWindowLayout" />
-        <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed
-             above the current line of text instead of below. -->
-        <attr name="textEditSuggestionsTopWindowLayout" />
         <!-- Layout of the TextView item that will populate the suggestion popup window. -->
         <attr name="textEditSuggestionItemLayout" />
 
@@ -3349,7 +3341,7 @@
         <!-- The row span: the difference between the bottom and top
         boundaries delimiting the group of cells occupied by this view.
         The default is one.
-        See {@link android.widget.GridLayout.Group}. -->
+        See {@link android.widget.GridLayout.Spec}. -->
         <attr name="layout_rowSpan" format="integer" min="1" />
         <!-- The column boundary delimiting the left of the group of cells
         occupied by this view. -->
@@ -3357,26 +3349,22 @@
         <!-- The column span: the difference between the right and left
         boundaries delimiting the group of cells occupied by this view.
         The default is one.
-        See {@link android.widget.GridLayout.Group}. -->
+        See {@link android.widget.GridLayout.Spec}. -->
         <attr name="layout_columnSpan" format="integer" min="1" />
         <!-- 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}.-->
+        <!-- {@deprecated To make a column group lexible, ensure that every component in the
+         group defines a horizontal gravity.} -->
         <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="inflexible" value="0" />
             <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}.-->
+        <!-- {@deprecated To make a row group flexible, ensure that every component in the
+         group defines a vertical gravity.} -->
         <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="inflexible" value="0" />
             <enum name="canStretch" value="2" />
         </attr>
     </declare-styleable>
@@ -4913,6 +4901,10 @@
         <attr name="minWidth"/>
         <!-- Minimum height of the AppWidget. -->
         <attr name="minHeight"/>
+        <!-- Minimum width that the AppWidget can be resized to. -->
+        <attr name="minResizeWidth" format="dimension"/>
+        <!-- Minimum height that the AppWidget can be resized to. -->
+        <attr name="minResizeHeight" format="dimension"/>
         <!-- Update period in milliseconds, or 0 if the AppWidget will update itself. -->
         <attr name="updatePeriodMillis" format="integer" />
         <!-- A resource id of a layout. -->
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index e51fc66..6e4db5e9 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -19,4 +19,5 @@
     <bool name="split_action_bar_is_narrow">true</bool>
     <bool name="preferences_prefer_dual_pane">false</bool>
     <bool name="show_ongoing_ime_switcher">true</bool>
+    <bool name="action_bar_expanded_action_views_exclusive">true</bool>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1f2b7fb..65dce49 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -182,6 +182,9 @@
     <!-- Boolean indicating whether the wifi chipset has dual frequency band support -->
     <bool translatable="false" name="config_wifi_dual_band_support">false</bool>
 
+    <!-- Boolean indicating whether the wifi chipset has p2p support -->
+    <bool translatable="false" name="config_wifi_p2p_support">false</bool>
+
     <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
          This mechanism allows the host to remain in suspend state and the dongle to actively
          scan and wake the host when a configured SSID is detected by the dongle. This chipset
@@ -466,6 +469,10 @@
          speech -->
     <bool name="config_bluetooth_wide_band_speech">true</bool>
 
+    <!-- Boolean indicating if current platform supports quick switch-on/off of
+         Bluetooth Module -->
+    <bool name="config_bluetooth_adapter_quick_switch">true</bool>
+
     <!-- The default data-use polling period. -->
     <integer name="config_datause_polling_period_sec">600</integer>
 
@@ -665,4 +672,7 @@
     <!-- Timeout to wait for NTP server response. -->
     <integer name="config_ntpTimeout">20000</integer>
 
+    <!-- Default network policy warning threshold, in megabytes. -->
+    <integer name="config_networkPolicyDefaultWarning">2048</integer>
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a5e5f70..b3e50ea 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -35,7 +35,7 @@
     <!-- Height of the system bar -->
     <dimen name="system_bar_height">48dip</dimen>
     <!-- Height of notification icons in the status bar -->
-    <dimen name="status_bar_icon_size">25dip</dimen>
+    <dimen name="status_bar_icon_size">24dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
     <!-- Height of notification icons in the system bar -->
@@ -67,9 +67,9 @@
     <dimen name="multiwaveview_hit_radius">60dip</dimen>
 
     <!-- Preference activity side margins -->
-    <dimen name="preference_screen_side_margin">0dp</dimen>
+    <dimen name="preference_screen_side_margin">16dp</dimen>
     <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">0dp</dimen>
+    <dimen name="preference_screen_side_margin_negative">16dp</dimen>
     <!-- Preference activity top margin -->
     <dimen name="preference_screen_top_margin">0dp</dimen>
     <!-- Preference activity bottom margin -->
@@ -96,6 +96,8 @@
          is along the major axis (that is the screen is landscape).  This may
          be either a fraction or a dimension. -->
     <item type="dimen" name="dialog_min_width_major">65%</item>
+    <!-- Preference activity, vertical padding for the header list -->
+    <dimen name="preference_screen_header_vertical_padding">0dp</dimen>
 
     <!-- The platform's desired minimum size for a dialog's width when it
          is along the minor axis (that is the screen is portrait).  This may
@@ -133,4 +135,19 @@
     <!-- Size of right margin on Unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_status_line_font_right_margin">45dip</dimen>
 
+    <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. -->
+    <dimen name="activity_chooser_popup_min_width">200dip</dimen>
+
+    <!-- The default gap between components in a layout. -->
+    <dimen name="default_gap">16dip</dimen>
+
+    <!-- Text padding for dropdown items -->
+    <dimen name="dropdownitem_text_padding_left">6dip</dimen>
+
+    <!-- Text padding for dropdown items -->
+    <dimen name="dropdownitem_text_padding_right">6dip</dimen>
+
+    <!-- Width of the icon in a dropdown list -->
+    <dimen name="dropdownitem_icon_width">48dip</dimen>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6dedc83..49c9447 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1715,12 +1715,8 @@
   <public type="attr" name="switchPreferenceStyle" />
 
   <public type="attr" name="textSuggestionsWindowStyle" />
-  <public type="attr" name="textEditSuggestionsBottomWindowLayout" />
-  <public type="attr" name="textEditSuggestionsTopWindowLayout" />
   <public type="attr" name="textEditSuggestionItemLayout" />
 
-  <public type="attr" name="layoutDirection" />
-
   <public type="attr" name="suggestionsEnabled" />
 
   <public type="attr" name="rowCount" />
@@ -1765,15 +1761,8 @@
   <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" />
@@ -1787,6 +1776,11 @@
   <public type="attr" name="colorActivatedHighlight" />
   <public type="attr" name="colorMultiSelectHighlight" />
 
+  <public type="attr" name="drawableStart" />
+  <public type="attr" name="drawableEnd" />
+
+  <public type="attr" name="actionModeStyle" />
+
   <public type="style" name="TextAppearance.SuggestionHighlight" />
   <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
   <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
@@ -1826,7 +1820,6 @@
   <public type="color" name="holo_purple" />
   <public type="color" name="holo_blue_bright" />
 
-  <public type="attr" name="drawableStart" />
-  <public type="attr" name="drawableEnd" />
-
+  <public type="attr" name="minResizeWidth" />
+  <public type="attr" name="minResizeHeight" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 70c204e..d698341 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -705,6 +705,12 @@
         interface of an input method. Should never be needed for normal applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindTextService">bind to a text service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindTextService">Allows the holder to bind to the top-level
+        interface of a text service(e.g. SpellCheckerService). Should never be needed for normal applications.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindWallpaper">bind to a wallpaper</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindWallpaper">Allows the holder to bind to the top-level
@@ -2152,6 +2158,14 @@
       not implement this feature.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether
+        they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permlab_readWriteOwnVoicemail">Access voicemails managed by this application</string>
+    <!-- Description of an application permission, listed so the user can choose whether
+        they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_readWriteOwnVoicemail">Allows the application to store and retrieve only
+      voicemails that its associated service can access.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether
         they want to allow the application to do this. -->
     <string name="permlab_writeGeolocationPermissions">Modify Browser geolocation permissions</string>
     <!-- Description of an application permission, listed so the user can choose whether
@@ -2560,9 +2574,23 @@
         <item quantity="one">Open Wi-Fi network available</item>
         <item quantity="other">Open Wi-Fi networks available</item>
     </plurals>
+
+     <!-- A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's title / ticker. -->
+    <string name="wifi_watchdog_network_disabled">A Wi-Fi network was disabled</string>
+    <!--  A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's message which leads to the settings pane -->
+    <string name="wifi_watchdog_network_disabled_detailed">A Wi-Fi network was temporarily disabled due to bad connectivity.</string>
+
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
 
+    <!-- Wi-Fi p2p dialog title-->
+    <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
+    <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct operation. This will turn off Wi-Fi client/hotspot operation.</string>
+    <string name="wifi_p2p_failed_message">Failed to start Wi-Fi Direct</string>
+    <string name="wifi_p2p_pbc_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Click OK to accept. </string>
+    <string name="wifi_p2p_pin_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Enter pin to proceed. </string>
+    <string name="wifi_p2p_pin_display_message">WPS pin <xliff:g id="p2p_wps_pin">%1$s</xliff:g> needs to be entered on the peer device <xliff:g id="p2p_client_address">%2$s</xliff:g> for connection setup to proceed </string>
+
     <!-- Name of the dialog that lets the user choose an accented character to insert -->
     <string name="select_character">Insert character</string>
 
@@ -2661,12 +2689,14 @@
     <!-- USB_STORAGE_ERROR dialog  ok button-->
     <string name="dlg_ok">OK</string>
 
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in MTP mode.  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MTP mode.  This is the title -->
     <string name="usb_mtp_notification_title">Connected as a media device</string>
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in PTP mode.  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode.  This is the title -->
     <string name="usb_ptp_notification_title">Connected as a camera</string>
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in mass storage mode (for installer CD image).  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in mass storage mode (for installer CD image).  This is the title -->
     <string name="usb_cd_installer_notification_title">Connected as an installer</string>
+    <!-- USB_PREFERENCES: Notification for when a USB accessory is attached.  This is the title -->
+    <string name="usb_accessory_notification_title">Connected to a USB accessory</string>
     <!-- See USB_PREFERENCES. This is the message. -->
     <string name="usb_notification_message">Touch for other USB options</string>
 
@@ -3004,6 +3034,15 @@
     <!-- 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>
 
+    <!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+    <string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
+    <!-- Notification title when 4G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+    <string name="data_usage_4g_limit_snoozed_title">4G data limit exceeded</string>
+    <!-- Notification title when mobile data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+    <string name="data_usage_mobile_limit_snoozed_title">Mobile data limit exceeded</string>
+    <!-- Notification body when data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+    <string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> over specified limit</string>
+
     <!-- SSL Certificate dialogs -->
     <!-- Title for an SSL Certificate dialog -->
     <string name="ssl_certificate">Security certificate</string>
@@ -3036,9 +3075,15 @@
 
     <!-- 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>
+    <!-- Title default for a dialog showing possible activities in ActivityChooserView [CHAR LIMIT=25] -->
+    <string name="activity_chooser_view_dialog_title_default">Select activity</string>
+
+    <!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] -->
+    <string name="share_action_provider_share_with">Share with...</string>
+
+    <!-- Status Bar icon descriptions -->
+
+    <!-- Description of for the status bar's icon that the device is locked for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="status_bar_device_locked">Device locked.</string>
 
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a5cd6e3..5aa47b7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -423,8 +423,6 @@
         <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item>
         <item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item>
         <item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item>
-        <item name="android:textEditSuggestionsBottomWindowLayout">?android:attr/textEditSuggestionsBottomWindowLayout</item>
-        <item name="android:textEditSuggestionsTopWindowLayout">?android:attr/textEditSuggestionsTopWindowLayout</item>
         <item name="android:textEditSuggestionItemLayout">?android:attr/textEditSuggestionItemLayout</item>
         <item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item>
     </style>
@@ -563,8 +561,8 @@
 
     <style name="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">6dip</item>
-        <item name="android:paddingRight">6dip</item>
+        <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item>
+        <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item>
         <item name="android:gravity">center_vertical</item>
     </style>
     
@@ -625,6 +623,7 @@
         <item name="android:completionThreshold">2</item>
         <item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
         <item name="android:popupBackground">@android:drawable/spinner_dropdown_background</item>
+        <item name="textCursorDrawable">@android:drawable/text_cursor_holo_light</item>
     </style>
 
     <style name="Widget.TabWidget">
@@ -1066,14 +1065,10 @@
     </style>
 
     <!-- Style for the popup window that contains text suggestions. -->
-    <style name="Widget.TextSuggestions">
-        <item name="android:popupAnimationStyle">@android:style/Animation.TextSuggestions</item>
-    </style>
-
-    <!-- Animation effects when showing/hiding the text suggestions popup window. -->
-    <style name="Animation.TextSuggestions">
-        <item name="windowEnterAnimation">@android:anim/fade_in</item>
-        <item name="windowExitAnimation">@android:anim/fade_out</item>
+    <style name="Widget.TextSuggestionsPopupWindow">
+        <item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
+        <item name="android:popupBackground">@android:drawable/text_edit_suggestions_window</item>
+        <item name="android:dropDownWidth">wrap_content</item>
     </style>
 
     <style name="Widget.ActionBar">
@@ -1543,7 +1538,7 @@
     <style name="Widget.Holo.TextSelectHandle" parent="Widget.TextSelectHandle">
     </style>
 
-    <style name="Widget.Holo.TextSuggestions" parent="Widget.TextSuggestions">
+    <style name="Widget.Holo.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow">
     </style>
 
     <style name="Widget.Holo.AbsListView" parent="Widget.AbsListView">
@@ -1672,6 +1667,7 @@
 
     <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Small">
         <item name="android:indeterminateDrawable">@android:drawable/progress_small_holo</item>
+        <item name="android:animationResolution">33</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Small.Title">
@@ -1679,6 +1675,7 @@
 
     <style name="Widget.Holo.ProgressBar.Large" parent="Widget.ProgressBar.Large">
         <item name="android:indeterminateDrawable">@android:drawable/progress_large_holo</item>
+        <item name="android:animationResolution">33</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Inverse">
@@ -1972,6 +1969,9 @@
     <style name="Widget.Holo.Light.TextSelectHandle" parent="Widget.TextSelectHandle">
     </style>
 
+   <style name="Widget.Holo.Light.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow">
+    </style>
+
     <style name="Widget.Holo.Light.AbsListView" parent="Widget.AbsListView">
     </style>
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 90f3602..8d66b93 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -189,9 +189,7 @@
         <item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item>
         <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item>
         <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item>
-        <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestions</item>
-        <item name="textEditSuggestionsBottomWindowLayout">@android:layout/text_edit_suggestions_bottom_window</item>
-        <item name="textEditSuggestionsTopWindowLayout">@android:layout/text_edit_suggestions_top_window</item>
+        <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestionsPopupWindow</item>
         <item name="textEditSuggestionItemLayout">@android:layout/text_edit_suggestion_item</item>
         <item name="textCursorDrawable">@null</item>
 
@@ -955,7 +953,7 @@
         <item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
         <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
-        <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestions</item>
+        <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@android:drawable/text_cursor_holo_dark</item>
 
         <!-- Widget styles -->
@@ -1251,7 +1249,7 @@
         <item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
         <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
-        <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestions</item>
+        <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.Light.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@android:drawable/text_cursor_holo_light</item>
 
         <!-- Widget styles -->
diff --git a/core/tests/coretests/src/android/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java
index 736c759..95b8465 100644
--- a/core/tests/coretests/src/android/content/ObserverNodeTest.java
+++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java
@@ -48,9 +48,9 @@
         int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
 
         // special case
-        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root);
+        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root, 0, 0);
         for(int i = 1; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root, 0, 0);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
@@ -77,7 +77,7 @@
         int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
 
         for(int i = 0; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root, 0, 0);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
diff --git a/core/tests/coretests/src/android/database/MatrixCursorTest.java b/core/tests/coretests/src/android/database/MatrixCursorTest.java
index cddc6c4..cdab638 100644
--- a/core/tests/coretests/src/android/database/MatrixCursorTest.java
+++ b/core/tests/coretests/src/android/database/MatrixCursorTest.java
@@ -16,6 +16,8 @@
 
 package android.database;
 
+import android.test.MoreAsserts;
+
 import junit.framework.TestCase;
 
 import java.util.*;
@@ -33,6 +35,7 @@
         cursor.moveToNext();
         assertTrue(cursor.isNull(0));
         assertNull(cursor.getString(0));
+        assertNull(cursor.getBlob(0));
         assertEquals(0, cursor.getShort(0));
         assertEquals(0, cursor.getInt(0));
         assertEquals(0L, cursor.getLong(0));
@@ -49,7 +52,8 @@
                 .add(2)
                 .add(3)
                 .add(4)
-                .add(5);
+                .add(5)
+                .add(new byte[] {(byte) 0xaa, (byte) 0x55});
 
         cursor.moveToNext();
 
@@ -61,7 +65,8 @@
                 .add("2")
                 .add("3")
                 .add("4")
-                .add("5");
+                .add("5")
+                .add(new byte[] {(byte) 0xaa, (byte) 0x55});
 
         cursor.moveToNext();
         checkValues(cursor);
@@ -73,7 +78,7 @@
     public void testAddArray() {
         MatrixCursor cursor = newMatrixCursor();
 
-        cursor.addRow(new Object[] { "a", 1, 2, 3, 4, 5 });
+        cursor.addRow(new Object[] { "a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55} });
         cursor.moveToNext();
         checkValues(cursor);
 
@@ -86,7 +91,7 @@
     public void testAddIterable() {
         MatrixCursor cursor = newMatrixCursor();
 
-        cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5));
+        cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55}));
         cursor.moveToNext();
         checkValues(cursor);
 
@@ -96,7 +101,8 @@
         } catch (IllegalArgumentException e) { /* expected */ }
 
         try {
-            cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!"));
+            cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5,
+                    new byte[] {(byte) 0xaa, (byte) 0x55}, "Too many!"));
             fail();
         } catch (IllegalArgumentException e) { /* expected */ }
     }
@@ -105,7 +111,7 @@
         MatrixCursor cursor = newMatrixCursor();
 
         cursor.addRow(new NonIterableArrayList<Object>(
-                Arrays.asList("a", 1, 2, 3, 4, 5)));
+                Arrays.asList("a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55})));
         cursor.moveToNext();
         checkValues(cursor);
 
@@ -116,7 +122,8 @@
 
         try {
             cursor.addRow(new NonIterableArrayList<Object>(
-                    Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!")));
+                    Arrays.asList("a", 1, 2, 3, 4, 5,
+                    new byte[] {(byte) 0xaa, (byte) 0x55}, "Too many!")));
             fail();
         } catch (IllegalArgumentException e) { /* expected */ }
     }
@@ -137,7 +144,7 @@
 
     private MatrixCursor newMatrixCursor() {
         return new MatrixCursor(new String[] {
-                "string", "short", "int", "long", "float", "double" });
+                "string", "short", "int", "long", "float", "double", "blob" });
     }
 
     private void checkValues(MatrixCursor cursor) {
@@ -147,6 +154,7 @@
         assertEquals(3, cursor.getLong(3));
         assertEquals(4.0f, cursor.getFloat(4));
         assertEquals(5.0D, cursor.getDouble(5));
+        MoreAsserts.assertEquals(new byte[] {(byte) 0xaa, (byte) 0x55}, cursor.getBlob(6));
     }
 
 }
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
index b5c2c27..42b7640 100644
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ b/core/tests/coretests/src/android/util/JsonReaderTest.java
@@ -856,4 +856,54 @@
         } catch (IOException expected) {
         }
     }
+
+    public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
+        reader.beginArray();
+        reader.endArray();
+    }
+
+    public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
+        reader.beginArray();
+        try {
+            reader.endArray();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testFailWithPosition() throws IOException {
+        testFailWithPosition("Expected literal value at line 6 column 3",
+                "[\n\n\n\n\n0,}]");
+    }
+
+    public void testFailWithPositionIsOffsetByBom() throws IOException {
+        testFailWithPosition("Expected literal value at line 1 column 4",
+                "\ufeff[0,}]");
+    }
+
+    public void testFailWithPositionGreaterThanBufferSize() throws IOException {
+        String spaces = repeat(' ', 8192);
+        testFailWithPosition("Expected literal value at line 6 column 3",
+                "[\n\n" + spaces + "\n\n\n0,}]");
+    }
+
+    private void testFailWithPosition(String message, String json) throws IOException {
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        reader.nextInt();
+        try {
+            reader.peek();
+            fail();
+        } catch (IOException expected) {
+            assertEquals(message, expected.getMessage());
+        }
+    }
+
+    private String repeat(char c, int count) {
+        char[] array = new char[count];
+        Arrays.fill(array, c);
+        return new String(array);
+    }
 }
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
index b29e2fd..1239a3c 100644
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ b/core/tests/coretests/src/android/util/JsonWriterTest.java
@@ -289,6 +289,15 @@
                 + "\"\\u0019\"]", stringWriter.toString());
     }
 
+    public void testUnicodeLineBreaksEscaped() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value("\u2028 \u2029");
+        jsonWriter.endArray();
+        assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString());
+    }
+
     public void testEmptyArray() throws IOException {
         StringWriter stringWriter = new StringWriter();
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index aad3fe1..9519b9f 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -39,6 +39,10 @@
         t = Patterns.TOP_LEVEL_DOMAIN.matcher("xn--0zwm56d").matches();
         assertTrue("Missed valid TLD", t);
 
+        // One of the new top level internationalized domain.
+        t = Patterns.TOP_LEVEL_DOMAIN.matcher("\uD55C\uAD6D").matches();
+        assertTrue("Missed valid TLD", t);
+
         t = Patterns.TOP_LEVEL_DOMAIN.matcher("mem").matches();
         assertFalse("Matched invalid TLD!", t);
 
@@ -80,6 +84,9 @@
         assertTrue("Valid URL", t);
         t = Patterns.WEB_URL.matcher("\uD604\uAE08\uC601\uC218\uC99D.kr").matches();
         assertTrue("Valid URL", t);
+        // URL with international TLD.
+        t = Patterns.WEB_URL.matcher("\uB3C4\uBA54\uC778.\uD55C\uAD6D").matches();
+        assertTrue("Valid URL", t);
 
         t = Patterns.WEB_URL.matcher("http://brainstormtech.blogs.fortune.cnn.com/2010/03/11/" +
             "top-five-moments-from-eric-schmidt\u2019s-talk-in-abu-dhabi/").matches();
diff --git a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
index bbf1696..4814c61 100644
--- a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
@@ -65,13 +65,13 @@
         assertEquals(0, first.getText().size());
         assertFalse(first.isChecked());
         assertNull(first.getContentDescription());
-        assertEquals(0, first.getItemCount());
+        assertEquals(-1, first.getItemCount());
         assertEquals(AccessibilityEvent.INVALID_POSITION, first.getCurrentItemIndex());
         assertFalse(first.isEnabled());
         assertFalse(first.isPassword());
-        assertEquals(0, first.getFromIndex());
-        assertEquals(0, first.getAddedCount());
-        assertEquals(0, first.getRemovedCount());
+        assertEquals(-1, first.getFromIndex());
+        assertEquals(-1, first.getAddedCount());
+        assertEquals(-1, first.getRemovedCount());
 
         // get another event from the pool (this must be the recycled first)
         AccessibilityEvent second = AccessibilityEvent.obtain();
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index c54e4a1..7dc95db 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,13 +16,13 @@
 
 package android.widget;
 
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.GetChars;
 import android.view.View;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * TextViewTest tests {@link TextView}.
  */
@@ -240,12 +240,12 @@
 
         getActivity().runOnUiThread(new Runnable() {
             public void run() {
-                tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+                ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+                tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
                 assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-                assertEquals(true, tv.isResolvedTextDirection());
 
                 ll.removeView(tv);
-                assertEquals(false, tv.isResolvedTextDirection());
+                assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
             }
         });
     }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 0b8d40f..05bd626 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -159,6 +159,7 @@
     <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
     <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
+    <assign-permission name="android.permission.WAKE_LOCK" uid="media" />
 
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
diff --git a/data/fonts/DroidKufi-Bold.ttf b/data/fonts/DroidKufi-Bold.ttf
new file mode 100644
index 0000000..650919e
--- /dev/null
+++ b/data/fonts/DroidKufi-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidKufi-Regular.ttf b/data/fonts/DroidKufi-Regular.ttf
new file mode 100644
index 0000000..af85975
--- /dev/null
+++ b/data/fonts/DroidKufi-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf
new file mode 100644
index 0000000..6b7d4f0
--- /dev/null
+++ b/data/fonts/DroidNaskh-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf
new file mode 100644
index 0000000..d11e1ae
--- /dev/null
+++ b/data/fonts/DroidNaskh-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansArabic.ttf b/data/fonts/DroidSansArabic.ttf
deleted file mode 100644
index bdefaac..0000000
--- a/data/fonts/DroidSansArabic.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
new file mode 100644
index 0000000..6ac615d
--- /dev/null
+++ b/data/fonts/fallback_fonts.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Fallback Fonts
+
+    This file specifies the fonts, and the priority order, that will be searched for any
+    glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml.
+    Each entry consists of a family tag and a list of files (file names) which support that
+    family. The fonts for each family are listed in the order of the styles that they
+    handle (the order is: regular, bold, italic, and bold-italic). The order in which the
+    families are listed in this file represents the order in which these fallback fonts
+    will be searched for glyphs that are not supported by the default system fonts (which are
+    found in /system/etc/system_fonts.xml).
+
+    Note that there is not nameset for fallback fonts, unlike the fonts specified in
+    system_fonts.xml. The ability to support specific names in fallback fonts may be supported
+    in the future. For now, the lack of files entries here is an indicator to the system that
+    these are fallback fonts, instead of default named system fonts.
+
+    There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to
+    provide references to other font families that should be used in addition to the default
+    fallback fonts. That file can also specify the order in which the fallback fonts should be
+    searched, to ensure that a vendor-provided font will be used before another fallback font
+    which happens to handle the same glyph.
+-->
+<familyset>
+    <family>
+        <fileset>
+            <file>DroidNaskh-Regular.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file>DroidSansEthiopic-Regular.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file>DroidSansHebrew-Regular.ttf</file>
+            <file>DroidSansHebrew-Bold.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file>DroidSansThai.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file>DroidSansFallback.ttf</file>
+        </fileset>
+    </family>
+</familyset>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index d222c0b..9a590bb 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -17,7 +17,8 @@
 PRODUCT_COPY_FILES := \
     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/DroidNaskh-Regular.ttf:system/fonts/DroidNaskh-Regular.ttf \
+    frameworks/base/data/fonts/DroidSansEthiopic-Regular.ttf:system/fonts/DroidSansEthiopic-Regular.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 \
@@ -30,4 +31,6 @@
     frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf \
     frameworks/base/data/fonts/AndroidClock.ttf:system/fonts/AndroidClock.ttf \
     frameworks/base/data/fonts/AndroidClock_Highlight.ttf:system/fonts/AndroidClock_Highlight.ttf \
-    frameworks/base/data/fonts/AndroidClock_Solid.ttf:system/fonts/AndroidClock_Solid.ttf
+    frameworks/base/data/fonts/AndroidClock_Solid.ttf:system/fonts/AndroidClock_Solid.ttf \
+    frameworks/base/data/fonts/system_fonts.xml:system/etc/system_fonts.xml \
+    frameworks/base/data/fonts/fallback_fonts.xml:system/etc/fallback_fonts.xml
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
new file mode 100644
index 0000000..8d8d020
--- /dev/null
+++ b/data/fonts/system_fonts.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    System Fonts
+
+    This file lists the font families that will be used by default for all supported glyphs.
+    Each entry consists of a family, various names that are supported by that family, and
+    up to four font files. The font files are listed in the order of the styles which they
+    support: regular, bold, italic and bold-italic. If less than four styles are listed, then
+    the styles with no associated font file will be supported by the other font files listed.
+
+    The first family is also the default font, which handles font request that have not specified
+    specific font names.
+
+    Any glyph that is not handled by the system fonts will cause a search of the fallback fonts.
+    The default fallback fonts are specified in the file /system/etc/fallback_fonts.xml, and there
+    is an optional file which may be supplied by vendors to specify other fallback fonts to use
+    in /vendor/etc/fallback_fonts.xml.
+-->
+<familyset>
+
+    <family>
+        <nameset>
+            <name>sans-serif</name>
+            <name>arial</name>
+            <name>helvetica</name>
+            <name>tahoma</name>
+            <name>verdana</name>
+        </nameset>
+        <fileset>
+            <file>DroidSans.ttf</file>
+            <file>DroidSans-Bold.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>serif</name>
+            <name>times</name>
+            <name>times new roman</name>
+            <name>palatino</name>
+            <name>georgia</name>
+            <name>baskerville</name>
+            <name>goudy</name>
+            <name>fantasy</name>
+            <name>cursive</name>
+            <name>ITC Stone Serif</name>
+        </nameset>
+        <fileset>
+            <file>DroidSerif-Regular.ttf</file>
+            <file>DroidSerif-Bold.ttf</file>
+            <file>DroidSerif-Italic.ttf</file>
+            <file>DroidSerif-BoldItalic.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>monospace</name>
+            <name>courier</name>
+            <name>courier new</name>
+            <name>monaco</name>
+        </nameset>
+        <fileset>
+            <file>DroidSansMono.ttf</file>
+        </fileset>
+    </family>
+
+</familyset>
diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
new file mode 100644
index 0000000..fe51fd27
--- /dev/null
+++ b/data/fonts/vendor_fonts.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Vendor-provided fallback fonts
+
+    This file can be edited to add references to fonts that are not installed or referenced in the
+    default system. The file should then be placed in /vendor/etc/fallback_fonts.xml.
+
+    For example, vendors might want to build configurations for locales that are
+    better served by fonts which either handle glyphs not supported in the default fonts or which
+    handle these glyphs differently than the default fallback fonts.
+    Each entry in this list is a "family", which consists of a list of "files"
+    (the filenames for that family). The files objects are
+    provided in the order of the styles supported for that family: regular, bold, italic, and
+    bold-italic. Only providing one font means that all styles will be rendered with that font.
+    Providing two means that these two fonts will render regular and bold fonts (italics will
+    be mapped to these two fonts).
+
+    There is also an optional "order" attribute on the Family tag. This specifies the index at
+    which that family of fonts should be inserted in the fallback font list, where the
+    default fallback fonts on the system (in /system/etc/fallback_fonts.xml) start at index 0.
+    If no 'order' attribute is supplied, that family will be inserted either at the end of the
+    current fallback list (if no order was supplied for any previous family in this file) or
+    after the previous family (if there was an order specified previously). Typically, vendors
+    may want to supply an order for the first family that puts this set of fonts at the appropriate
+    place in the overall fallback fonts. The order of this list determines which fallback font
+    will be used to support any glyphs that are not handled by the default system fonts.
+
+    The sample configuration below is an example of how one might provide two families of fonts
+    that get inserted at the first and second (0  and 1) position in the overall fallback fonts.
+
+    See /system/etc/system_fonts.xml and /system/etc/fallback_fonts.xml for more information
+    and to understand the order in which the default system fonts are loaded and structured for
+    lookup.
+-->
+
+<!-- Sample fallback font additions to the default fallback list. These fonts will be added
+    to the top two positions of the fallback list, since the first has an order of 0. -->
+<!--
+<familyset>
+    <family order="0">
+        <fileset>
+            <file>MyFont.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file>MyOtherFont.ttf</file>
+        </fileset>
+    </family>
+</familyset>
+-->
\ No newline at end of file
diff --git a/data/sounds/effects/ogg/Dock.ogg b/data/sounds/effects/ogg/Dock.ogg
old mode 100644
new mode 100755
index 626d695..a1c1f2c
--- a/data/sounds/effects/ogg/Dock.ogg
+++ b/data/sounds/effects/ogg/Dock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressDelete.ogg b/data/sounds/effects/ogg/KeypressDelete.ogg
old mode 100644
new mode 100755
index 5e724f4..38c3244
--- a/data/sounds/effects/ogg/KeypressDelete.ogg
+++ b/data/sounds/effects/ogg/KeypressDelete.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressReturn.ogg b/data/sounds/effects/ogg/KeypressReturn.ogg
old mode 100644
new mode 100755
index a1200b2..1bd5b73
--- a/data/sounds/effects/ogg/KeypressReturn.ogg
+++ b/data/sounds/effects/ogg/KeypressReturn.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar.ogg b/data/sounds/effects/ogg/KeypressSpacebar.ogg
old mode 100644
new mode 100755
index 0d0fbf1..3a83594
--- a/data/sounds/effects/ogg/KeypressSpacebar.ogg
+++ b/data/sounds/effects/ogg/KeypressSpacebar.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard.ogg b/data/sounds/effects/ogg/KeypressStandard.ogg
old mode 100644
new mode 100755
index 5878135..4b8d128
--- a/data/sounds/effects/ogg/KeypressStandard.ogg
+++ b/data/sounds/effects/ogg/KeypressStandard.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
old mode 100644
new mode 100755
index a25513f..deeba68
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/LowBattery.ogg b/data/sounds/effects/ogg/LowBattery.ogg
old mode 100644
new mode 100755
index c21218c..370c86c
--- a/data/sounds/effects/ogg/LowBattery.ogg
+++ b/data/sounds/effects/ogg/LowBattery.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Undock.ogg b/data/sounds/effects/ogg/Undock.ogg
old mode 100644
new mode 100755
index dd132c4..91e410e
--- a/data/sounds/effects/ogg/Undock.ogg
+++ b/data/sounds/effects/ogg/Undock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Unlock.ogg b/data/sounds/effects/ogg/Unlock.ogg
old mode 100644
new mode 100755
index 490f98e..ac50288
--- a/data/sounds/effects/ogg/Unlock.ogg
+++ b/data/sounds/effects/ogg/Unlock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/camera_click.ogg b/data/sounds/effects/ogg/camera_click.ogg
old mode 100644
new mode 100755
index eee590f..bfb2a68
--- a/data/sounds/effects/ogg/camera_click.ogg
+++ b/data/sounds/effects/ogg/camera_click.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Argon.ogg b/data/sounds/notifications/ogg/Argon.ogg
old mode 100644
new mode 100755
index f160562..e58b3b6
--- a/data/sounds/notifications/ogg/Argon.ogg
+++ b/data/sounds/notifications/ogg/Argon.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Beryllium.ogg b/data/sounds/notifications/ogg/Beryllium.ogg
old mode 100644
new mode 100755
index 5f7bd3c..2c5b4fe
--- a/data/sounds/notifications/ogg/Beryllium.ogg
+++ b/data/sounds/notifications/ogg/Beryllium.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Cobalt.ogg b/data/sounds/notifications/ogg/Cobalt.ogg
old mode 100644
new mode 100755
index a9adeb8..b6e253a
--- a/data/sounds/notifications/ogg/Cobalt.ogg
+++ b/data/sounds/notifications/ogg/Cobalt.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Fluorine.ogg b/data/sounds/notifications/ogg/Fluorine.ogg
old mode 100644
new mode 100755
index 6340cf3..fd884f5
--- a/data/sounds/notifications/ogg/Fluorine.ogg
+++ b/data/sounds/notifications/ogg/Fluorine.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Gallium.ogg b/data/sounds/notifications/ogg/Gallium.ogg
old mode 100644
new mode 100755
index b0446b2..3c7e1156
--- a/data/sounds/notifications/ogg/Gallium.ogg
+++ b/data/sounds/notifications/ogg/Gallium.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Radon.ogg b/data/sounds/notifications/ogg/Radon.ogg
old mode 100644
new mode 100755
index 1d70c11..550cddd
--- a/data/sounds/notifications/ogg/Radon.ogg
+++ b/data/sounds/notifications/ogg/Radon.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Selenium.ogg b/data/sounds/notifications/ogg/Selenium.ogg
old mode 100644
new mode 100755
index 7624eff..9d60917
--- a/data/sounds/notifications/ogg/Selenium.ogg
+++ b/data/sounds/notifications/ogg/Selenium.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Zirconium.ogg b/data/sounds/notifications/ogg/Zirconium.ogg
old mode 100644
new mode 100755
index 31e40c1..d84b59e
--- a/data/sounds/notifications/ogg/Zirconium.ogg
+++ b/data/sounds/notifications/ogg/Zirconium.ogg
Binary files differ
diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd
index 5c18a83..7a0e17f 100644
--- a/docs/html/guide/appendix/api-levels.jd
+++ b/docs/html/guide/appendix/api-levels.jd
@@ -82,20 +82,71 @@
 Android platform.</p>
 
 <table>
-  <tr><th>Platform Version</th><th>API Level</th></tr>
-  <tr><td>Android 3.1</td><td>12</td></tr>
-  <tr><td>Android 3.0</td><td>11</td></tr>
-  <tr><td>Android 2.3.4</td><td rowspan="2">10</td></tr>
-  <tr><td>Android 2.3.3</td></tr>
-  <tr><td>Android 2.3</td><td>9</td></tr>
-  <tr><td>Android 2.2</td><td>8</td></tr>
-  <tr><td>Android 2.1</td><td>7</td></tr>
-  <tr><td>Android 2.0.1</td><td>6</td></tr>
-  <tr><td>Android 2.0</td><td>5</td></tr>
-  <tr><td>Android 1.6</td><td>4</td></tr>
-  <tr><td>Android 1.5</td><td>3</td></tr>
-  <tr><td>Android 1.1</td><td>2</td></tr>
-  <tr><td>Android 1.0</td><td>1</td></tr>
+  <tr><th>Platform Version</th><th>API Level</th><th>VERSION_CODE</th><th>Notes</th></tr>
+  
+    <tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td>
+    <td><a href="{@docRoot}sdk/api_diff/13/changes.html" title="Diff Report">13</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}</td>
+    <td><!-- <a href="{@docRoot}sdk/android-3.2-highlights.html">Platform Highlights</a>--></td></tr>
+  
+  <tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1.x</a></td>
+    <td><a href="{@docRoot}sdk/api_diff/12/changes.html" title="Diff Report">12</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR1}</td>
+    <td><a href="{@docRoot}sdk/android-3.1-highlights.html">Platform Highlights</a></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0.x</td>
+    <td><a href="{@docRoot}sdk/api_diff/11/changes.html" title="Diff Report">11</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB}</td>
+    <td><a href="{@docRoot}sdk/android-3.0-highlights.html">Platform Highlights</a></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.4<br>Android 2.3.3</td>
+    <td><a href="{@docRoot}sdk/api_diff/10/changes.html" title="Diff Report">10</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1}</td>
+    <td rowspan="2"><a href="{@docRoot}sdk/android-2.3-highlights.html">Platform Highlights</a></td></tr>
+  
+  <tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3.2<br>Android 2.3.1<br>Android 2.3</td>
+    <td><a href="{@docRoot}sdk/api_diff/9/changes.html" title="Diff Report">9</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD}</td>
+    </tr>
+  
+  <tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2.x</td>
+    <td ><a href="{@docRoot}sdk/api_diff/8/changes.html" title="Diff Report">8</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#FROYO}</td>
+    <td><a href="{@docRoot}sdk/android-2.2-highlights.html">Platform Highlights</a></td></tr>
+  
+  <tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1.x</td>
+    <td><a href="{@docRoot}sdk/api_diff/7/changes.html" title="Diff Report">7</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#ECLAIR_MR1}</td>
+    <td rowspan="3" ><a href="{@docRoot}sdk/android-2.0-highlights.html">Platform Highlights</a></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-2.0.1.html">Android 2.0.1</td>
+    <td><a href="{@docRoot}sdk/api_diff/6/changes.html" title="Diff Report">6</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#ECLAIR_0_1}</td>
+    </tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-2.0.html">Android 2.0</td>
+    <td><a href="{@docRoot}sdk/api_diff/5/changes.html" title="Diff Report">5</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#ECLAIR}</td>
+    </tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</td>
+    <td><a href="{@docRoot}sdk/api_diff/4/changes.html" title="Diff Report">4</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#DONUT}</td>
+    <td><a href="{@docRoot}sdk/android-1.6-highlights.html">Platform Highlights</a></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</td>
+    <td><a href="{@docRoot}sdk/api_diff/3/changes.html" title="Diff Report">3</a></td>
+    <td>{@link android.os.Build.VERSION_CODES#CUPCAKE}</td>
+    <td><a href="{@docRoot}sdk/android-1.5-highlights.html">Platform Highlights</a></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-1.1.html">Android 1.1</td>
+    <td>2</td>
+    <td>{@link android.os.Build.VERSION_CODES#BASE_1_1}</td><td></td></tr>
+    
+  <tr><td><a href="{@docRoot}sdk/android-1.0.html">Android 1.0</td>
+    <td>1</td>
+    <td>{@link android.os.Build.VERSION_CODES#BASE}</td>
+    <td></td></tr>
 </table>
 
 
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index ef1deba..dc79d95 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -13,10 +13,15 @@
 
 <h2>In this document</h2>
 
-<ol> <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
-<li><a href="#manifest-filters">Filtering based on Manifest File Elements</a></li>
-<li><a href="#other-filters">Other Filters</a></li> 
-<li><a href="#advanced-filters">Advanced Manifest Filters</a></li>
+<ol>
+  <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
+  <li><a href="#manifest-filters">Filtering based on Manifest Elements</a>
+    <ol>
+      <li><a href="#advanced-filters">Advanced manifest filters</a></li>
+    </ol>
+  </li>
+  <li><a href="#other-filters">Other Filters</a></li>
+  <li><a href="#MultiApks">Publishing Multiple APKs with Different Filters</a></li>
 </ol>
 
 <h2>See also</h2>
@@ -39,75 +44,72 @@
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</code></a></li>
 </ol>
 
-<div id="qv-extra"> <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
-<div id="qv-sub-rule"> <img src="{@docRoot}assets/images/icon_market.jpg"
-style="float:left;margin:0;padding:0;"> <p style="color:#669999;">Interested in
-publishing your app on Android Market?</p> <a id="publish-link"
-href="http://market.android.com/publish">Go to Android Market &raquo;</a> </div>
+<div id="qv-extra">
+  <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
+  <div id="qv-sub-rule">
+    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
+    <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2> 
+    <p><a id="publish-link"
+href="http://market.android.com/publish">Go to Android Market</a> to create a publisher
+account and upload your app.</p></div>
 </div>
 
 </div>
 </div>
 
 
-<p>When a user searches or browses in Android Market, the results are filtered based on which
-applications are compatible with the user's device. For example, if an application requires a
-trackball (as specified in the manifest file), then Android Market will not show
-the app on any device that does not have a trackball.</p>
+<p>When a user searches or browses in Android Market on an Android device, the results are filtered
+based on which applications are compatible with that device. For example, if an application
+requires a camera (as specified in the application manifest file), then Android Market will not show
+the app on any device that does not have a camera.</p>
 
-<p>The manifest file and the device's hardware and features are only part of how applications are
-filtered&mdash;filtering might also depend on the country and carrier, the presence or absence of a
-SIM card, and other factors. </p>
+<p>Declarations in the manifest file that are compared to the device's configuration is not the
+only part of how applications are filtered. Filtering might also occur due to the user's country and
+carrier, the presence or absence of a SIM card, and other factors. </p>
 
-<p>Changes to the Android Market filters are independent of changes 
-to the Android platform itself. This document will be updated periodically to reflect 
-any changes that affect the way Android Market filters applications.</p>
+<p>Changes to the Android Market filters are independent of changes to the Android platform itself.
+This document is updated periodically to reflect any changes that affect the way Android Market
+filters applications.</p>
 
 
 <h2 id="how-filters-work">How Filters Work in Android Market</h2>
 
 <p>Android Market uses the filter restrictions described below to determine
 whether to show your application to a user who is browsing or searching for
-applications on an Android-powered device. When determining whether to display your app,
-Market checks the device's hardware and software capabilities, as well as it's
+applications from the Android Market app. When determining whether to display your app,
+Market checks the device's hardware and software configuration, as well as it's
 carrier, location, and other characteristics. It then compares those against the
-restrictions and dependencies expressed by the application itself, in its
+restrictions and dependencies expressed by the application's
 manifest file and publishing details. If the application is
 compatible with the device according to the filter rules, Market displays the
 application to the user. Otherwise, Market hides your application from search
-results and category browsing. </p>
+results and category browsing, even if a user specifically requests 
+the app by clicking a deep link that points directly to the app's ID within Market..</p>
 
-<p>You can use the filters described below to control whether Market shows or
-hides your application to users. You can use any combination of the
-available filters for your app&mdash;for example, you can set a
-<code>minSdkVersion</code> requirement of <code>"4"</code> and set
-<code>smallScreens="false"</code> in the app, then when uploading the app to
-Market you could target European countries (carriers) only. Android Market's
-filters would prevent the application from being visible on any device that did
-not match all three of these requirements. </p>
+<p class="note"><strong>Note:</strong> When users browse the <a
+href="http://market.android.com">Android Market web site</a>, they can see all published
+applications. The Android Market web site compares the application requirements to each of the
+user's registered devices for compatibility, though, and only allows them to install the application
+if it's compatible with their device.</p>
 
- <p>A filtered app is not visible within Market, even if a user specifically requests 
-the app by clicking a deep link that points directly to the app's ID within Market. 
-All filtering restrictions are associated with an application's version and can
-change between versions. For example:</p> 
+<p>You can use any combination of the available filters for your app. For example, you can set a
+<code>minSdkVersion</code> requirement of <code>"4"</code> and set <code>smallScreens="false"</code>
+in the app, then when uploading the app to Market you could target European countries (carriers)
+only. Android Market's filters will thus prevent the application from being available on any device
+that does not match all three of these requirements. </p>
 
-<ul> 
-<li>If you publish a new version of your app with stricter restrictions, the app
-will not be visible to users for whom it is filtered, even if those users were
-able see the previous version.</li>
-<li>If a user has installed your application and you publish an upgrade that
-makes the app invisible to the user, the user will not see that an upgrade is
-available. </li>
-</ul>
-
+<p>All filtering restrictions are associated with an application's version and can
+change between versions. For example, if a user has installed your application and you publish an
+update that makes the app invisible to the user, the user will not see that an update is
+available.</p>
 
 
 <h2 id="manifest-filters">Filtering based on Manifest Elements</h2>
 
 <p>Most Market filters are triggered by elements within an application's
 manifest file, <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>,
-although not everything in the manifest file can trigger filtering.
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a> 
+(although not everything in the manifest file can trigger filtering).
 Table 1 lists the manifest elements that you should use to trigger Android
 Market filtering, and explains how the filtering for each element works.</p>
 
@@ -143,29 +145,22 @@
 attributes, which vary by API Level. Specifically: </p>
 
 <ul>
-<li><p>In API level 3, the <code>&lt;supports-screens&gt;</code> element itself
+<li><p>For applications that set either the <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
+minSdkVersion</a></code> or <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
+targetSdkVersion</a></code> to 3 or lower, the <code>&lt;supports-screens&gt;</code> element itself
 is undefined and no attributes are available. In this case, Market assumes that
 the application is designed for normal-size screens and shows the application to
-devices that have normal or large screens. </p>
+devices that have normal or larger screens. </p>
 
-<p>This behavior is especially significant for applications that set their
-<code><a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">android:
-minSdkVersion</a></code> to 3 or lower, since Market will filter them from
-small-screen devices by default. Such applications can enable support for
-small-screen devices by adding a <code>android:targetSdkVersion="4"</code>
-attribute to the <code>&lt;uses-sdk&gt;</code> element in their manifest
-files. For more information, see <a
-href="{@docRoot}guide/practices/screens_support.html#strategies">Strategies for
-Legacy Applications</a>.</p></li>
-
-<li>In API Level 4, the defaults for all of the attributes is
-<code>"true"</code>. If an application does not declare a
-<code>&lt;supports-screens&gt;</code> element, Market assumes that the
-application is designed for all screen sizes and does not filter it from any
-devices. If the application does not declare one of the attributes, Market uses
-the default value of <code>"true"</code> and does not filter the app for devices
-of corresponding screen size.</li>
+<li>When the either the <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
+minSdkVersion</a></code> or <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
+targetSdkVersion</a></code> is set to 4 or higher, the default for all attributes is
+<code>"true"</code>. In this way, the application is considered to support all screen sizes by
+default.</li>
 </ul>
 
     <p><strong>Example 1</strong><br />
@@ -192,6 +187,7 @@
     Screens</a>.</p>
 </td>
   </tr>
+
   <tr>
     <td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>
       <!-- ##api level 3## --></td>
@@ -207,6 +203,7 @@
 <p>For more details, see  <a
 href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><code>&lt;uses-configuration&gt;</code></a>.</p></td>
   </tr>
+
   <tr>
     <td rowspan="2" valign="top" style="white-space:nowrap;"><code><a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a>
@@ -237,6 +234,7 @@
 below.</p>
 </td>
   </tr>
+
   <tr>
     <td valign="top">OpenGL-ES
     Version<br />
@@ -263,6 +261,7 @@
 <p>For more details, see <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>.</p></td>
   </tr>
+
   <tr>
     <td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code></td>
     <td valign="top">Software Libraries</td>
@@ -299,6 +298,7 @@
 element.</p>
 </td>
   </tr>
+
   <tr>
     <td rowspan="2" valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code></td>
     <td valign="top">Minimum Framework Version (<code>minSdkVersion</code>)</td>
@@ -324,11 +324,55 @@
 </table>
 
 
+
+<h3 id="advanced-filters">Advanced manifest filters</h3>
+
+<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
+filter applications based on the advanced manifest elements in table 2.</p>
+
+<p>These manifest elements and the filtering they trigger are for exceptional use-cases
+only. These are designed for certain types of high-performance games and similar applications that
+require strict controls on application distribution. <strong>Most applications should never use
+these filters</strong>.</p>
+
+<p id="table2" class="table-caption"><strong>Table 2.</strong> Advanced manifest elements for
+Android Market filtering.</p>
+<table>
+  <tr><th>Manifest Element</th><th>Summary</th></tr>
+  <tr>
+    <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+&lt;compatible-screens&gt;}</a></nobr></td>
+    <td>
+      <p>Android Market filters the application if the device screen size and density does not match
+any of the screen configurations (declared by a {@code &lt;screen&gt;} element) in the {@code
+&lt;compatible-screens&gt;} element.</p>
+      <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
+this manifest element</strong>. Using this element can dramatically
+reduce the potential user base for your application, by excluding all combinations of screen size
+and density that you have not listed. You should instead use the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> manifest element (described above in <a href="#table1">table
+1</a>) to enable screen compatibility mode for screen configurations you have not accounted for
+with alternative resources.</p>
+    </td>
+  </tr>
+  <tr>
+    <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+&lt;supports-gl-texture&gt;}</a></nobr></td>
+    <td>
+      <p>Android Market filters the application unless one or more of the GL texture compression
+formats supported by the application are also supported by the device. </p>
+    </td>
+  </tr>
+</table>
+
+
+
 <h2 id="other-filters">Other Filters</h2>
 
 <p>Android Market uses other application characteristics to determine whether to show or hide an application for a particular user on a given device, as described in the table below. </p>
 
-<p id="table2" class="table-caption"><strong>Table 2.</strong> Application and publishing
+<p id="table3" class="table-caption"><strong>Table 3.</strong> Application and publishing
 characteristics that affect filtering on Market.</p>
 <table> <tr>
     <th>Filter Name</th> <th>How It Works</th> </tr>
@@ -365,44 +409,46 @@
 
 
 
+<h2 id="MultiApks">Publishing Multiple APKs with Different Filters</h2>
 
-<h2 id="advanced-filters">Advanced Manifest Filters</h2>
+<p>Some specific Android Market filters allow you to publish multiple APKs for the same
+application in order to provide a different APK to different device configurations. For example, if
+you're creating a video game that uses high-fidelity graphic assets, you might want to create
+two APKs that each support different texture compression formats. This way, you can reduce the
+size of the APK file by including only the textures that are required for each device
+configuration. Depending on each device's support for your texture compression formats, Android
+Market will deliver it the APK that you've declared to support that device.</p>
 
-<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
-filter applications based on the advanced manifest elements in table 3.</p>
+<p>Currently, Android Market allows you to publish multiple APKs for the same application only
+when each APK provides different filters based on the following configurations:</p>
+<ul>
+  <li>OpenGL texture compression formats
+    <p>By using the <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+&lt;supports-gl-texture&gt;}</a> element.</p>
+  </li>
+  <li>Screen size (and, optionally, screen density)
+    <p>By using the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> or <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+&lt;compatible-screens&gt;}</a> element.</p>   
+  </li>
+  <li>API level
+    <p>By using the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code
+&lt;uses-sdk&gt;}</a> element.</p>
+  </li>
+</ul>
 
-<p>These manifest elements and the filtering they trigger are for exceptional use-cases
-only. They are designed for some types of high-performance games and similar applications that
-require strict controls on application distribution. <strong>Most applications should never use
-these filters</strong>.</p>
+<p>All other filters still work the same as usual, but these three are the only filters that can
+distinguish one APK from another within the same application listing on Android Market. For example,
+you <em>cannot</em> publish multiple APKs for the same application if the APKs differ only based on
+whether the device has a camera.</p>
 
-<p id="table3" class="table-caption"><strong>Table 3.</strong> Advanced manifest elements for
-Android Market filtering.</p>
-<table>
-  <tr><th>Manifest Element</th><th>Summary</th></tr>
-  <tr>
-    <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
-&lt;compatible-screens&gt;}</a></nobr></td>
-    <td>
-      <p>Android Market filters the application if the device screen size and density does not match
-any of the screen configurations (declared by a {@code &lt;screen&gt;} element) in the {@code
-&lt;compatible-screens&gt;} element.</p>
-      <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
-this manifest element</strong>. Using this element can dramatically
-reduce the potential user base for your application, by excluding all combinations of screen size
-and density that you have not listed. You should instead use the <a
-href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
-&lt;supports-screens&gt;}</a> manifest element (described above in <a href="#table1">table
-1</a>) to enable screen compatibility mode for screen configurations you have not accounted for
-with alternative resources.</p>
-    </td>
-  </tr>
-  <tr>
-    <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
-&lt;supports-gl-texture&gt;}</a></nobr></td>
-    <td>
-      <p>Android Market filters the application unless one or more of the GL texture compression formats supported by the application are also supported by the device. </p>
-    </td>
-  </tr>
-</table>
+<p class="caution"><strong>Caution:</strong> Publishing multiple APKs for the same application is
+considered an advanced feature and <strong>most application should publish only one
+APK that supports a wide range of device configurations</strong>. Publishing multiple APKs
+requires that you follow specific rules within your filters and that you pay extra attention to the
+version codes for each APK to ensure proper update paths for each configuration.</p>
 
+<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/developing/debugging/index.jd b/docs/html/guide/developing/debugging/index.jd
index 1f1a4ca..0ad1a08 100644
--- a/docs/html/guide/developing/debugging/index.jd
+++ b/docs/html/guide/developing/debugging/index.jd
@@ -1,4 +1,4 @@
-page.title=Debugging 
+page.title=Debugging
 @jd:body
 
 
@@ -10,7 +10,7 @@
         <li><a href="#stack">Debugging Environment</a></li>
 
         <li><a href="#addltools">Additional Debugging Tools</a></li>
-        
+
         <li><a href="#tips">Debugging Tips</a></li>
       </ol>
     </div>
@@ -50,7 +50,7 @@
 
     <dd>The Dalvik VM (Virtual Machine) supports the JDWP protocol to allow debuggers to attach to
     a VM. Each application runs in a VM and exposes a unique port that you can attach a debugger to
-    via DDMS. If you want to debug multiple applications, attaching to each port might become 
+    via DDMS. If you want to debug multiple applications, attaching to each port might become
     tedious, so DDMS provides a port forwarding feature that can forward a specific VM's debugging
     port to port 8700. You can switch freely from application to application by highlighting it in the
     Devices tab of DDMS. DDMS forwards the appropriate port to port 8700. Most modern Java IDEs include a JDWP debugger,
@@ -109,11 +109,11 @@
     that provide useful information such as CPU usage and frame rate. You can also transfer the
     application to a hardware device.</dd>
   </dl>
-  
-  
-  <h2 id="tips">Debugging Tips</h2>  
-  
-<p>While debugging, keep these helpful tips in mind to help you figure out common problems with your 
+
+
+  <h2 id="tips">Debugging Tips</h2>
+
+<p>While debugging, keep these helpful tips in mind to help you figure out common problems with your
 applications:</p>
 
 <dl>
@@ -131,14 +131,14 @@
 </dd>
 
 <dt><strong>Get application and system state information from the emulator</strong></dt>
-<dd>You can access dumpstate information from the <code>adb shell</code> commands. See 
+<dd>You can access dumpstate information from the <code>adb shell</code> commands. See
 <a href="{@docRoot}guide/developing/tools/adb.html#dumpsys">dumpsys and
 dumpstate</a> on the adb topic page.</dd>
 
 
 
 <dt><strong>Get wireless connectivity information</strong></dt>
-<dd>You can get information about wireless connectivity using DDMS. 
+<dd>You can get information about wireless connectivity using DDMS.
 From the <strong>Device</strong> menu, select <strong>Dump
 radio state</strong>.</dd>
 
@@ -165,6 +165,16 @@
 <dt><strong>Use debugging helper classes</strong></dt>
 <dd>Android provides debug helper classes such as {@link android.util.Log
     util.Log} and {@link android.os.Debug} for your convenience. </dd>
+
+<dt><strong>Garbage collection</strong></dt>
+<dd>
+The debugger and garbage collector are currently loosely integrated. The VM guarantees that any
+object the debugger is aware of is not garbage collected until after the debugger disconnects.
+This can result in a buildup of objects over time while the debugger is connected. For example,
+if the debugger sees a running thread, the associated {@link java.lang.Thread} object is not
+garbage collected even after the thread terminates.
+</dd>
+
 </dl>
 
 <p>See the <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting</a> document
@@ -176,10 +186,3 @@
 
 
 
-
-
-
-
-
-
-
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index cb5a0b6..bde170e 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -142,6 +142,9 @@
     <td>Huawei</td>
     <td><code>12d1</code></td></tr>
   <tr>
+    <td>K-Touch</td>
+    <td><code>24e3</code></td></tr>
+  <tr>
     <td>Kyocera</td>
     <td><code>0482</code></td></tr>
   <tr>
diff --git a/docs/html/guide/developing/index.jd b/docs/html/guide/developing/index.jd
index 3d7e353..722c75a 100644
--- a/docs/html/guide/developing/index.jd
+++ b/docs/html/guide/developing/index.jd
@@ -98,20 +98,22 @@
 
     <dt>Jarsigner (or similar signing tool)</dt>
 
-    <dd>To sign your .apk file with a private key generated by keytool. Jarsigner is part of the
+    <dd>To sign your .apk file with a private key generated by Keytool. Jarsigner is part of the
     JDK.</dd>
   </dl>
   
-  <p>If you are using Eclipse and ADT, tools such as <code>adb</code> and the <code>android</code>
-  are called by Eclipse and ADT under the hood or similar functionality is provided within Eclipse.
-  You need to be familiar with <code>adb</code>, however, because certain functions are not accessible from
-  Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and Jarsigner to
+  <p>If you are using Eclipse and ADT, tools such as <code>adb</code> and <code>android</code>
+  are automatically called by Eclipse and ADT so you don't have to manually invoke these tools.
+  You need to be familiar with <code>adb</code>, however, because certain functions are not
+accessible from
+  Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and
+Jarsigner to
   sign your applications, but you can set up Eclipse to do this automatically as well.</p>
   
 <p>For more information on the tools provided with the Android SDK, see the
   <a href="{@docRoot}guide/developing/tools/index.html">Tools</a> section of the documentation.</p>
   
-<h2 id="ThirdParty">Third-Party Development Tools</h2>
+<h2 id="ThirdParty">Other Third-Party Development Tools</h2>
 <p>
 	The tools described in this section are not developed by the Android SDK team. The Android Dev Guide
 	    does not provide documentation for these tools. Please refer to the linked documents in each
diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd
index a109dc8..d32cf66 100644
--- a/docs/html/guide/developing/tools/adb.jd
+++ b/docs/html/guide/developing/tools/adb.jd
@@ -280,7 +280,7 @@
 <td>Run PPP over USB.
 <ul>
 <li><code>&lt;tty&gt;</code> &mdash; the tty for PPP stream. For example <code>dev:/dev/omap_csmi_ttyl</code>. </li>
-<li><code>[parm]... </code> &mdash zero or more PPP/PPPD options, such as <code>defaultroute</code>, <code>local</code>, <code>notty</code>, etc.</li></ul>
+<li><code>[parm]... </code> &mdash; zero or more PPP/PPPD options, such as <code>defaultroute</code>, <code>local</code>, <code>notty</code>, etc.</li></ul>
 
 <p>Note that you should not automatically start a PPP connection. </p></td>
 <td></td>
@@ -503,7 +503,7 @@
 <ul>
     <li><code>V</code> &mdash; Verbose (lowest priority)</li>
 	<li><code>D</code> &mdash; Debug</li>
-	<li><code>I</code> &mdash; Info</li>
+	<li><code>I</code> &mdash; Info (default priority)</li>
 	<li><code>W</code> &mdash; Warning</li>
 	<li><code>E</code> &mdash; Error</li>
 	<li><code>F</code> &mdash; Fatal</li>
@@ -520,7 +520,7 @@
 
 <p>To reduce the log output to a manageable level, you can restrict log output using <em>filter expressions</em>. Filter expressions let you indicate to the system the tags-priority combinations that you are interested in &mdash; the system suppresses other messages for the specified tags. </p>
 
-<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag.  Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. </p>
+<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag.  Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. The default output is to show all log messages with the Info priority (*:I).</p>
 
 <p>Here's an example of a filter expression that suppresses all log messages except those with the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp", with priority "Debug" or above:</p>
 
diff --git a/docs/html/guide/developing/tools/etc1tool.jd b/docs/html/guide/developing/tools/etc1tool.jd
new file mode 100644
index 0000000..a7f76f5
--- /dev/null
+++ b/docs/html/guide/developing/tools/etc1tool.jd
@@ -0,0 +1,68 @@
+page.title=etc1tool
+parent.title=Tools
+parent.link=index.html
+@jd:body
+
+
+ <p><code>etc1tool</code> is a command line utility that lets you encode PNG
+ images to the ETC1 compression standard and decode ETC1 compressed images back to PNG.</p>
+
+  <p>The usage for <code>etc1tool</code> is:</p>
+<pre>etc1tool infile [--help | --encode | --encodeNoHeader | --decode] [--showDifference
+diff-file] [-o outfile]</pre>
+
+  <table>
+    <tr>
+      <th>Option</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td><code>infile</code></td>
+
+      <td>The input file to compress</td>
+    </tr>
+
+    <tr>
+      <td><code>--help</code></td>
+
+      <td>Print usage information</td>
+    </tr>
+
+    <tr>
+      <td><code>--encode</code></td>
+
+      <td>Create an ETC1 file from a PNG file.
+      This is the default mode for the tool if nothing is specified.</td>
+    </tr>
+
+    <tr>
+      <td><code>--encodeNoHeader</code></td>
+
+      <td>Create a raw ETC1 data file (without a header) from a PNG file.</td>
+    </tr>
+
+    <tr>
+      <td><code>--decode</code></td>
+
+      <td>Create a PNG file from an ETC1 file</td>
+    </tr>
+
+    <tr>
+      <td><code>--showDifference <em>diff-file</em></code></td>
+
+      <td>Write the difference between the original and encoded image to
+      <code><em>diff-file</em></code> (only valid when encoding).</td>
+    </tr>
+
+    <tr>
+      <td><code>-o <em>outfile</em></code></td>
+
+      <td>Specify the name of the output file.
+      If <code><em>outfile</em></code> is not specified, the output file is constructed
+      from the input filename with the appropriate suffix (<code>.pkm</code> or <code>.png</code>).
+      </td>
+    </tr>
+
+  </table>
\ No newline at end of file
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 3ec174e..a647cd3 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -148,7 +148,7 @@
               </a></li>
         </ul>
       </li><!-- end of User Interface -->
-      
+
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/resources/index.html">
                <span class="en">Application Resources</span>
@@ -221,7 +221,7 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></li>
           <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-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>
               <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>
@@ -231,8 +231,8 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></li>
         </ul>
       </li><!-- end of the manifest file -->
-    </ul>  
-      
+    </ul>
+
     <ul>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">
@@ -256,8 +256,7 @@
       <li class="toggle-list">
 	        <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
 	            <span class="en">RenderScript</span>
-	          </a>
-	          <span class="new">new!</span></div>
+	          </a></div>
 	        <ul>
 	          <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
 	                <span class="en">3D Graphics</span>
@@ -266,7 +265,7 @@
 	          <li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html">
 	                <span class="en">Compute</span>
 	              </a>
-	          </li>         
+	          </li>
 	        </ul>
   	  </li>
 
@@ -304,11 +303,9 @@
   <!--<li><a style="color:gray;">Localization</a></li>  -->
       <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
             <span class="en">App Widgets</span></a>
-            <span class="new">updated</span>
           </li>
       <li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
             <span class="en">Bluetooth</span></a>
-            <span class="new">updated</span>
           </li>
       <li><a href="<?cs var:toroot?>guide/topics/nfc/index.html">
             <span class="en">Near Field Communication</span>
@@ -316,7 +313,6 @@
       <li class="toggle-list">
           <div><a href="<?cs var:toroot?>guide/topics/usb/index.html">
             <span class="en">USB</span></a>
-            <span class="new">new!</span>
           </div>
             <ul>
               <li><a href="<?cs var:toroot ?>guide/topics/usb/accessory.html">Accessory</a></li>
@@ -341,7 +337,6 @@
       </li>
       <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
             <span class="en">Device Administration</span></a>
-            <span class="new">updated</span>
       </li>
       <li class="toggle-list">
            <div>
@@ -388,9 +383,6 @@
             <span class="en">In-app Billing</span></a>
         </div>
         <ul>
-          <li><a href="<?cs var:toroot?>guide/market/billing/billing_about.html">
-              <span class="en">About this Release</span></a>
-          </li>
           <li><a href="<?cs var:toroot?>guide/market/billing/billing_overview.html">
               <span class="en">In-app Billing Overview</span></a>
           </li>
@@ -414,6 +406,10 @@
       <li><a href="<?cs var:toroot ?>guide/appendix/market-filters.html">
           <span class="en">Market Filters</span></a>
       </li>
+      <li><a href="<?cs var:toroot ?>guide/market/publishing/multiple-apks.html">
+          <span class="en">Multiple APK Support</span></a>
+          <span class="new">new!</span>
+      </li>
     </ul>
   </li>
 
@@ -576,8 +572,10 @@
           <li><a href="<?cs var:toroot ?>guide/developing/tools/android.html">android</a></li>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/dmtracedump.html">dmtracedump</a></li>
-          <li><a href="<?cs var:toroot ?>guide/developing/tools/draw9patch.html" >Draw 9-Patch</a></li>
+          <li><a href="<?cs var:toroot?>guide/developing/tools/draw9patch.html">Draw
+          9-Patch</a></li>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/etc1tool.html">etc1tool</a></li>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/hprof-conv.html">hprof-conv</a></li>
           <li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>
@@ -673,11 +671,14 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/practices/screens_support.html">
           <span class="en">Supporting Multiple Screens</span>
-        </a></div>
+        </a> <span class="new">updated</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/practices/screens-distribution.html">
             <span class="en">Distributing to Specific Screens</span>
           </a></li>
+          <li><a href="<?cs var:toroot ?>guide/practices/screen-compat-mode.html">
+            <span class="en">Screen Compatibility Mode</span>
+          </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/practices/screens-support-1.5.html">
             <span class="en">Strategies for Android 1.5</span>
           </a></li>
@@ -732,9 +733,16 @@
       <li><a href="<?cs var:toroot ?>guide/practices/design/accessibility.html">
             <span class="en">Designing for Accessibility</span>
           </a></li>
-      <li><a href="<?cs var:toroot ?>guide/practices/design/performance.html">
+      <li class="toggle-list">
+        <div><a href="<?cs var:toroot ?>guide/practices/design/performance.html">
             <span class="en">Designing for Performance</span>
-          </a></li>
+          </a> <span class="new-child">new!</span></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/practices/design/jni.html">
+                <span class="en">JNI Tips</span>
+              </a> <span class="new">new!</span></li>
+        </ul>
+      </li>
       <li><a href="<?cs var:toroot ?>guide/practices/design/responsiveness.html">
             <span class="en">Designing for Responsiveness</span>
           </a></li>
diff --git a/docs/html/guide/market/billing/billing_about.html b/docs/html/guide/market/billing/billing_about.html
new file mode 100644
index 0000000..d8395df
--- /dev/null
+++ b/docs/html/guide/market/billing/billing_about.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<meta http-equiv="refresh"
+content="0;url=http://developer.android.com/guide/market/billing/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/market/billing/index.html">click
+here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/market/billing/billing_about.jd b/docs/html/guide/market/billing/billing_about.jd
deleted file mode 100755
index 5924170..0000000
--- a/docs/html/guide/market/billing/billing_about.jd
+++ /dev/null
@@ -1,30 +0,0 @@
-page.title=About this Release
-parent.title=In-app Billing
-parent.link=index.html
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#billing-about">About this Release</a></li>
-  </ol>
-  <h2>Downloads</h2>
-  <ol>
-    <li><a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">Sample Application</a></li>
-  </ol>
-  <h2>See also</h2>
-  <ol>
-    <li><a href="{@docRoot}guide/market/billing/billing_overview.html">Overview of In-app Billing</a></li>
-    <li><a href="{@docRoot}guide/market/billing/billing_integrate.html">Implementing In-app Billing</a></li>
-    <li><a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a></li>
-    <li><a href="{@docRoot}guide/market/billing/billing_testing.html">Testing In-app Billing</a></li>
-    <li><a href="{@docRoot}guide/market/billing/billing_admin.html">Administering In-app Billing</a></li>
-    <li><a href="{@docRoot}guide/market/billing/billing_reference.html">In-app Billing Reference</a></li>
-  </ol>
-</div>
-</div>
-
-<p>Android Market In-app Billing has reached the final launch milestone and is now available to developers and users. You can now publish applications that use Android Market's in-app billing service, and users can make in-app purchases. To find out how to implement in-app billing in your applications, see the  <a href="{@docRoot}guide/market/billing/index.html">documentation</a> and the <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a>.</p>
-
-
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index 939bbaa..cbb4b29 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -202,6 +202,11 @@
 href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing
 Pricing</a>.</p>
 
+<p class="caution"><strong>Important:</strong> You cannot use the Google Checkout API to issue
+refunds or cancel in-app billing transactions. You must do this manually through your Google
+Checkout merchant account. However, you can use the Google Checkout API to retrieve order
+information.</p>
+
 <h2 id="billing-testing-setup">Setting Up Test Accounts</h2>
 
 <p>The Android Market publisher site lets you set up one or more test accounts. A test account is a
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index 1a1f02a..3eebd59 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -783,11 +783,17 @@
 <code>RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error
 information about the request.</p>
 
-<p class="note"><strong>Note:</strong> As a best practice, you should not send a
-<code>CONFIRM_NOTIFICATIONS</code> request for a purchased item until you have delivered the item to
-the user. This way, if your application crashes or something else prevents your application from
-delivering the product, your application will still receive an <code>IN_APP_NOTIFY</code> broadcast
-intent from Android Market indicating that you need to deliver the product.</p>
+<p>You must send a confirmation when you receive transaction information from Android Market. If you
+don't send a confirmation message, Android Market will continue sending
+<code>IN_APP_NOTIFY</code> messages for the transactions you have not confirmed. Also,
+your application must be able to handle <code>IN_APP_NOTIFY</code> messages that contain multiple
+orders.</p>
+
+<p>In addition, as a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request
+for a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+that you need to deliver the product.</p>
 
 <h4>Restoring transaction information (RESTORE_TRANSACTIONS)</h4>
 
@@ -828,6 +834,10 @@
 signed JSON string (unencrypted). The message includes the signature so you can verify the integrity
 of the signed string.</p>
 
+<p class="note"><strong>Note:</strong> You should use the <code>RESTORE_TRANSACTIONS</code>
+request type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.</p>
+
 <h3>Other service tasks</h3>
 
 <p>You may also want your {@link android.app.Service} to receive intent messages from your {@link
@@ -1061,7 +1071,12 @@
 Design</a>.</p>
 
 <p class="note"><strong>Note</strong>: If you store any purchase information on a device, be sure to
-encrypt the data and use a device-specific encryption key.</p>
+encrypt the data and use a device-specific encryption key. Also, if the purchase type for any of
+your items is "unmanaged," we recommend that you back up the purchase information for these items to
+a remote server or use Android's <a href="{@docRoot}guide/topics/data/backup.html">data
+backup</a> framework to back up the purchase information. Backing up purchase information for
+unmanaged items is important because unmanaged items cannot be restored by using the
+<code>RESTORE_TRANSACTIONS</code> request type.</p>
 
 <h3>Creating a user interface for selecting items</h3>
 
diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/market/billing/billing_overview.jd
index a42b772..8f9fd4c 100755
--- a/docs/html/guide/market/billing/billing_overview.jd
+++ b/docs/html/guide/market/billing/billing_overview.jd
@@ -257,7 +257,10 @@
   <code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and <code>REQUEST_ID</code>. The
   <code>PURCHASE_INTENT</code> key provides a {@link android.app.PendingIntent}, which your
   application uses to start the checkout UI for the given product ID.</li>
-  <li>Your application launches the pending intent, which launches the checkout UI.</li>
+  <li>Your application launches the pending intent, which launches the checkout UI.
+    <p class="note"><strong>Note:</strong> You must launch the pending intent from an activity
+    context and not an application context.</p>
+  </li>
   <li>When the checkout flow finishes (that is, the user successfully purchases the item or cancels
   the purchase), Android Market sends your application a notification message (an
   <code>IN_APP_NOTIFY</code> broadcast intent). The notification message includes a notification ID,
@@ -276,14 +279,21 @@
   <code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key.</li>
 </ol>
 
-<p class="note"><strong>Note:</strong> You must launch the pending intent from an activity context
-and not an application context.</p>
-
 <img src="{@docRoot}images/billing_request_purchase.png" height="231" id="figure2" />
 <p class="img-caption">
   <strong>Figure 2.</strong> Message sequence for a purchase request.
 </p>
 
+<p>Keep in mind, you must send a confirmation when you receive transaction information from Android
+Market (step 8 in figure 2). If you don't send a confirmation message, Android Market will
+continue sending <code>IN_APP_NOTIFY</code> messages for the transactions you have not
+confirmed. As a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request for
+a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+that you need to deliver the product. Also, as a best practice, your application must be able to
+handle <code>IN_APP_NOTIFY</code> messages that contain multiple orders.</p>
+
 <p>The messaging sequence for a restore transaction request is shown in figure 3. Request types for
 each <code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents
 are shown in <em>italic</em>. For clarity, figure 3 does not show the <code>RESPONSE_CODE</code>
@@ -308,6 +318,10 @@
 information that is sent during a purchase request, although you do not need to respond to this
 intent with a <code>CONFIRM_NOTIFICATIONS</code> message.</p>
 
+<p class="note"><strong>Note:</strong> You should use the <code>RESTORE_TRANSACTIONS</code> request
+type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.</p>
+
 <p>The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The
 request type for the <code>sendBillingRequest()</code> method is shown in <strong>bold</strong>.</p>
 
@@ -335,21 +349,32 @@
 <code>GET_PURCHASE_INFORMATION</code> request. Android Market responds with a
 <code>PURCHASE_STATE_CHANGED</code> broadcast intent, which contains the details of the purchase
 state change. Your application then sends a <code>CONFIRM_NOTIFICATIONS</code> message, informing
-Android Market that you've received the purchase state change information.</p>
+Android Market that you have received the purchase state change information.</p>
 
-<p>When Android Market receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given message, it
-usually stops sending <code>IN_APP_NOTIFY</code> intents for that message. However, there are some
-cases where Android Market may send repeated <code>IN_APP_NOTIFY</code> intents for a message even
-though your application has sent a <code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a
-device loses network connectivity while you are sending the <code>CONFIRM_NOTIFICATIONS</code>
-message. In this case, Android Market might not receive your <code>CONFIRM_NOTIFICATIONS</code>
-message and it could send multiple <code>IN_APP_NOTIFY</code> messages until it receives
-acknowledgement that you received the message. Therefore, your application must be able to recognize
-that the subsequent <code>IN_APP_NOTIFY</code> messages are for a previously processed transaction.
-You can do this by checking the <code>orderID</code> that's contained in the JSON string because
-every transaction has a unique <code>orderId</code>.</p>
+<p>In some special cases, you may receive multiple <code>IN_APP_NOTIFY</code> messages even though
+you have confirmed receipt of the purchase information, or you may receive
+<code>IN_APP_NOTIFY</code> messages for a purchase change even though you never initiated the
+purchase. Your application must handle both of these special cases.</p>
 
-<p>There are two cases where your application may also receive <code>IN_APP_NOTIFY</code> broadcast
+<h4>Handling multiple IN_APP_NOTIFY messages</h4>
+
+<p>When Android Market receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given
+<code>PURCHASE_STATE_CHANGED</code> message, it usually stops sending <code>IN_APP_NOTIFY</code>
+intents for that <code>PURCHASE_STATE_CHANGED</code> message. Sometimes, however, Android
+Market may send repeated <code>IN_APP_NOTIFY</code> intents for a
+<code>PURCHASE_STATE_CHANGED</code> message even though your application has sent a
+<code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a device loses network connectivity
+while you are sending the <code>CONFIRM_NOTIFICATIONS</code> message. In this case, Android Market
+might not receive your <code>CONFIRM_NOTIFICATIONS</code> message and it could send multiple
+<code>IN_APP_NOTIFY</code> messages until it receives acknowledgement that you received the
+transaction message. Therefore, your application must be able to recognize that the subsequent
+<code>IN_APP_NOTIFY</code> messages are for a previously processed transaction. You can do this by
+checking the <code>orderID</code> that's contained in the JSON string because every transaction has
+a unique <code>orderId</code>.</p>
+
+<h4>Handling refunds and other unsolicited IN_APP_NOTIFY messages</h4>
+
+<p>There are two cases where your application may receive <code>IN_APP_NOTIFY</code> broadcast
 intents even though your application has not sent a <code>REQUEST_PURCHASE</code> message. Figure 5
 shows the messaging sequence for both of these cases. Request types for each
 <code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents are
@@ -359,11 +384,11 @@
 <div class="figure" style="width:481px">
 <img src="{@docRoot}images/billing_refund.png" alt="" height="189" />
 <p class="img-caption">
-  <strong>Figure 5.</strong> Message sequence for refunds and other unsolicited IN_APP_NOTIFY messages.
-</p>
+  <strong>Figure 5.</strong> Message sequence for refunds and other unsolicited
+IN_APP_NOTIFY messages.</p>
 </div>
 
-<p>In the first case, your application can receive an <code>IN_APP_NOTIFY</code> broadcast intent
+<p>In the first case, your application may receive an <code>IN_APP_NOTIFY</code> broadcast intent
 when a user has your application installed on two (or more) devices and the user makes an in-app
 purchase from one of the devices. In this case, Android Market sends an <code>IN_APP_NOTIFY</code>
 message to the second device, informing the application that there is a purchase state change. Your
@@ -384,6 +409,11 @@
 <code>PURCHASE_STATE_CHANGED</code> broadcast intent. Also, the <code>purchaseState</code> field in
 the JSON string is set to 2.</p>
 
+<p class="caution"><strong>Important:</strong> You cannot use the Google Checkout API to
+issue refunds or cancel in-app billing transactions. You must do this manually through your
+Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order
+information.</p>
+
 <h2 id="billing-security">Security Controls</h2>
 
 <p>To help ensure the integrity of the transaction information that is sent to your application,
diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/market/billing/billing_testing.jd
index 84d25b2..5453047 100755
--- a/docs/html/guide/market/billing/billing_testing.jd
+++ b/docs/html/guide/market/billing/billing_testing.jd
@@ -211,7 +211,8 @@
 users will experience in your application.</p>
 
 <p class="note"><strong>Note</strong>: You do not need to publish your application to do end-to-end
-testing. You only need to upload your draft application to perform end-to-end testing.</p>
+testing. You only need to upload your application as a draft application to perform end-to-end
+testing.</p>
 
 <p>To test your in-app billing implementation with actual in-app purchases, you will need to
 register at least one test account on the Android Market publisher site. You cannot use your
@@ -233,8 +234,11 @@
 <ol>
   <li><strong>Upload your application as a draft application to the publisher site.</strong>
     <p>You do not need to publish your application to perform end-to-end testing with real product
-    IDs. To learn how to upload an application to Android Market, see <a
-    href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
+    IDs; you only need to upload your application as a draft application. However, you must sign
+    your application with your release key before you upload it as a draft application. Also, the
+    version number of the uploaded application must match the version number of the application you
+    load to your device for testing. To learn how to upload an application to Android Market, see
+    <a href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
     applications</a>.</p>
   </li>
   <li><strong>Add items to the application's product list.</strong>
diff --git a/docs/html/guide/market/publishing/multiple-apks.jd b/docs/html/guide/market/publishing/multiple-apks.jd
new file mode 100644
index 0000000..ff70e85
--- /dev/null
+++ b/docs/html/guide/market/publishing/multiple-apks.jd
@@ -0,0 +1,643 @@
+page.title=Multiple APK Support
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>Quickview</h2>
+  <ul>
+    <li>Simultaneously publish different APKs for different
+device configurations</li>
+    <li>Different APKs are distributed to different devices based on filters declared in the
+manifest file</li>
+    <li>You should publish multiple APKs only when it's not possible or reasonable to
+support all desired devices with a single APK</li>
+  </ul>
+
+  <h2>In this document</h2>
+<ol>
+  <li><a href="#Concepts">Publishing Concepts</a>
+    <ol>
+      <li><a href="#Active">Active APKs</a></li>
+      <li><a href="#SimpleAndAdvanced">Simple mode and advanced mode</a></li>
+    </ol>
+  </li>
+  <li><a href="#HowItWorks">How Multiple APKs Work</a>
+    <ol>
+      <li><a href="#SupportedFilters">Supported filters</a></li>
+      <li><a href="#Rules">Rules for multiple APKs</a></li>
+    </ol>
+  </li>
+  <li><a href="#CreatingApks">Creating Multiple APKs</a>
+    <ol>
+      <li><a href="#VersionCodes">Assigning version codes</a></li>
+    </ol>
+  </li>
+  <li><a href="#SingleAPK">Using a Single APK Instead</a>
+    <ol>
+      <li><a href="#TextureOptions">Supporting multiple GL textures</a></li>
+      <li><a href="#ScreenOptions">Supporting multiple screens</a></li>
+      <li><a href="#ApiLevelOptions">Supporting multiple API levels</a></li>
+    </ol>
+  </li>
+</ol>
+
+  <h2>See also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></li>
+  <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+  <li><a href="{@docRoot}sdk/compatibility-library.html">Compatibility
+Package</a></li>
+  <li><a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>Multiple APK support is a feature in Android Market that allows you to publish different APKs
+for your application that are each targeted to different device configurations. Each APK is a
+complete and independent version of your application, but they share the same application listing on
+Android Market and must share the same package name and be signed with the same release key. This
+feature is useful for cases in which your application cannot reach all desired devices with a single
+APK.</p>
+
+<p>Android-powered devices may differ in several ways and it's important
+to the success of your application that you make it available to as many devices as possible.
+Android applications usually run on most compatible devices with a single APK, by supplying
+alternative resources for different configurations (for example, different layouts for different
+screen sizes) and the Android system selects the appropriate resources for the device at runtime. In
+a few cases, however, a single APK is unable to support all device configurations, because
+alternative resources make the APK file too big (greater than 50MB) or other technical challenges
+prevent a single APK from working on all devices.</p>
+
+<p>Although <strong>we encourage you to develop and publish a single APK</strong> that supports as
+many device configurations as possible, doing so is sometimes not possible. To help
+you publish your application for as many devices as possible, Android Market allows you to
+publish multiple APKs under the same application listing. Android Market then supplies each APK to
+the appropriate devices based on configuration support you've declared in the manifest file of each
+APK.</p>
+
+<p>By publishing your application with multiple APKs, you can:</p>
+
+<ul>
+  <li>Support different OpenGL texture compression formats with each APK.</li>
+  <li>Support different screen configurations with each APK.</li>
+  <li>Support different platform versions with each APK.</li>
+</ul>
+
+<p>Currently, these are the only device characteristics that Android Market supports for publishing
+multiple APKs as the same application.</p>
+
+<p class="note"><strong>Note:</strong> You should generally use multiple APKs to support
+different device configurations <strong>only when your APK is too large</strong> (greater than
+50MB). Using a single APK to support different configurations is always the best practice,
+because it makes the path for application updates simple and clear for users (and also makes
+your life simpler by avoiding development and publishing complexity). Read the section below about
+<a href="#SingleAPK">Using a Single APK Instead</a> to
+consider your options before publishing multiple APKs.</p>
+
+
+<h2 id="Concepts">Publishing Concepts</h2>
+
+<p>Before you start publishing multiple APKs on Android Market, you must understand a few
+concepts regarding how the Android Market publisher site works.</p>
+
+<h3 id="Active">Active APKs</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h4>The difference between "Publish" and "Save"</h4>
+  <p>When editing your application, there are two buttons on the top-right side of the page. The
+first button is either <strong>Publish</strong> or <strong>Unpublish</strong> and the second
+button is always <strong>Save</strong> (but its behavior changes).</p>
+  <p>When your application is new or you have unpublished it from Market, the first
+button says <strong>Publish</strong>. Clicking it will publish any APKs listed as
+Active, making them available on Android Market. Also while your application is new
+or unpublished, clicking <strong>Save</strong> will save any changes you've made, such
+as information added to the Product details and APKs you've uploaded, but nothing is made visible on
+Android Market&mdash;this allows you to save your changes and sign out of the publisher site before
+deciding to publish.</p>
+ <p>Once you've published your application, the first button changes to
+<strong>Unpublish</strong>. Clicking it in this state unpublishes your application so that none
+of the APKs are available on Android Market. Also while published, the behavior of the
+<strong>Save</strong> button is different. In this state, clicking <strong>Save</strong> not
+only saves all your changes, but also publishes them to Android Market. For example, if you've
+already published your application and then make changes to your product details or activate new
+APKs, clicking <strong>Save</strong> makes all those changes live on Android Market.</p>
+</div>
+</div>
+
+
+<p>Before you can publish your application (whether publishing one or multiple APKs), you
+must "activate" your APK(s) from the <strong>APK files</strong> tab. When you activate an APK, it
+moves into the list of <em>Active</em> APKs. This list allows you to preview which APK(s)
+you're about to publish.</p>
+
+<p>If there are no errors, any "active" APK will be published to
+Android Market when you click the <strong>Publish</strong> button (if the application is
+unpublished) or when you click the <strong>Save</strong> button (if the application is
+already published).</p>
+
+
+<h3 id="SimpleAndAdvanced">Simple mode and advanced mode</h3>
+
+<p>The Android Market publisher site provides two modes for managing the APKs associated with
+your application: <em>simple mode</em> and <em>advanced mode</em>. You can switch between these by
+clicking the
+link at the top-right corner of the <strong>APK files</strong> tab.</p>
+
+<p>Simple mode is the traditional way to publish an application, using one APK at a time. In
+simple mode, only one APK can be activated at a time. If you upload a new APK to update
+the application, clicking "Activate" on the new APK deactivates the currently
+active APK (you must then click <strong>Save</strong> to publish the new APK).</p>
+
+<p>Advanced mode allows you to activate and publish multiple APKs that are each designed for a
+specific set of device configurations. However, there are several rules based on the manifest
+declarations in each APK that determine whether you're allowed to activate each APK along with
+others. When you activate an APK and it violates one of the rules, you will receive an error or
+warning message. If it's an error, you cannot publish until you resolve the problem; if it's a
+warning, you can publish the activated APKs, but there might be unintended consequences as to
+whether your application is available for different devices. These rules are discussed more
+below.</p>
+
+
+<h2 id="HowItWorks">How Multiple APKs Work</h2>
+
+<p>The concept for using multiple APKs on Android Market is that you have just one entry in
+Android Market for your application, but different devices might download a different APK. This
+means that:</p>
+
+<ul>
+  <li>You maintain only one set of product details (app description, icons, screenshots, etc.).
+This also means you <em>cannot</em> charge a different price for different APKs.</li>
+  <li>All users see only one version of your application on Android Market, so they are not
+confused by different versions you may have published that are "for tablets" or
+"for phones."</li>
+  <li>All user reviews are applied to the same application listing, even though users on different
+devices may have different APKs.</li>
+  <li>If you publish different APKs for different versions of Android (for different API levels),
+then when a user's device receives a system update that qualifies them for a different APK you've
+published, Android Market updates the user's application to the APK designed for the higher version
+of Android. Any system data associated with the application is retained (the same as with normal
+application updates when using a single APK).</li>
+</ul>
+
+<p>To publish multiple APKs for the same application, you must enable <strong>Advanced mode</strong>
+in your application's <strong>APK files</strong> tab (as discussed in the previous section). Once
+in advanced mode, you can upload, activate, then publish multiple APKs for the same application. The
+following sections describe more about how it works.</p>
+
+
+<h3 id="SupportedFilters">Supported filters</h3>
+
+<p>Which devices receive each APK is determined by <a
+href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a> that are specified by
+elements in the manifest file of each APK. However, Android Market allows you to publish multiple
+APKs only when each APK uses filters to support a variation of the following
+device characteristics:</p>
+
+<ul>
+  <li><strong>OpenGL texture compression formats</strong>
+    <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+&lt;supports-gl-texture&gt;}</a> element(s).</p>
+    <p>For example, when developing a game that uses OpenGL ES, you can provide one APK for
+devices that support ATI texture compression and a separate APK for devices
+that support PowerVR compression (among many others).</p>
+  <br/>
+  </li>
+
+  <li><strong>Screen size (and, optionally, screen density)</strong>
+    <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> <em>or</em> <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+&lt;compatible-screens&gt;}</a> element. You should never use both elements and you should use only
+<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> when possible.</p>
+    <p>For example, you can provide one APK that supports small and normal size screens and another
+APK that supports large and xlarge screens.</p>
+
+    <p class="note"><strong>Note:</strong> The Android system provides strong support for
+applications to support all screen configurations with a single APK. You should avoid creating
+multiple APKs to support different screens unless absolutely necessary and instead follow the guide
+to <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a> so that your application is flexible and can adapt to all screen configurations
+with a single APK.</p>
+    <p class="caution"><strong>Caution:</strong> By default, all screen size attributes in the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element are "true" if you do not declare them otherwise. However,
+because the {@code android:xlargeScreens} attribute was added in Android 2.3 (API level
+9), Android Market will assume that it is "false" if your application does not set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to "9" or higher.</p>
+    <p class="caution"><strong>Caution:</strong> You should not combine both <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> and <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+&lt;compatible-screens&gt;}</a> elements in your manifest file. Using both increases the chances
+that you'll introduce an error due to conflicts between them. For help deciding which to use, read
+<a href="{@docRoot}guide/practices/screens-distribution.html">Distributing to Specific Screens</a>.
+If you can't avoid using both, be aware that for any conflicts in agreement between a given size,
+"false" will win.</p>
+  <br/>
+  </li>
+
+  <li><strong>API level</strong>
+    <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element.
+You
+can use both the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> and <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max">{@code android:maxSdkVersion}</a>
+attributes to specify support for different API levels.</p>
+    <p>For example, you can publish your application with one APK that supports API levels 4 - 7
+(Android 1.6 - 2.1)&mdash;using only APIs available since API level 4 or lower&mdash;and another
+APK that supports API levels 8 and above (Android 2.2+)&mdash;using APIs available since API level 8
+or lower.</p>
+    <div class="note">
+      <p><strong>Note:</strong></p>
+      <ul>
+        <li>If you use this characteristic as the factor to distinguish multiple APKs, then the APK
+with a higher <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> value must have a higher <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
+value. This is also true if two APKs overlap their device support based on a different supported
+filter. This ensures that when a device receives a system update, Android Market can offer the user
+an update for your application (because updates are based on an increase in the app version code).
+This requirement is described further in the section below about <a href="#Rules">Rules for
+multiple APKs</a>.</li>
+        <li>You should avoid using <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max">{@code
+android:maxSdkVersion}</a> in general, because as long as you've properly developed your
+application with public APIs, it is always compatible with future versions of Android. If you want
+to publish a different APK for higher API levels, you still do not need to specify the
+maximum version, because if the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> is {@code "4"} in one APK and {@code "8"} in another, devices that
+support API level 8 or higher will always receive the second APK (because it's version code is
+higher, as per the previous note).</li>
+    </ul>
+  </div>
+  </li>
+</ul>
+
+<p>Other manifest elements that enable <a
+href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a>&mdash;but are not
+listed above&mdash;are still applied for each APK as usual. However, Android Market does not allow
+you to publish multiple APKs based on variations of them. Thus, you cannot publish
+multiple APKs if the above listed filters are the same for each APK (but the APKs differ based on
+other characteristics in the manifest file). For
+example, you cannot provide different APKs that differ purely on the <a
+href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">{@code
+&lt;uses-configuration&gt;}</a> characteristics.</p>
+
+
+
+<h3 id="Rules">Rules for multiple APKs</h3>
+
+<p>Before you enable advanced mode to publish multiple APKs for your application, you need to
+understand the following rules that define how publishing multiple APKs works:</p>
+
+<ul>
+  <li>All APKs you publish for the same application <strong>must have the same package
+name and be signed with the same certificate key</strong>.</li>
+
+  <li>Each APK <strong>must have a different version code</strong>, specified by the
+<a href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a> attribute.</li>
+
+  <li>Each APK <strong>must not exactly match the configuration support of another APK</strong>.
+    <p>That is, each APK must declare slightly different support for at least one of
+the <a href="#MarketFiltersSupported">supported Market filters</a> (listed above).</p>
+    <p>Usually, you will differentiate your APKs based on a specific characteristic (such as the
+supported texture compression formats), and thus, each APK will declare support for different
+devices. However, it's OK to publish multiple APKs that overlap their support slightly. When two
+APKs do overlap (they support some of the same device configurations), a device that falls within
+that overlap range will receive the APK with a higher version code (defined by <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a>).</p></li>
+
+  <li>You cannot activate a new APK that has a version code lower than that of the APK it's
+replacing. For example, say you have an active APK for screen sizes small - normal with version code
+0400, then try to replace it with an APK for the same screen sizes with version code 0300. This
+raises an error, because it means users of the previous APK will not be able to update the
+application.</li>
+
+  <li>An APK that requires a <strong>higher API level</strong> must have a <strong>higher
+version code</strong>.
+    <p>This is true only when either: the APKs differ based <em>only</em> on the
+supported API levels (no other <a href="#SupportedMarketFilters">supported market filters</a>
+distinguish the APKs from each other) <em>or</em> when the APKs do use another supported filter, but
+there is an overlap between the APKs within that filter.</p>
+    <p>This is important because a user's device receives an application update from
+Android Market only if the version code for the APK on Android Market is higher than the version
+code of the APK currently on the device. This ensures that if a device receives a system update that
+then qualifies it to install the APK for higher API levels, the device receives an application
+update because the version code increases.</p>
+<p class="note"><strong>Note:</strong> The size of the version code increase is irrelevant; it
+simply needs to be larger in the version that supports higher API levels.</p>
+    <p>Here are some examples:</p>
+    <ul>
+      <li>If an APK you've uploaded for API levels 4 and above (Android 1.6+) has a version code of
+{@code 0400}, then an APK for API levels 8 and above (Android 2.2+) must be {@code 0401} or
+greater. In this case, the API level is the only supported filter used, so the version codes
+<strong>must increase</strong> in correlation with the API level support for each APK, so that users
+get an update when they receive a system update.</li>
+      <li>If you have one APK that's for API level 4 (and above) <em>and</em> small -
+large screens, and another APK for API level 8 (and above) <em>and</em> large - xlarge screens, then
+the version codes <strong>must increase</strong>. In this case, the API level filter is used to
+distinguish each APK, but so is the screen size. Because the screen sizes overlap (both APKs
+support large screens), the version codes must still be in order. This ensures that a large screen
+device that receives a system update to API level 8 will receive an update for the second
+APK.</li>
+      <li>If you have one APK that's for API level 4 (and above) <em>and</em> small -
+normal screens, and another APK for API level 8 (and above) <em>and</em> large - xlarge
+screens, then the version codes <strong>do not need to increase</strong> in correlation with the API
+levels. Because there is no overlap within the screen size filter, there are no devices that
+could potentially move between these two APKs, so there's no need for the version codes to
+increase from the lower API level to the higher API level.</li>
+    </ul>
+  </li>
+
+</ul>
+
+<p>Failure to abide by the above rules results in an error on the Android Market publisher site
+when you activate your APKs&mdash;you will be unable to publish your application until you
+resolve the error.</p>
+
+<p>There are other conflicts that might occur when you activate your APKs, but which will result
+in warnings rather than errors. Warnings can be caused by the following:</p>
+
+<ul>
+  <li>When you modify an APK to "shrink" the support for a device's characteristics and no other
+APKs support the devices that then fall outside the supported range. For example, if an APK
+currently supports small and normal size screens and you change it to support only small screens,
+then you have shrunk the pool of supported devices and some devices will no longer see your
+application in Android Market. You can resolve this by adding another APK that supports normal size
+screens so that all previously-supported devices are still supported.</li>
+
+  <li>When there are "overlaps" between two or more APKs. For example, if an APK supports screen
+sizes small, normal, and large, while another APK supports sizes large and xlarge, there is an
+overlap, because both APKs support large screens. If you do not resolve this, then devices that
+qualify for both APKs (large screen devices in the example) will receive whichever APK has the
+highest version code.</li>
+</ul>
+
+<p>When such conflicts occur, you will see a warning message, but you can still publish your
+application.</p>
+
+
+
+<h2 id="CreatingApks">Creating Multiple APKs</h2>
+
+<p>Once you decide to publish multiple APKs, you probably need to create separate
+Android projects for each APK you intend to publish so that you can appropriately develop them
+separately. You can do this by simply duplicating your existing project and give it a new name.
+(Alternatively, you might use a build system that can output different resources&mdash;such
+as textures&mdash;based on the build configuration.)</p>
+
+<p class="note"><strong>Tip:</strong> One way to avoid duplicating large portions of your
+application code is to use a <a
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">library project</a>. A library
+project holds shared code and resources, which you can include in your actual application
+projects.</p>
+
+<p>When creating multiple projects for the same application, it's a good practice to identify each
+one with a name that indicates the device restrictions to be placed on the APK, so you can
+easily identify them. For example, "HelloWorld_8" might be a good name for an
+application designed for API level 8 and above.</p>
+
+<p class="note"><strong>Note:</strong> All APKs you publish for the same application
+<strong>must have the same package name and be signed with the same certificate key</strong>. Be
+sure you also understand each of the <a href="#Rules">Rules for multiple APKs</a>.</p>
+
+
+<h3 id="VersionCodes">Assigning version codes</h3>
+
+<p>Each APK for the same application <strong>must have a unique version code</strong>, specified by
+the <a href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a> attribute. You must be careful about assigning version codes when
+publishing multiple APKs, because they must each be different, but in some
+cases, must or should be defined in a specific order, based on the configurations that each APK
+supports.</p>
+
+<h4>Ordering version codes</h4>
+
+<p>An APK that requires a higher API level must usually have a higher version code. For example, if
+you create two APKs to support different API levels, the APK for the higher API levels must have the
+higher version code. This ensures that if a device receives a system update that then qualifies it
+to install the APK for higher API levels, the user receives a notification to update the app. For
+more information about how this requirement applies, see the section above about <a
+href="#Rules">Rules for multiple APKs</a>.</p>
+
+<p>You should also consider how the order of version codes might affect which APK your users
+receive either due to overlap between coverage of different APKs or future changes you might make to
+your APKs.</p>
+
+<p>For example, if you have different APKs based on screen size, such as one for small - normal and
+one for large - xlarge, but foresee a time when you will change the APKs to be one for small and one
+for normal - xlarge, then you should make the version code for the large - xlarge APK be higher.
+That way, a normal size device will receive the appropriate update when you make the change, because
+the version code increases from the existing APK to the new APK that now supports the device. </p>
+
+<p>Also, when creating multiple APKs that differ based on support for different OpenGL texture
+compression formats, be aware that many devices support multiple formats. Because a device
+receives the APK with the highest version code when there is an overlap in coverage between two
+APKs, you should order the version codes among your APKs so that the APK with the
+preferred compression format has the highest version code. For example, you might want to perform
+separate builds for your app using PVRTC, ATITC, and ETC1 compression formats. If you prefer these
+formats in this exact order, then the APK that uses PVRTC should have the highest version code, the
+APK that uses ATITC has a lower version code, and the version with ETC1 has the lowest. Thus, if a
+device supports both PVRTC and ETC1, it receives the APK with PVRTC, because it has the highest
+version code.</p>
+
+
+<h4>Using a version code scheme</h4>
+
+<p>In order to allow different APKs to update their version codes independent of others (for
+example, when you fix a bug in only one APK, so don't need to update all APKs), you should use a
+scheme for your version codes that
+provides sufficient room between each APK so that you can increase the code in one without requiring
+an increase in others. You should also include your actual version name in the code (that is, the
+user visible version assigned to <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code android:versionName}</a>),
+so that it's easy for you to associate the version code and version name.</p>
+
+<p class="note"><strong>Note:</strong> When you increase the version code for an APK, Android
+Market will prompt users of the previous version to update the application. Thus, to avoid
+unnecessary updates, you should not increase the version code for APKs that do not actually
+include changes.</p>
+
+<p>We suggest using a version code with at least 7 digits: integers that represent
+the supported configurations are in the higher order bits, and the version name (from <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code
+android:versionName}</a>) is in the lower order bits. For example, when the application version
+name is 3.1.0, version codes for an API level 4
+APK and an API level 11 APK would be something like 0400310 and 1100310, respectively. The first
+two digits are reserved for the API Level (4 and 11, respectively), the middle two digits are for
+either screen sizes or GL texture formats (not used in these examples), and the last three digits
+are for the application's version name (3.1.0). Figure 1 shows two examples that split based on both
+the platform version (API Level) and screen size.</p>
+
+<img src="{@docRoot}images/market/version-codes.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> A suggested scheme for your version codes,
+using the first two digits for the API Level, the second and third digits for the minimum and
+maximum screen size (1 - 4 indicating each of the four sizes) or to denote the texture formats
+and the last three digits for the app version.</p>
+
+<p>This scheme for version codes is just a suggestion for how you should establish a
+pattern that is scalable as your application evolves. In particular, this scheme doesn't
+demonstrate a solution for identifying different texture compression formats. One option might be
+to define your own table that specifies a different integer to each of the different
+compression formats your application supports (for example, 1 might correspond to ETC1 and 2 is
+ATITC, and so on).</p>
+
+<p>You can use any scheme you want, but you should carefully consider how future versions of your
+application will need to increase their version codes and how devices can receive updates when
+either the device configuration changes (for example, due to a system update) or when you modify the
+configuration support for one or several of the APKs.</p>
+
+
+
+
+<h2 id="SingleAPK">Using a Single APK Instead</h2>
+
+<p><strong>Creating multiple APKs for your application is not the normal procedure</strong> for
+publishing an application on Android Market. In most cases, you should be able to publish your
+application to most users with a single APK and we encourage that you do so. When you encounter
+a situation in which using a single APK becomes difficult, you should carefully consider all your
+options before deciding to publish multiple APKs.</p>
+
+<p>First of all, there are a few key benefits to developing a single APK that supports all
+devices:</p>
+
+<ul>
+  <li><strong>Publishing and managing your application is easier.</strong>
+    <p>With only one APK to worry about at any given time, you're less likely to become confused by
+which APK is what. You also don't have to keep track of multiple version codes for each
+APK&mdash;by using only one APK, you can simply increase the version code with each release and
+be done.</p>  </li>
+  <li><strong>You need to manage only a single code base.</strong>
+    <p>Although you can use a <a
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">library project</a>
+to share code between multiple Android projects, it's still likely that you'll reproduce some code
+across each project and this could become difficult to manage, especially when resolving
+bugs.</p></li>
+  <li><strong>Your application can adapt to device configuration changes.</strong>
+    <p>By creating a single APK that contains all the resources for each device configuration, your
+application can adapt to configuration changes that occur at runtime. For example, if the user docks
+or otherwise connects a handset device to a larger screen, there's a chance that this will invoke a
+system configuration change to support the larger screen. If you include all resources for different
+screen configurations in the same APK, then your application will load alternative resources and
+optimize the user experience for the new interface.</p>
+  </li>
+  <li><strong>App restore across devices just works.</strong>
+    <p>If a user has enabled data backup on his or her current device and then buys a new device
+that has a different configuration, then when the user's apps are automatically restored during
+setup, the user receives your application and it runs using the resources optimized for that device.
+For example, on a new tablet, the user receives your application and it runs with your
+tablet-optimized resources. This restore
+process does not work across different APKs, because each APK can potentially have different
+permissions that the user has not agreed to, so Android Market may not restore the application at
+all. (If you use multiple APKs, the user receives either the exact same APK if it's compatible or
+nothing at all and must manually download your application to get the APK designed for the new
+device.)</p></li>
+</ul>
+
+<p>The following sections describe some of the other options you should use to support multiple
+device configurations before deciding to publish multiple APKs.</p>
+
+
+
+<h3 id="TextureOptions">Supporting multiple GL textures</h3>
+
+<p>To support multiple types of GL textures with a single APK, your application should query the GL
+texture formats supported on the device and then use the appropriate resources or download
+them from a web server. For example, in order to keep the size of your APK small, you can query the
+device's support for different GL texture formats when the application starts for the first time and
+then download only the textures you need for that device.</p>
+
+<p>For maximum performance and compatibility, your application should use ETC1 textures wherever it
+doesn't impact the visual quality. However, because ETC1 cannot deal with images that have drastic
+chroma changes, such as line art and (most) text, and doesn't support alpha, it may not the best
+format for all textures.</p>
+
+<p>With a single APK, you should try to use ETC1 textures and uncompressed textures whenever
+reasonable, and consider the use of PVRTC, ATITC, or DXTC as a last resort when ETC1 does not
+suffice.</p>
+
+<p>Here's an example query for supported texture compression formats from inside a
+{@link android.opengl.GLSurfaceView.Renderer GLSurfaceView.Renderer}:</p>
+
+<pre>
+public void onSurfaceChanged(GL10 gl, int w, int h) {
+    String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
+    Log.d("ExampleActivity", extensions);
+}
+</pre>
+
+<p>This returns a string that lists each of the supported compression formats.</p>
+
+
+
+<h3 id="ScreenOptions">Supporting multiple screens</h3>
+
+<p>Unless your APK file exceeds the Android Market size limit of 50MB, supporting multiple screens
+should always be done with a single APK. Since Android 1.6, the Android system manages most of the
+work required for your application to run successfully on a variety of screen sizes and
+densities.</p>
+
+<p>To further optimize your application for different screen sizes and densities, you should provide
+<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
+resources</a> such as bitmap drawables at different resolutions and different layout designs for
+different screen sizes.</p>
+
+<p>For more information about how to support multiple screens with a single APK, read <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
+
+<p>Additionally, you should consider using a support library from the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Package</a> so that you can add <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> to your activity designs
+when running on larger screens such as tablets.</p>
+
+
+
+<h3 id="ApiLevelOptions">Supporting multiple API levels</h3>
+
+<p>If you want to support as many versions of the Android platform as possible, you should use
+only APIs available in the lowest reasonable version. For example, your application may not require
+APIs newer than Android 2.1 (API Level 7), which makes an application available to
+over 95% of Android-powered devices (as indicated by the <a
+href="{@docRoot}resources/dashboard/platform-versions.html">Platform Versions</a> dashboard).</p>
+
+<p>By using a support library from the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Package</a>, you can also use APIs
+from some of the latest versions (such as Android 3.0) while
+still supporting versions as low as Android 1.6. The support library includes APIs for <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a>, <a
+href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a>, and more. Using the fragment
+APIs is particularly valuable so that you can optimize your user interface for large devices such as
+tablets.</p>
+
+<p>Alternatively, if you want to use some APIs that are available only in newer versions of Android
+(which your application can still function without), then you should consider using reflection. By
+using reflection, you can check whether the current device supports certain APIs. If the APIs are
+not available, your application can gracefully disable and hide the feature.</p>
+
+<p>Another way to use new APIs only when running on a version that supports them is to check the
+API level of the current device. That is, you can query the value of {@link
+android.os.Build.VERSION#SDK_INT} and create different code paths depending on the API level
+supported by the device. For example:</p>
+
+<pre>
+if (android.os.Build.VERSION.SDK_INT >= 11) {
+    // Use APIs supported by API level 11 (Android 3.0) and up
+} else {
+    // Do something different to support older versions
+}
+</pre>
+
diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd
index 3e9ddc4..1d0e26e 100644
--- a/docs/html/guide/practices/design/jni.jd
+++ b/docs/html/guide/practices/design/jni.jd
@@ -6,7 +6,6 @@
 
 <h2>In this document</h2>
 <ol>
-  <li><a href="#what">What is JNI?</a></li>
   <li><a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a></li>
   <li><a href="#threads">Threads</a></li>
   <li><a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a></li>
@@ -27,9 +26,6 @@
 </div>
 </div>
 
-<a name="what_is_jni" id="what_is_jni"></a>
-<h2>What is JNI?</h2>
-
 <p>JNI is the Java Native Interface.  It defines a way for code written in the
 Java programming language to interact with native
 code, e.g. functions written in C/C++.  It's VM-neutral, has support for loading code from
@@ -175,8 +171,8 @@
 
 <p>This pattern is commonly used when caching copies of class objects obtained
 from <code>FindClass</code>, e.g.:</p>
-<pre>jclass* localClass = env-&gt;FindClass("MyClass");
-jclass* globalClass = (jclass*) env-&gt;NewGlobalRef(localClass);</pre>
+<pre>jclass localClass = env-&gt;FindClass("MyClass");
+jclass globalClass = reinterpret_cast&lt;jclass&gt;(env-&gt;NewGlobalRef(localClass));</pre>
 
 <p>All JNI methods accept both local and global references as arguments.
 It's possible for references to the same object to have different values;
@@ -215,10 +211,9 @@
 <a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a>
 <h2>UTF-8 and UTF-16 Strings</h2>
 
-<p>The Java programming language uses UTF-16.  For convenience, JNI provides methods that work with "modified UTF-8" encoding
-as well.  (Some VMs use the modified UTF-8 internally to store strings; ours do not.)  The
-modified encoding only supports the 8- and 16-bit forms, and stores ASCII NUL values in a 16-bit encoding.
-The nice thing about it is that you can count on having C-style zero-terminated strings,
+<p>The Java programming language uses UTF-16.  For convenience, JNI provides methods that work with <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> as well.  The
+modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
+The nice thing about this is that you can count on having C-style zero-terminated strings,
 suitable for use with standard libc string functions.  The down side is that you cannot pass
 arbitrary UTF-8 data into the VM and expect it to work correctly.</p>
 
@@ -235,11 +230,11 @@
 are guaranteed valid until Release is called, which means they are not
 released when the native method returns.</p>
 
-<p><strong>Data passed to NewStringUTF must be in "modified" UTF-8 format</strong>.  A
+<p><strong>Data passed to NewStringUTF must be in Modified UTF-8 format</strong>.  A
 common mistake is reading character data from a file or network stream
 and handing it to <code>NewStringUTF</code> without filtering it.
 Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
-characters or convert them to proper "modified" UTF-8 form.  If you don't,
+characters or convert them to proper Modified UTF-8 form.  If you don't,
 the UTF-16 conversion will likely not be what you expect.  The extended
 JNI checks will scan strings and warn you about invalid data, but they
 won't catch everything.</p>
@@ -321,10 +316,10 @@
 to do is copy data in or out.  Consider the following:</p>
 
 <pre>
-    jbyte* data = env->GetByteArrayElements(array, NULL);
+    jbyte* data = env-&gt;GetByteArrayElements(array, NULL);
     if (data != NULL) {
         memcpy(buffer, data, len);
-        env->ReleaseByteArrayElements(array, data, JNI_ABORT);
+        env-&gt;ReleaseByteArrayElements(array, data, JNI_ABORT);
     }</pre>
 
 <p>This grabs the array, copies the first <code>len</code> byte
@@ -335,7 +330,7 @@
 
 <p>We can accomplish the same thing with this:</p>
 <pre>
-    env->GetByteArrayRegion(array, 0, len, buffer);</pre>
+    env-&gt;GetByteArrayRegion(array, 0, len, buffer);</pre>
 
 <p>This has several advantages:</p>
 <ul>
@@ -433,7 +428,7 @@
 <li> Check for calls to inappropriate functions between Critical get/release calls.</li>
 <li> Check that JNIEnv structs aren't being shared between threads.</li>
 <li> Make sure local references aren't used outside their allowed lifespan.</li>
-<li> UTF-8 strings contain only valid "modified UTF-8" data.</li>
+<li> UTF-8 strings contain only valid <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> data.</li>
 </ul>
 
 <p>Accessibility of methods and fields (i.e. public vs. private) is not
@@ -476,20 +471,21 @@
 <li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code></li>
 <li>In <code>JNI_OnLoad</code>, register all of your native methods.  You
 should declare
-the methods "static" so the names don't take up space in the symbol table
+the functions <code>static</code> so the names don't take up space in the symbol table
 on the device.</li>
 </ul>
 
 <p>The <code>JNI_OnLoad</code> function should look something like this if
-written in C:</p>
+written in C++:</p>
 <pre>jint JNI_OnLoad(JavaVM* vm, void* reserved)
 {
     JNIEnv* env;
-    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
+    if (vm-&gt;GetEnv(reinterpret_cast&lt;void**&gt;(&env), JNI_VERSION_1_6) != JNI_OK) {
         return -1;
+    }
 
-    /* get class with (*env)->FindClass */
-    /* register methods with (*env)->RegisterNatives */
+    // Get jclass with env-&gt;FindClass.
+    // Register methods with env-&gt;RegisterNatives.
 
     return JNI_VERSION_1_6;
 }</pre>
@@ -603,7 +599,7 @@
     is commonly caused by:
     <ul>
         <li>For lazy method lookup, failing to declare C++ functions
-        with <code>extern C</code>.  You can use <code>arm-eabi-nm</code>
+        with <code>extern "C"</code>.  You can use <code>arm-eabi-nm</code>
         to see the symbols as they appear in the library; if they look
         mangled (e.g. <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
         rather than <code>Java_Foo_myfunc</code>) then you need to
diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd
new file mode 100644
index 0000000..a792386
--- /dev/null
+++ b/docs/html/guide/practices/screen-compat-mode.jd
@@ -0,0 +1,257 @@
+page.title=Screen Compatibility Mode
+parent.title=Supporting Multiple Screens
+parent.link=screens_support.html
+
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#Disable">Disabling Screen Compatibility Mode</a></li>
+  <li><a href="#Enable">Enabling Screen Compatibility Mode</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+  <li><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a></li>
+</ol>
+</div>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-zoom.png">
+<img src="{@docRoot}images/screens_support/compat-zoom-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
+on an Android 3.2 tablet.</p>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-stretch.png">
+<img src="{@docRoot}images/screens_support/compat-stretch-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 2.</strong> The same application from figure 1, with
+compatibility mode disabled.</p>
+</div>
+
+<p class="caution"><strong>Notice:</strong> If you've developed an application for a version of
+Android lower than Android 3.0, but it does resize properly for larger screens such as tablets, you
+should disable screen compatibility mode in order to maintain the best user experience. To learn how
+to quickly disable the user option, jump to <a href="#Disable">Disabling Screen Compatibility
+Mode</a>.</p>
+
+<p>Screen compatibility mode is an escape hatch for applications that are not properly designed
+to resize for larger screens such as tablets. Since Android 1.6, Android has supported a
+variety of screen sizes and does most of the work to resize application layouts so that they
+properly fit each screen. However, if your application does not successfully follow the guide to
+<a href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a>,
+then it might encounter some rendering issues on larger screens. For applications with this
+problem, screen compatibility mode can make the application a little more usable on larger
+screens.</p>
+
+<p>There are two versions of screen compatibility mode with slightly different behaviors:</p>
+<dl>
+  <dt>Version 1 (Android 1.6 - 3.1)</dt>
+  <dd>The system draws the application's UI in a "postage stamp"
+window. That is, the system draws the application's layout the same as it would on a
+normal size handset (emulating a 320dp x 480dp screen), with a black border that fills
+the remaining area of the screen.
+
+<p>This was introduced with Android 1.6 to handle apps that were designed only for the
+original screen size of 320dp x 480dp. Because there are so few active devices remaining that run
+Android 1.5, almost all applications should be developed against Android 1.6 or greater and
+should not have version 1 of screen compatibility mode enabled for larger screens. This version
+is considered obsolete.</p>
+  <p>To disable this version of screen compatibility mode, you simply need to set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "4"} or higher, or set <a
+href="guide/topics/manifest/supports-screens-element.html#resizeable">{@code
+android:resizeable}</a> to {@code "true"}.</p>
+  </dd>
+  
+  <dt>Version 2 (Android 3.2 and greater)</dt>
+  <dd>The system draws the application's layout the same as
+it would on a normal size handset (approximately emulating a 320dp x 480dp screen), then scales it
+up to fill the screen. This essentially "zooms" in on your layout to make it bigger,
+which will usually cause artifacts such as blurring and pixelation in your UI.
+  <p>This was introduced with Android 3.2 to further
+assist applications on the latest tablet devices when the applications have not yet
+implemented techniques for <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
+  <p>In general, large screen devices running Android 3.2 or higher allow users to enable
+screen compatibility mode when the application does not <strong>explicitly declare that it supports
+large screens</strong> in the manifest file. When this is the case, an icon (with
+outward-pointing arrows) appears next to the clock in the system bar, which allows the user to
+toggle screen compatibility mode on and off (figure 3). An application can also explicitly
+declare that it <em>does not</em> support large screens such that screen compatibility mode
+is always enabled and the user cannot disable it. (How to declare your application's
+support for large screens is discussed in the following sections.)</p></dd>
+</dl>
+
+<img src="{@docRoot}images/screens_support/compat-toggle.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> The pop up menu to toggle screen compatibility
+mode (currently disabled, so normal resizing occurs).</p>
+
+<p>As a developer, you have control over when your application uses screen compatibility mode. The
+following sections describe how you can choose to disable or enable screen compatibility mode for
+larger screens when running Android 3.2 or higher.</p>
+
+
+<h2 id="Disable">Disabling Screen Compatibility Mode</h2>
+
+<p>If you've developed your application primarily for versions of Android lower than 3.0, but
+<strong>your application does resize properly</strong> for larger screens such as tablets,
+<strong>you should disable screen compatibility mode</strong> in order to maintain the best user
+experience. Otherwise, users may enable screen compatibility mode and experience your application in
+a less-than-ideal format.</p>
+
+<p>By default, screen compatibility mode for devices running Android 3.2 and higher is offered to
+users as an optional feature when one of the following is true:</p>
+
+<ul>
+  <li>Your application has set both <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "10"} or lower and <strong>does not explicitly
+declare support</strong> for large screens using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element.</li>
+
+  <li>Your application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher and <strong>explicitly declares that it does
+not support</strong> large screens, using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element.</li>
+</ul>
+
+<p>To completely disable the user option for screen compatibility mode and remove the icon in the
+system bar, you can do one of the following:</p>
+
+<ul>
+  <li><strong>Easiest:</strong>
+    <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#xlarge">{@code
+android:xlargeScreens}</a> attribute to {@code "true"}:</p>
+<pre>
+&lt;supports-screens android:xlargeScreens="true" /&gt;
+</pre>
+  <p>That's it. This declares that your application supports all larger screen sizes, so the
+system will always resize your layout to fit the screen. This works regardless of what values
+you've set in the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a>
+attributes.</p> 
+  </li>
+  
+  <li><strong>Easy but has other effects:</strong>
+    <p>In your manifest's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a>
+element, set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher:</p>
+<pre>
+&lt;uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /&gt;
+</pre>
+  <p>This declares that your application supports Android 3.0 and, thus, is designed to
+work on larger screens such as tablets.</p>
+  <p class="caution"><strong>Caution:</strong> When running on Android 3.0 and greater, this also
+has the effect of enabling the Holographic theme for you UI, adding the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> to your activities, and removing the
+Options Menu button in the system bar.</p>
+  <p>If screen compatibility mode is still enabled after you change this, check your manifest's <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> and be sure that there are no attributes set {@code "false"}. The best
+practice is to always explicitly declare your support for different screen sizes using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element, so you should use this element anyway.</p>
+  <p>For more information about updating your application to target Android 3.0 devices, read <a
+href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android
+3.0</a>.</p>
+  </li>
+<!--
+  <li><strong>Most control</strong> (but you must compile against Android 3.2 or higher):
+    <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the {@code android:compatibleWidthLimitDp}
+attribute to any value <em>higher than</em> {@code "320"}:</p>
+<pre>
+&lt;supports-screens android:compatibleWidthLimitDp="720" /&gt;
+</pre>
+  <p>Using this technique allows you to specify exactly what your application's limit is for
+layout resizing. Normally, only applications that are already built against Android 3.2 (or
+higher) use this attribute, because the primary intention is to specify at what size should screen
+compatibility mode actually be offered to users.</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 to any device if
+your value for {@code android:compatibleWidthLimitDp} is larger than 320.</p>
+  </li>
+  -->
+</ul>
+
+
+
+<h2 id="Enable">Enabling Screen Compatibility Mode</h2>
+
+<p>When your application is targeting Android 3.2 (API level 13) or higher, you can affect
+whether compatibility mode is enabled for certain screens by using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens>}</a> element.</p>
+
+<p class="note"><strong>Note:</strong> Screen compatibility mode is <strong>not</strong> a mode in
+which you should want your application to run&mdash;it causes pixelation and blurring in your UI,
+due to zooming. The proper way to make your application work well on large screens is to follow the
+guide to <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a> and
+provide alternative layouts for different screen sizes.</p>
+
+<p>By default, when you've set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher, screen compatibility mode is
+<strong>not</strong> available to users. If either of these are true and your application does not
+resize properly for larger screens, you can choose to enable screen compatibility mode in one
+of the following ways:</p>
+
+<ul>
+  <li>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> attribute to {@code "320"}:</p>
+<pre>
+&lt;supports-screens android:compatibleWidthLimitDp="320" /&gt;
+</pre>
+  <p>This indicates that the maximum "smallest screen width" for which your application is designed
+is 320dp. This way, any devices with their smallest side being larger than this value will offer
+screen compatibility mode as a user-optional feature.</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 to any device if
+your value for <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> is larger than 320.</p>
+  </li>
+
+  <li>If your application is functionally broken when resized for large screens and you want to
+force users into screen compatibility mode (rather than simply providing the option), you can use
+the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">{@code
+android:largestWidthLimitDp}</a> attribute:
+<pre>
+&lt;supports-screens android:largestWidthLimitDp="320" /&gt;
+</pre>
+  <p>This works the same as <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> except it force-enables
+screen compatibility mode and does not allow users to disable it.</p>
+  </li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd
index 0c5193b..951e364cc 100644
--- a/docs/html/guide/practices/screens-distribution.jd
+++ b/docs/html/guide/practices/screens-distribution.jd
@@ -17,6 +17,7 @@
   <ol>
     <li><a href="#FilteringHansetApps">Filtering a Handset Application from Tablets</a></li>
     <li><a href="#FilteringTabletApps">Filtering a Tablet Application from Handsets</a></li>
+    <li><a href="#MultiApks">Publishing Multiple APKs for Different Screens</a></li>
   </ol>
 
   <h2>See also</h2>
@@ -43,7 +44,7 @@
 should understand the techniques for <a
 href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and implement
 them to the best of your ability. By supporting multiple screens, your application can be made
-available to the greatest number of users with different devices, using a single {@code .apk}.</p>
+available to the greatest number of users with different devices, using a single APK.</p>
 
 
 
@@ -144,9 +145,9 @@
 with <em>larger</em> screens) and set the larger screen size attributes to {@code "false"}, then
 external services such as Android Market <strong>do not</strong> apply filtering. Your application
 will still be available to larger screens, but when it runs, it will not resize to fit the screen.
-Instead, the system will draw it in a "postage stamp" window that's the same relative size as the
-screen size that your application does support (see <a
-href="screens-support-1.5.html#CompatMode">compatibility mode</a> for more information). If you want
+Instead, the system will emulate a handset screen size (about 320dp x 480dp; see <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">Screen Compatibility Mode</a> for more
+information). If you want
 to prevent your application from being downloaded on larger screens, use <a
 href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
 &lt;compatible-screens>}</a>, as discussed in the previous section about <a
@@ -162,3 +163,24 @@
 or you have decided to provide different versions of your application for different sets of screen
 configurations.</p>
 
+
+
+<h2 id="MultiApks">Publishing Multiple APKs for Different Screens</h2>
+
+<p>Although we recommend that you publish one APK for your application, Android Market allows
+you to publish multiple APKs for the same
+application when each APK supports a different set of screen configurations (as declared in
+the manifest file). For example, if you want to publish both a handset version and a tablet
+version of your application, but you're unable to make the same APK work for both screen sizes,
+you can actually publish two APKs for the same application listing. Depending on each device's
+screen configuration, Android Market will deliver it the APK that you've declared to support that
+device's screen.</p>
+
+<p>Beware, however, that publishing multiple APKs for the same application is
+considered an advanced feature and <strong>most applications should publish only one
+APK that can support a wide range of device configurations</strong>. Supporting multiple screen
+sizes, especially, is within reason using a single APK, as long as you follow the guide to
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
+
+<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/practices/screens-support-1.5.jd b/docs/html/guide/practices/screens-support-1.5.jd
index 6fd36bb..9f033b4 100644
--- a/docs/html/guide/practices/screens-support-1.5.jd
+++ b/docs/html/guide/practices/screens-support-1.5.jd
@@ -18,7 +18,6 @@
   <h2>In this document</h2>
   <ol>
     <li><a href="#strategies">Adding Multiple Screens Support</a></li>
-    <li><a href="#CompatMode">Compatibility Mode</a></li>
   </ol>
 
   <h2>See also</h2>
@@ -47,11 +46,13 @@
 default, an application written for Android 1.5 or below that does not set the <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
 android:targetSdkVersion}</a> set to {@code "4"} or higher runs in <a
-href="#CompatMode">compatibility mode</a> when on a device with a screen larger than the
+href="screen-compat-mode">screen compatibility mode</a> when on a device with a screen larger than
+the
 <em>normal</em> screen size (basically, the system displays the application in a small window
 that is roughly the size of the normal screen size).</p>
 
-<p>This document describes how to get your application out of <a href="#CompatMode">compatibility
+<p>This document describes how to get your application out of <a
+href="screen-compat-mode.html">screen compatibility
 mode</a> and instead support multiple screens, but also maintain compatibility with Android 1.5 and
 below.</p>
 
@@ -144,43 +145,3 @@
 href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to add
 complete support for different screen configurations.</p>
 
-
-<h2 id="CompatMode">Compatibility Mode</h2>
-
-<div class="figure" style="width:450px;margin:0">
-<img src="{@docRoot}images/screens_support/compat-mode-on.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
-on an extra large screen.</p>
-</div>
-
-<p>To allow applications to run on larger screens without stretching the UI, Android provides a
-compatibility mode that draws an application's UI in a "postage stamp" window when on larger
-screens. That is, the system displays the application at the baseline size (<em>normal</em>) and
-density (<em>mdpi</em>), with a black border that fills the rest of the screen.</p>
-
-<p>Compatibility mode exists primarily to support application's developed for Android 1.5 (or lower)
-when running on larger screens, because multiple screen support was not added until Android 1.6,
-older applications were not designed to support different screen configurations.</p>
-
-<p>As such, if you've set your <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> to {@code "3"} or lower and have <em>not</em> set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher, then compatibility mode is enabled and
-the system will not scale your application, because your application implicitly declares that it
-only supports the baseline screen configuration (normal screen size and medium density).</p>
-
-<p>To disable compatibility mode, set either <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> or <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher. For more information, see the previous
-section about <a href="#strategies">Adding Multiple Screens Support</a>.</p>
-
-<p>You can also affect whether compatibility mode is enabled by using the <a
-href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
-&lt;supports-screens>}</a> element (you can enable it by setting {@code android:resizeable} or
-specific screen sizes to {@code "false"}). However, you should not explicitly enable compatibility
-mode for your application, but should instead apply the necessary techniques to <a
-href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and allow your
-application to properly fit the screen on all screen sizes.</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 14de152..6dec4b3 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -25,6 +25,13 @@
         <li><a href="#qualifiers">Using configuration qualifiers</a></li>
         <li><a href="#DesigningResources">Designing alternative layouts and drawables</a></li>
       </ol></li>
+    <li><a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> <span
+class="new">new!</span>
+      <ol>
+        <li><a href="#NewQualifiers">Using new size qualifiers</a></li>
+        <li><a href="#ConfigurationExamples">Configuration examples</a></li>
+        <li><a href="#DeclaringScreenSizeSupport">Declaring screen size support</a></li>
+      </ol></li>
     <li><a href="#screen-independence">Best Practices</a></li>
     <li><a href="#DensityConsiderations">Additional Density Considerations</a>
       <ol>
@@ -57,15 +64,15 @@
 applications, the Android system provides a consistent development environment across devices and
 handles most of the work to adjust each application's user interface to the screen on which it is
 displayed. At the same time, the system provides APIs that allow you to control your
-application's UI on specific screen sizes and densities, in order to modify and optimize your UI
+application's UI for specific screen sizes and densities, in order to optimize your UI
 design for different screen configurations. For example, you might want a UI for tablets
-that's different from the design for handsets.</p>
+that's different from the UI for handsets.</p>
 
-<p>Although the system performs sufficient scaling and resizing to make your application work on
+<p>Although the system performs scaling and resizing to make your application work on
 different screens, you should make the effort to optimize your application for different screen
 sizes and densities. In doing so, you maximize the user experience for all devices and your users
 believe that your application was actually designed for <em>their</em> devices&mdash;rather than
-simply stretched to fit their devices.</p>
+simply stretched to fit the screen on their devices.</p>
 
 <p>By following the practices described in this document, you can create an application that
 displays properly and provides an optimized user experience on all supported screen configurations,
@@ -74,7 +81,14 @@
 <p class="note"><strong>Note:</strong> The information in this document assumes that your
 application is designed for Android 1.6 (API Level 4) or higher. If your application supports
 Android 1.5 or lower, please first read <a
-href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.</p>
+href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.
+<br/><br/>
+Also, be aware that <strong>Android 3.2 has introduced new APIs</strong> that allow you to more
+precisely control the layout resources your application uses for different screen sizes. These new
+features are especially important if you're developing an application that's optimized for tablets.
+For details, see the section about <a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for
+Android 3.2</a>.
+</p>
 
 
 
@@ -143,9 +157,16 @@
 <li>A set of four generalized <strong>sizes</strong>: <em>small</em>, <em>normal</em>,
 <em>large</em>,
 and <em>xlarge</em></em>
+<p class="note"><strong>Note:</strong> Beginning with Android 3.2 (API level 13), these size groups
+are deprecated in favor of a new technique for managing screen sizes based on the available screen
+width. If you're developing for Android 3.2 and greater, see <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for more
+information.</p>
+</li>
 <li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
 (medium),
 <em>hdpi</em> (high), and <em>xhdpi</em> (extra high)
+</li>
 </ul>
 
 <p>The generalized sizes and densities are arranged around a
@@ -154,7 +175,7 @@
 G1, which has an HVGA screen (until Android 1.6, this was the only screen configuration that Android
 supported).</p>
 
-<p>Each generalized size or density spans a range of actual screen sizes or density. For example,
+<p>Each generalized size and density spans a range of actual screen sizes and densities. For example,
 two devices that both report a screen size of <em>normal</em> might have actual screen sizes and
 aspect ratios that are slightly different when measured by hand. Similarly, two devices that report
 a screen density of <em>hdpi</em> might have real pixel densities that are slightly different.
@@ -168,11 +189,30 @@
 Illustration of how Android roughly maps actual sizes and densities
 to generalized sizes and densities (figures are not exact).</p>
 
+<p>As you design your UI for different screen sizes, you'll discover that each design requires a
+minimum amount of space. So, each generalized screen size above has an associated minimum
+resolution that's defined by the system. These minimum sizes are in "dp" units&mdash;the same units
+you should use when defining your layouts&mdash;which allows the system to avoid worrying about
+changes in screen density.</p>
+
+<ul>
+  <li><em>xlarge</em> screens are at least 960dp x 720dp</li>
+  <li><em>large</em> screens are at least 640dp x 480dp</li>
+  <li><em>normal</em> screens are at least 470dp x 320dp</li>
+  <li><em>small</em> screens are at least 426dp x 320dp</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> These minimum screen sizes were not as well defined prior to
+Android 3.0, so you may encounter some devices that are mis-classified between normal and large. 
+These are also based on the physical resolution of the screen, so may vary across devices&mdash;for
+example a 1024x720 tablet with a system bar actually has a bit less space available to the
+application due to it being used by the system bar.</p>
+
 <p>To optimize your application's UI for the different screen sizes and densities, you can provide
 <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
 resources</a> for any of the generalized sizes and densities. Typically, you should
 provide alternative layouts for some of the different screen sizes and alternative bitmap images for
-different screen densities. At runtime, the system uses the appropriate size or density resources
+different screen densities. At runtime, the system uses the appropriate resources
 for your application, based on the generalized size or density of the current device screen.</p>
 
 <p>You do not need to provide alternative resources for every combination of screen size and
@@ -221,7 +261,7 @@
 </ul>
 
 <p>In figure 2, the text view and bitmap drawable have dimensions specified in pixels ({@code px}
-units), so the elements are physically larger on a low density screen and smaller on a high density
+units), so the views are physically larger on a low density screen and smaller on a high density
 screen. This is because although the actual screen sizes may be the same, the high density screen
 has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout
 dimensions are specified in density-independent pixels ({@code dp} units). Because the baseline for
@@ -255,6 +295,18 @@
 however, you should also:</p>
 
 <ul>
+  <li><strong>Explicitly declare in the manifest which screen sizes your application
+supports</strong>
+    <p>By declaring which screen sizes your application supports, you can ensure that only
+devices with the screens you support can download your application. Declaring support for
+different screen sizes can also affect how the system draws your application on larger
+screens&mdash;specifically, whether your application runs in <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a>.</p>
+    <p>To declare the screen sizes your application supports, you should include the
+<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element in your manifest file.</p>
+  </li>
+  
   <li><strong>Provide different layouts for different screen sizes</strong>
     <p>By default, Android resizes your application layout to fit the current device screen. In most
 cases, this works fine. In other cases, your UI might not look as good and might need adjustments
@@ -264,6 +316,12 @@
     <p>The configuration qualifiers you can use to provide size-specific resources are
 <code>small</code>, <code>normal</code>, <code>large</code>, and <code>xlarge</code>. For
 example, layouts for an extra large screen should go in {@code layout-xlarge/}.</p>
+    <p>Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you
+should instead use the {@code sw&lt;N&gt;dp} configuration qualifier to define the smallest
+available width required by your layout resources. For example, if your multi-pane tablet layout
+requires at least 600dp of screen width, you should place it in {@code layout-sw600dp/}. Using the
+new techniques for declaring layout resources is discussed further in the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>.</p>
   </li>
   
   <li><strong>Provide different bitmap drawables for different screen densities</strong>
@@ -386,7 +444,7 @@
 </tr>
 
 <tr>
-<td rowspan="5">Density</td>
+<td rowspan="6">Density</td>
 <td><code>ldpi</code></td>
 <td>Resources for low-density (<em>ldpi</em>) screens (~120dpi).</td>
 </tr>
@@ -408,7 +466,15 @@
 <td>Resources for all densities. These are density-independent resources. The system does not
 scale resources tagged with this qualifier, regardless of the current screen's density.</td>
 </tr>
-
+<tr>
+<td><code>tvdpi</code></td>
+<td>Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not
+considered a "primary" density group. It is mostly intended for televisions and most apps shouldn't
+need it&mdash;providing mdpi and hdpi resources is sufficient for most apps and the system will
+scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them
+at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x
+133px for tvdpi.</td>
+</tr>
 <tr>
 <td rowspan="2">Orientation</td>
 <td><code>land</code></td>
@@ -432,6 +498,12 @@
 </tr>
 </table>
 
+<p class="note"><strong>Note:</strong> If you're developing your application for Android 3.2 and
+higher, see the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for information about
+new configuration qualifiers that you should use when declaring layout resources for specific
+screen sizes (instead of using the size qualifiers in table 1).</p></p>
+
 <p>For more information about how these qualifiers roughly correspond to real screen
 sizes and densities, see <a href="#range">Range of Screens Supported</a>, earlier in this
 document.</p>
@@ -457,6 +529,20 @@
 <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
 Providing Alternative Resources</a>.</p>
 
+<p>Be aware that, when the Android system picks which resources to use at runtime, it uses
+certain logic to determing the "best matching" resources. That is, the qualifiers you use don't
+have to exactly match the current screen configuration in all cases in order for the system to
+use them. Specifically, when selecting resources based on the size qualifiers, the system will
+use resources designed for a screen smaller than the current screen if there are no resources
+that better match (for example, a large-size screen will use normal-size screen resources if
+necessary). However, if the only available resources are <em>larger</em> than the current screen,
+the system will not use them and your application will crash if no other resources match the device
+configuration (for example, if all layout resources are tagged with the {@code xlarge} qualifier,
+but the device is a normal-size screen). For more information about how the system selects
+resources, read <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">How Android Finds the
+Best-matching Resource</a>.</p>
+
   <p class="note"><strong>Tip:</strong> If you have some drawable resources that the system
 should never scale (perhaps because you perform some adjustments to the image yourself at
 runtime), you should place them in a directory with the {@code nodpi} configuration qualifier.
@@ -554,6 +640,291 @@
 
 
 
+
+<h2 id="DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</h2>
+
+<p>For the first generation of tablets running Android 3.0, the proper way to declare tablet
+layouts was to put them in a directory with the {@code xlarge} configuration qualifier (for example,
+ {@code res/layout-xlarge/}). In order to accommodate other types of tablets and screen
+sizes&mdash;in particular, 7" tablets&mdash;Android 3.2 introduces a new way to specify resources
+for more discrete screen sizes. The new technique is based on the amount of space your layout needs
+(such as 600dp of width), rather than trying to make your layout fit the generalized size groups
+(such as <em>large</em> or <em>xlarge</em>).</p>
+
+<p>The reason designing for 7" tablets is tricky when using the generalized size groups is
+that a 7" tablet is technically in the same group as a 5" handset (the <em>large</em> group). While
+these two devices are seemingly close to each other in size, the amount of space for an
+application's UI is significantly different, as is the style of user interaction. Thus, a 7" and 5"
+screen should not always use the same layout. To make it possible for you to provide different
+layouts for these two kinds of screens, Android now allows you to specify your layout resources
+based on the width and/or height that's actually available for your application's layout, specified
+in dp units.</p>
+
+<p>For example, after you've designed the layout you want to use for tablet-style devices, you might
+determine that the layout stops working well when the screen is less than 600dp wide. This threshold
+thus becomes the minimum size that you require for your tablet layout. As
+such, you can now specify that these layout resources should be used only when there is at least
+600dp of width available for your application's UI.</p>
+
+<p>You should either pick a width and design to it as your minimum size, or test what is the
+smallest width your layout supports once it's complete.</p>
+
+<p class="note"><strong>Note:</strong> Remember that all the figures used with these new size APIs
+are density-indpendent pixel (dp) values and your layout dimensions should also always be defined
+using dp units, because what you care about is the amount of screen space available after the system
+accounts for screen density (as opposed to using raw pixel resolution). For more information about
+density-indpendent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
+document.</p>
+
+
+<h3 id="NewQualifiers">Using new size qualifiers</h3>
+
+<p>The different resource configurations that you can specify based on the space available for your
+layout are summarized in table 2. These new qualifiers offer you more control over the specific
+screen sizes your application supports, compared to the traditional screen size groups (small,
+normal, large, and xlarge).</p>
+
+<p class="note"><strong>Note:</strong> The sizes that you specify using these qualifiers are
+<strong>not the actual screen sizes</strong>. Rather, the sizes are for the width or height in dp
+units that are <strong>available to your activity's window</strong>. The Android system
+might use some of the screen for system UI (such as the system bar at the bottom of the screen or
+the status bar at the top), so some of the screen might not be available for your layout. Thus, the
+sizes you declare should be specifically about the sizes needed by your activity&mdash;the system
+accounts for any space used by system UI when declaring how much space it provides for your layout.
+Also beware that the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> is considered
+a part of your application's window space, although your layout does not declare it, so it reduces
+the space available for your layout and you must account for it in your design.</p>
+
+<p class="table-caption"><strong>Table 2.</strong> New configuration qualifers for screen size
+(introduced in Android 3.2).</p>
+<table>
+  <tr><th>Screen configuration</th><th>Qualifier values</th><th>Description</th></tr>
+  <tr><td>smallestWidth</td>
+      <td><code>sw&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
+        <code>sw600dp</code><br/>
+        <code>sw720dp</code><br/>
+      </td>
+      <td>
+        <p>The fundamental size of a screen, as indicated by the shortest dimension of the available
+screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
+height and width (you may also think of it as the "smallest possible width" for the screen). You can
+use this qualifier to ensure that, regardless of the screen's current orientation, your
+application's has at least {@code &lt;N&gt;} dps of width available for it UI.</p>
+        <p>For example, if your layout requires that its smallest dimension of screen area be at
+least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
+available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
+height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
+device's smallestWidth does not change when the screen's orientation changes</strong>.</p>
+  <p>The smallestWidth of a device takes into account screen decorations and system UI. For
+example, if the device has some persistent UI elements on the screen that account for space along
+the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual
+screen size, because those are screen pixels not available for your UI.</p>
+  <p>This is an alternative to the generalized screen size qualifiers (small, normal, large, xlarge)
+that allows you to define a discrete number for the effective size available for your UI.
+Using smallestWidth to determine the general screen size is useful because width is
+often the driving factor in designing a layout. A UI will often scroll vertically, but have fairly
+hard constraints on the minimum space it needs horizontally. The available width is also the key
+factor in determining whether to use a one-pane layout for handsets or multi-pane layout for
+tablets. Thus, you likely care most about what the smallest possible width will be on each
+device.</p>
+    </td>
+  </tr>
+    <tr>
+      <td>Available screen width</td>
+      <td><code>w&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
+        <code>w720dp</code><br/>
+        <code>w1024dp</code><br/>
+      </td>
+      <td>
+        <p>Specifies a minimum available width in dp units at which the resources should be
+used&mdash;defined by the <code>&lt;N&gt;</code> value. The system's corresponding value for the
+width changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual width that's available for your UI.</p>
+        <p>This is often useful to determine whether to use a multi-pane layout, because even on a
+tablet device, you often won't want the same multi-pane layout for portrait orientation as you do
+for landscape. Thus, you can use this to specify the minimum width required for the layout, instead
+of using both the screen size and orientation qualifiers together.</p>
+      </td>
+    </tr>
+    <tr>
+      <td>Available screen height</td>
+      <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 resources should be
+used&mdash;defined by the <code>&lt;N&gt;</code> value. The system's corresponding value for
+the height changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual height that's available for your UI.</p>
+        <p>Using this to define the
+height required by your layout is useful in the same way as <code>w&lt;N&gt;dp</code> is for
+defining the required width, instead of using both the screen size and orientation qualifiers.
+However, most apps won't need this qualifier, considering that UIs often scroll vertically and are
+thus more flexible with how much height is available, whereas the width is more rigid.</p>
+      </td>
+    </tr>
+</table>
+
+<p>While using these qualifiers might seem more complicated than using screen size groups, it should
+actually be simpler once you determine the requirements for your UI.  When you design your UI,
+the main thing you probably care about is the actual size at which your application switches between
+a handset-style UI and a tablet-style UI that uses multiple panes. The exact point of this switch
+will depend on your particular design&mdash;maybe you need a 720dp width for your tablet layout,
+maybe 600dp is enough, or 480dp, or some number between these. Using these qualifiers in table 2,
+you are in control of the precise size at which your layout changes.</p>
+
+<p>For more discussion about these size configuration qualifiers, see the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+Providing Resources</a> document.</p>
+
+
+<h3 id="ConfigurationExamples">Configuration examples</h3>
+
+<p>To help you target some of your designs for different types of devices, here are some
+numbers for typical screen widths:</p>
+
+<ul>
+  <li>320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).</li>
+  <li>480dp: a tweener tablet like the Streak (480x800 mdpi).</li>
+  <li>600dp: a 7” tablet (600x1024 mdpi).</li>
+  <li>720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).</li>
+</ul>
+
+<p>Using the size qualifiers from table 2, your application can switch between your different layout
+resources for handsets and tablets using any number you want for width and/or height.  For example,
+if 600dp is the smallest available width supported by your tablet layout, you can provide these two
+sets of layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml           # For handsets
+res/layout-sw600dp/main_activity.xml   # For tablets
+</pre>
+
+<p>In this case, the smallest width of the available screen space must be 600dp in order for the
+tablet layout to be applied.</p>
+
+<p>For other cases in which you want to further customize your UI to differentiate between sizes
+such as 7” and 10” tablets, you can define additional smallest width layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
+res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)
+res/layout-sw720dp/main_activity.xml   # For 10” tablets (720dp wide and bigger)
+</pre>
+
+<p>Notice that the previous two sets of example resources use the "smallest width" qualifer, {@code
+sw&lt;N&gt;dp}, which specifies the smallest of the screen's two sides, regardless of the
+device's current orientation. Thus, using {@code sw&lt;N&gt;dp} is a simple way to specify the
+overall screen size available for your layout by ignoring the screen's orientation.</p>
+
+<p>However, in some cases, what might be
+important for your layout is exactly how much width or height is <em>currently</em> available. For
+example, if you have a two-pane layout with two fragments side by side, you might want to use it
+whenever the screen provides at least 600dp of width, whether the device is in landscape or
+portrait orientation. In this case, your resources might look like this:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml         # For handsets (smaller than 600dp available width)
+res/layout-w600dp/main_activity.xml  # Multi-pane (any screen with 600dp available width or more)
+</pre>
+
+<p>Notice that the second set is using the "available width" qualifier, {@code w&lt;N&gt;dp}. This
+way, one device may actually use both layouts, depending on the orientation of the screen (if
+the available width is at least 600dp in one orientation and less than 600dp in the other
+orientation).</p>
+
+<p>If the available height is a concern for you, then you can do the same using the {@code
+h&lt;N&gt;dp} qualifier. Or, even combine the {@code w&lt;N&gt;dp} and {@code h&lt;N&gt;dp}
+qualifiers if you need to be really specific.</p>
+
+
+<h3 id="DeclaringScreenSizeSupport">Declaring screen size support</h3>
+
+<p>Once you've implemented your layouts for different screen sizes, it's equally important that you
+declare in your manifest file which screens your application supports.</p>
+
+<p>Along with the new configuration qualifiers for screen size, Android 3.2 introduces new
+attributes for the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a>
+manifest element:</p>
+
+<dl>
+  
+  <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">
+{@code android:requiresSmallestWidthDp}</a></dt>
+  <dd>Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of
+the screen space (in {@code dp} units) that must be available to your application UI&mdash;that is,
+the shortest of the available screen's two dimensions. So, in order for a device to be considered
+compatible with your application, the device's smallestWidth must be equal to or greater than this
+value. (Usually, the value you supply for this is the "smallest width" that your layout supports,
+regardless of the screen's current orientation.)
+  <p>For example, if your application is only for tablet-style devices with a 600dp
+smallest available width:</p>
+<pre>
+&lt;manifest ... &gt;
+    &lt;supports-screens android:requiresSmallestWidthDp="600" /&gt;
+    ...
+&lt;/manifest&gt;
+</pre>
+  <p>However, if your application supports all screen sizes supported by Android (as small as
+426dp x 320dp), then you don't need to declare this attribute, because the smallest width your
+application requires is the smallest possible on any device.</p>
+
+  <p class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
+attribute, so it does not affect how your application behaves at runtime. Instead, it is used
+to enable filtering for your application on services such as Android Market. However,
+<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+3.2), so you should continue using the other size attributes if your application does not support
+small screens.</p>
+</dd>
+
+  <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">
+{@code android:compatibleWidthLimitDp}</a></dt>
+  <dd>This attribute allows you to enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> as a
+user-optional feature by specifying the maximum "smallest width" that your application
+supports. If the smallest side of a device's available screen is greater than your value here,
+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 users to toggle screen compatibility
+mode on and off.
+  <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute. We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+
+  <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">
+{@code android:largestWidthLimitDp}</a></dt>
+  <dd>This attribute allows you to force-enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> by specifying
+the maximum "smallest width" that your application supports. If the smallest
+side of a device's available screen is greater than your value here, the application runs in screen
+compatibility mode with no way for the user to disable it.
+  <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute.  We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+</dl>
+
+<p class="caution"><strong>Caution:</strong> When developing for Android 3.2 and higher, you
+should not use the older screen size attributes in combination with the attributes
+listed above. Using both the new attributes and the older size attributes might cause
+unexpected behavior.</p>
+
+<p>For more information about each of these attributes, follow the respective links above.</p>
+
+
+
+
 <h2 id="screen-independence">Best Practices</h2>
 
 <p>The objective of supporting multiple screens is to create an application that can function
@@ -875,7 +1246,7 @@
 the {@code &lt;sdk&gt;/tools/} directory (on all platforms). Figure 6 shows the Android SDK and
 AVD Manager with a selection of AVDs, for testing various screen configurations.</p>
 
-<p>Table 2 shows the various emulator skins that are available in the Android SDK, which you can use
+<p>Table 3 shows the various emulator skins that are available in the Android SDK, which you can use
 to emulate some of the most common screen configurations.</p>
 
 <p>For more information about creating and using AVDs to test your application, see <a
@@ -883,7 +1254,7 @@
 Manager</a>.</p>
 
 
-<p class="table-caption" id="screens-table"><strong>Table 2.</strong> Various screen
+<p class="table-caption" id="screens-table"><strong>Table 3.</strong> Various screen
 configurations available from emulator skins in the Android SDK (indicated in bold) and other
 representative resolutions.</p>
 
diff --git a/docs/html/guide/publishing/preparing.jd b/docs/html/guide/publishing/preparing.jd
index f471961..69aecd4 100644
--- a/docs/html/guide/publishing/preparing.jd
+++ b/docs/html/guide/publishing/preparing.jd
@@ -78,9 +78,6 @@
 and performance. However, we strongly recommend that you test your application
 on an actual target device before publishing it. </li>
 
-<li>If you are targeting the <a href="http://www.t-mobileg1.com/">T-Mobile
-G1</a> device for your application, make sure that your UI handles screen
-orientation changes. </li>
 </ul>
 
 <h3 id="eula">2. Consider adding an End User License Agreement in your 
diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd
index 95d89fa..fa677e6 100644
--- a/docs/html/guide/publishing/publishing.jd
+++ b/docs/html/guide/publishing/publishing.jd
@@ -39,7 +39,7 @@
 <div id="qv-extra">
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
   <div id="qv-sub-rule">
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
+    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
     <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
     <p><a href="http://market.android.com/publish">Go to Android Market</a> to
 create a developer account and upload your application. For more information about the
@@ -155,48 +155,43 @@
 
 <p>To help users discover your published applications, you can use two special Android Market URIs
 that direct users to your application's details page or perform a search for all of your published
-applications in Android Market. You can use these URIs to do the following:</p>
+applications in Android Market. You can use these URIs to create a button in your application or a
+link on a web page that:</p>
 
 <ul>
-  <li>Create a button in your application or a link on a web page that opens one of your
-application's details page in the Android Market application or web site.</li>
-  <li>Create a button in your application or a link on a web page that searches for all your
-published applications in the Android Market application or web site.</li>
+  <li>Opens your application's details page in the Android Market application or web site.</li>
+  <li>Searches for all your published applications in the Android Market application or web
+site.</li>
 </ul>
 
 <p>You can launch the Android Market application or web site in the following ways:</p>
 <ul>
   <li>Initiate an {@link android.content.Intent} from your application that launches the
-Android Market application on the user's device. The intent must use the {@link
-android.content.Intent#ACTION_VIEW} action, and include intent data with the appropriate
-Android Market URI scheme.</li>
-  <li>Provide a hyperlink on a web page that opens the Android Market web site.</li>
+Android Market application on the user's device.</li>
+  <li>Provide a link on a web page that opens the Android Market web site (but will also
+open the Android Market application if clicked from a device).</li>
 </ul>
 
-<p>In both cases, you need to create a URI that indicates either the application you'd like to view
-in Android Market or the search you'd like to perform. The URI is quite similar whether you want
-to open the application or open the web site. The only difference is the URI prefix.</p>
+<p>In both cases, whether you want to initiate the action from your application or from a web
+page, the URIs are quite similar. The only difference is the URI prefix.</p>
 
-<p>To open the Android Market application on the device, the prefix for the intent's data URI
-is:</p>
+<p>To open the Android Market application from your application, the prefix for the intent's data
+URI is:</p>
 
 <p style="margin-left:2em"><code>market://</code></p>
 
-<p>To open the Android Market web site, the prefix for the link URI is:</p>
+<p>To open Android Market from your web site, the prefix for the link URI is:</p>
 
 <p style="margin-left:2em"><code>http://market.android.com/</code></p>
 
-<p>To complete each URI, you must append a string that specifies either the
-application for which you want to view or the search to execute. The following sections
-describe how to create a complete URI for each case.</p>
+<p>The following sections describe how to create a complete URI for each action.</p>
 
-<p class="note"><strong>Note:</strong> If you create a link to open the Android Market web site and
-the user selects it from an Android-powered device, the Android Market application will also resolve
-the link so the user can use the native application instead of the web site. Also, because the
-Android Market application also reads the {@code http://} URIs, you can also use them in an intent,
-but you should usually use the {@code market://} URIs for an intent, so that the native application
-is opened by default. You should use {@code http://} URIs only when creating links from a web
-page.</p>
+<p class="note"><strong>Note:</strong> If you create a link to open Android Market from your web
+site and the user selects it from an Android-powered device, the device's Market application will
+resolve the link so the user can use the Market application instead of opening the web
+site. As such, you should always use {@code http://market.android.com/} URIs when creating a link on
+a web page. When pointing to your apps from within your Android app, use the
+{@code market://} URIs in an intent, so that the Market application always opens.</p>
 
 
 <h3 id="OpeningDetails">Opening an app's details page</h3>
@@ -209,22 +204,23 @@
 
 <p style="margin-left:2em"><code>&lt;URI_prefix&gt;<b>details?id=</b>&lt;package_name&gt;</code></p>
 
-<p>The <code>&lt;package_name&gt;</code> is a placeholder for the target application's fully
-qualified package name, as declared in the <a
+<p>The <code>&lt;package_name&gt;</code> is a placeholder for the target application's
+fully-qualified package name, as declared in the <a
 href="{@docRoot}guide/topics/manifest/manifest-element.html#package">{@code
 package}</a> attribute of the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code
-&lt;manifest&gt;}</a> element in the application's manifest file.</p>
+&lt;manifest&gt;}</a> element.</p>
 
 
-<h4>Opening details in the Android Market application</h4>
+<h4>Opening the app details page from your Android app</h4>
 
-<p>To open the details page in the Android Market application, create an intent with the
-{@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p>
+<p>To open the Android Market details page from your application,
+create an intent with the {@link android.content.Intent#ACTION_VIEW} action and include a data URI
+in this format:</p>
 
 <p style="margin-left:2em"><code>market://details?id=&lt;package_name&gt;</code></p>
 
-<p>For example, here's how you can create an intent and open an application's details page in the
-Android Market application:</p>
+<p>For example, here's how you can create an intent and open an application's details page in
+Android Market:</p>
 
 <pre>
 Intent intent = new Intent(Intent.ACTION_VIEW);
@@ -232,23 +228,30 @@
 startActivity(intent);
 </pre>
 
+<p>This will open the Android Market application on the device to view the {@code
+com.android.example} application.</p>
 
-<h4>Opening details on the Android Market web site</h4>
 
-<p>To open the details page on the Android Market web site, create a link with a URI in this
+<h4>Opening the app details page from a web site</h4>
+
+<p>To open the details page from your web site, create a link with a URI in this
 format:</p>
 
 <p style="margin-left:2em">
   <code>http://market.android.com/details?id=&lt;package_name&gt;</code>
 </p>
 
-<p>For example, here's a link that opens an application's details page on the Android Market web
-site:</p>
+<p>For example, here's a link that opens an application's details page on Android Market:</p>
 
 <pre>
 &lt;a href="http://market.android.com/details?id=com.android.example">App Link&lt;/a>
 </pre>
 
+<p>When clicked from a desktop web browser, this opens the Android Market web site to view the
+{@code com.android.example} application. When clicked from an Android-powered device, users are
+given the option to use either their web browser or the Android Market application to view the
+application.</p>
+
 
 
 <h3 id="PerformingSearch">Performing a search</h3>
@@ -274,9 +277,9 @@
 </ul>
 
 
-<h4>Searching the Android Market application</h4>
+<h4>Searching from your Android app</h4>
 
-<p>To perform a search in the Android Market application, create an intent with the
+<p>To initiate a search on Android Market from your application, create an intent with the
 {@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p>
 
 <p style="margin-left:2em"><code>market://search?q=&lt;query&gt;</code></p>
@@ -292,13 +295,13 @@
 startActivity(intent);
 </pre>
 
-<p>The search result shows all applications published by the publisher and which are compatible with
-the current device.</p>
+<p>This opens the Android Market application to perform the search. The search result shows all
+applications published by the publisher that are compatible with the current device.</p>
 
 
-<h4>Searching the Android Market web site</h4>
+<h4>Searching from a web site</h4>
 
-<p>To perform a search on the Android Market web site, create a link with a URI in this
+<p>To initiate a search on Android Market from your web site, create a link with a URI in this
 format:</p>
 
 <p style="margin-left:2em">
@@ -307,26 +310,31 @@
 
 <p>The query may include the {@code pub:} parameter described above.</p>
 
-<p>For example, here's a link that initiates a search on the Android Market web site, based on the
+<p>For example, here's a link that initiates a search on Android Market, based on the
 publisher name:</p>
 
 <pre>
 &lt;a href="http://market.android.com/search?q=pub:Your Publisher Name">Search Link&lt;/a>
 </pre>
 
-<p>The search result shows all applications published by the publisher.</p>
+<p>When clicked from a desktop web browser, this opens the Android Market web site and performs the
+search. When clicked from an Android-powered device, users are given the option to use either their
+web browser or the Android Market application to perform the search.</p>
 
 
 
 <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>Use the following form to generate an "Available in Android Market" button that you can use on
+your web site. Input either your application's package name or publisher name and the button will
+take users to Android Market to either view your application's information or view a list of
+your published apps. If users click the button while on an Android-powered device, the Android
+Market application will respond to show users your application(s).</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>
+<p>This form offers four versions of the official "Available in Android Market" button at
+recommended sizes. If you want to create a different size, you can download an EPS file for
+the button images from the <a href="http://www.android.com/branding.html">Android Brand
+Guidelines</a>.</p>
 
 <style type="text/css">
   
@@ -548,4 +556,3 @@
 </tr>
 
 </table>
-
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index 31e7c4b..e7a07e0 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -12,28 +12,33 @@
           <ol>
             <li><a href="#how">How property animation works</a></li>
           </ol>
-            </li>
+        </li>
 
-            <li><a href="#value-animator">Animating with ValueAnimator</a></li>
+        <li><a href="#value-animator">Animating with ValueAnimator</a></li>
 
-            <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
+        <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
 
-            <li><a href="#choreography">Choreographing Multiple Animations with
-            AnimatorSet</a></li>            
-            
-            <li><a href="#listeners">Animation Listeners</a></li>
+        <li><a href="#choreography">Choreographing Multiple Animations with
+        AnimatorSet</a></li>
 
-            <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
+        <li><a href="#listeners">Animation Listeners</a></li>
 
-            <li><a href="#interpolators">Using Interpolators</a></li>
+        <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
 
-            <li><a href="#keyframes">Specifying Keyframes</a></li>
-            <li><a href="#layout">Animating Layout Changes to ViewGroups</a></li>
+        <li><a href="#interpolators">Using Interpolators</a></li>
 
-            <li><a href="#views">Animating Views</a></li>
+        <li><a href="#keyframes">Specifying Keyframes</a></li>
 
-            <li><a href="#declaring-xml">Declaring Animations in XML</a></li>
-      </ol>     
+        <li><a href="#layout">Animating Layout Changes to ViewGroups</a></li>
+
+        <li><a href="#views">Animating Views</a>
+          <ol>
+            <li><a href="#view-prop-animator">ViewPropertyAnimator</a></li>
+          </ol>
+        </li>
+
+        <li><a href="#declaring-xml">Declaring Animations in XML</a></li>
+      </ol>
 
       <h2>Key classes</h2>
 
@@ -63,13 +68,13 @@
   You can define an animation to change any object property over time, regardless of whether it
   draws to the screen or not.The property animation system also has a few advantages over the view
   animation system, which makes it more flexible to use.</p>
-  
+
   <p>The view animation system provides the capability to only animate View objects, so if
   you wanted to animate non-View objects, you had to implement your own code to do so. The view
   animation system also was constrained in the fact that it only exposed a few aspects of a View
   object to animate, such as the scaling and rotation of a View but not the background color for
   instance.</p>
-  
+
   <p>Another disadvantage of the view animation system is that it only modified where the
   View was drawn, and not the actual View itself. For instance, if you animated a button to move
   across the screen, the button draws correctly, but the actual location where you can click the
@@ -80,7 +85,7 @@
   <p>The view animation system, however, takes less time to setup and requires less code to write.
   If view animation accomplishes everything that you need to do, or if your existing code already
   works the way you want, there is no need to use the property animation system.</p>
-  
+
     <p class="note"><strong>Tip:</strong> To see how the ADT layout editor allows you to develop and
 preview animations in your layout, watch the <a
 href="http://www.youtube.com/watch?v=Oq05KqjXTvs&feature=player_detailpage#t=1709s">Android
@@ -114,7 +119,7 @@
     default is set to  refresh every 10 ms, but the speed in which your application can refresh frames is
     ultimately dependent on how busy the system is overall and how fast the system can service the underlying timer.</li>
   </ul>
-  
+
 
   <h3 id="how">How the property animation system works</h3>
 
@@ -254,7 +259,7 @@
         </tr>
       </table>
 
-    
+
       <p>Evaluators tell the property animation system how to calculate values for a given
       property. They take the timing data that is provided by an {@link android.animation.Animator}
       class, the animation's start and end value, and calculate the animated values of the property
@@ -299,9 +304,9 @@
           information on how to write a custom evaluator.</td>
         </tr>
       </table>
- 
-      
- 
+
+
+
 
       <p>A time interpolator defines how specific values in an animation are calculated as a
       function of time. For example, you can specify animations to happen linearly across the whole
@@ -397,7 +402,7 @@
   <pre>
 ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
 animation.setDuration(1000);
-animation.start();        
+animation.start();
 </pre>
 
   <p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
@@ -408,7 +413,7 @@
   <pre>
 ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
 animation.setDuration(1000);
-animation.start();        
+animation.start();
 </pre>
 
   <p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
@@ -483,7 +488,7 @@
 
     <li>Depending on what property or object you are animating, you might need to call the {@link
     android.view.View#invalidate invalidate()} method on a View force the screen to redraw itself with the
-    updated animated values. You do this in the 
+    updated animated values. You do this in the
     {@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate onAnimationUpdate()}
     callback. For example, animating the color property of a Drawable object only cause updates to the
     screen when that object redraws itself. All of the property setters on View, such as
@@ -492,7 +497,7 @@
     methods with new values. For more information on listeners, see the section about <a href="#listeners">Animation Listeners</a>.
     </li>
   </ul>
-  
+
   <h2 id="choreography">Choreographing Multiple Animations with AnimatorSet</h2>
 
   <p>In many cases, you want to play an animation that depends on when another animation starts or
@@ -576,12 +581,12 @@
           {@link android.view.View#invalidate invalidate()} on a View to force that area of the
           screen to redraw itself with the new animated values. For example, animating the
           color property of a Drawable object only cause updates to the screen when that object
-          redraws itself. All of the property setters on View, 
+          redraws itself. All of the property setters on View,
           such as {@link android.view.View#setAlpha setAlpha()} and
           {@link android.view.View#setTranslationX setTranslationX()} invalidate the View
           properly, so you do not need to invalidate the View when calling these methods with new values.
           </p>
-          
+
         </li>
       </ul>
     </li>
@@ -658,7 +663,7 @@
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:id="@+id/verticalContainer"
-    android:animateLayoutChanges="true" /&gt;  
+    android:animateLayoutChanges="true" /&gt;
 </pre>
 
   <p>Setting this attribute to true automatically animates Views that are added or removed from the
@@ -872,16 +877,55 @@
 ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
 </pre>
 
-For more information on creating animators, see the sections on animating with
-<a href="#value-animator">ValueAnimator</a> and <a href="#object-animator">ObjectAnimator</a>
+<p>For more information on creating animators, see the sections on animating with
+<a href="#value-animator">ValueAnimator</a> and <a href="#object-animator">ObjectAnimator</a>.
+</p>
 
+<h3 id="view-prop-animator">Animating with ViewPropertyAnimator</h3>
+<p>The {@link android.view.ViewPropertyAnimator} provides a simple way to animate several
+properties of a {@link android.view.View} in parallel, using a single underlying {@link
+android.animation.Animator}
+object. It behaves much like an {@link android.animation.ObjectAnimator}, because it modifies the
+actual values of the view's properties, but is more efficient when animating many properties at
+once. In addition, the code for using the {@link android.view.ViewPropertyAnimator} is much
+more concise and easier to read. The following code snippets show the differences in using multiple
+{@link android.animation.ObjectAnimator} objects, a single
+{@link android.animation.ObjectAnimator}, and the {@link android.view.ViewPropertyAnimator} when
+simultaneously animating the <code>x</code> and <code>y</code> property of a view.</p>
+
+<p><strong>Multiple ObjectAnimator objects</strong></p>
+<pre>
+ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
+ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
+AnimatorSet animSetXY = new AnimatorSet();
+animSetXY.playTogether(animX, animY);
+animSetXY.start();
+</pre>
+
+<p><strong>One ObjectAnimator</strong></p>
+<pre>
+PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
+PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
+ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
+</pre>
+
+<p><strong>ViewPropertyAnimator</strong></p>
+<pre>
+myView.animate().x(50f).y(100f);
+</pre>
+
+<p>
+For more detailed information about {@link
+android.view.ViewPropertyAnimator}, see the corresponding Android Developers
+<a href="http://android-developers.blogspot.com/2011/05/introducing-viewpropertyanimator.html">blog
+post</a>.</p>
 
 <h2 id="declaring-xml">Declaring Animations in XML</h2>
 
   <p>The property animation system lets you declare property animations with XML instead of doing
   it programmatically. By defining your animations in XML, you can easily reuse your animations
 in multiple activities and more easily edit the animation sequence.</p>
-  
+
 <p>To distinguish animation files that use the new property animation APIs from those that use the
 legacy <a href="{@docRoot}guide/topics/graphics/view-animation.html">view animation</a> framework,
 starting with Android 3.1, you should save the XML files for property animations in the {@code
diff --git a/docs/html/guide/topics/intents/intents-filters.jd b/docs/html/guide/topics/intents/intents-filters.jd
index 5905214..3f94553 100644
--- a/docs/html/guide/topics/intents/intents-filters.jd
+++ b/docs/html/guide/topics/intents/intents-filters.jd
@@ -927,7 +927,7 @@
 
 <p>
 The first, primary, purpose of this activity is to enable the user to 
-interact with a single note &mdash to either {@code VIEW} the note or 
+interact with a single note &mdash; to either {@code VIEW} the note or 
 {@code EDIT} it.  (The {@code EDIT_NOTE} category is a synonym for 
 {@code EDIT}.)  The intent would contain the URI for data matching the 
 MIME type <code>vnd.android.cursor.item/vnd.google.note</code> &mdash;
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 3486212..b2a78fe 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -28,7 +28,9 @@
           android:<a href="#proc">process</a>="<i>string</i>"
           android:<a href="#screen">screenOrientation</a>=["unspecified" | "user" | "behind" |
                                      "landscape" | "portrait" |
-                                     "sensor" | "nosensor"]
+                                     "reverseLandscape" | "reversePortrait" |
+                                     "sensorLandscape" | "sensorPortrait" |
+                                     "sensor" | "fullSensor" | "nosensor"]
           android:<a href="#state">stateNotNeeded</a>=["true" | "false"]
           android:<a href="#aff">taskAffinity</a>="<i>string</i>"
           android:<a href="#theme">theme</a>="<i>resource or theme</i>"
@@ -589,12 +591,6 @@
        uses, and therefore the choices made in specific contexts, may differ 
        from device to device.</td>
 </tr><tr>
-   <td>"{@code landscape}"</td>
-   <td>Landscape orientation (the display is wider than it is tall).</td>
-</tr><tr>
-   <td>"{@code portrait}"</td>
-   <td>Portrait orientation (the display is taller than it is wide).</td>
-</tr><tr>
    <td>"{@code user}"</td>
    <td>The user's current preferred orientation.</td>
 </tr><tr>
@@ -602,16 +598,47 @@
    <td>The same orientation as the activity that's immediately beneath it in 
        the activity stack.</td>
 </tr><tr>
+   <td>"{@code landscape}"</td>
+   <td>Landscape orientation (the display is wider than it is tall).</td>
+</tr><tr>
+   <td>"{@code portrait}"</td>
+   <td>Portrait orientation (the display is taller than it is wide).</td>
+</tr><tr>
+   <td>"{@code reverseLandscape}"</td>
+   <td>Landscape orientation in the opposite direction from normal landscape.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+   <td>"{@code reversePortrait}"</td>
+   <td>Portrait orientation in the opposite direction from normal portrait.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+   <td>"{@code sensorLandscape}"</td>
+   <td>Landscape orientation, but can be either normal or reverse landscape based on the device
+sensor.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+   <td>"{@code sensorPortrait}"</td>
+   <td>Portrait orientation, but can be either normal or reverse portrait based on the device
+sensor.
+<em>Added in API level 9.</em></td>
+</tr><tr>
    <td>"{@code sensor}"</td>
-   <td>The orientation determined by a physical orientation sensor.  The 
-       orientation of the display depends on how the user is holding the device; 
-       it changes when the user rotates the device.</td>
+   <td>The orientation is determined by the device orientation sensor.  The orientation of the
+display depends on how the user is holding the device; it changes when the user rotates the
+device. Some devices, though, will not rotate to all four possible orientations, by default. To
+allow all four orientations, use {@code "fullSensor"}.</td>
+</tr><tr>
+   <td>"{@code fullSensor}"</td>
+   <td>The orientation is determined by the device orientation sensor for any of the 4 orientations.
+This is similar to {@code "sensor"} except this allows any of the 4 possible screen orientations,
+regardless of what the device will normally do (for example, some devices won't normally use reverse
+portrait or reverse landscape, but this enables those). <em>Added in API level 9.</em></td>
 </tr><tr>
    <td>"{@code nosensor}"</td>
-   <td>An orientation determined without reference to a physical orientation sensor.  
-       The sensor is ignored, so the display will not rotate based on how the user 
-       moves the device.  Except for this distinction, the system chooses the 
-       orientation using the same policy as for the "{@code unspecified}" setting.</td>
+   <td>The orientation is determined without reference to a physical orientation sensor.  The sensor
+is ignored, so the display will not rotate based on how the user moves the device.  Except for this
+distinction, the system chooses the orientation using the same policy as for the "{@code
+unspecified}" setting.</td>
 </tr>
 </table></dd>
 
@@ -710,7 +737,7 @@
 The setting must be one of the values listed in the following table, or a 
 combination of one "{@code state...}" value plus one "{@code adjust...}" 
 value.  Setting multiple values in either group &mdash; multiple 
-"{@code state...}" values, for example &mdash has undefined results.  
+"{@code state...}" values, for example &mdash; has undefined results.  
 Individual values are separated by a vertical bar ({@code |}).  For example:
 </p>
 
@@ -801,4 +828,4 @@
 <dt>see also:</dt>
 <dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> 
 <br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code></dd>
-</dl>
\ No newline at end of file
+</dl>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 605a2bb..81d6e27 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,15 +8,15 @@
 <dt>syntax:</dt>
 <dd>
 <pre class="stx">
-&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"]
+&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"]
                   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"]
+                  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>"/&gt;
 </pre>
 </dd>
 
@@ -24,37 +24,38 @@
 <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 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.
+<dd>Lets you specify the screen sizes your application supports and enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> for screens
+larger than what your application supports. It's important that you always use this element in your
+application to specify the screen sizes your application supports.
 
 <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. 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 to fit the current screen, you can
-optimize your UI for different screen sizes by providing <a
+Normal resizing applied by the system 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. However, it's
+often important that you optimize your application's 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>
+layout resources</a>. For instance, you might want to modify the layout of an activity
+when it is on a tablet compared to when running on a handset device.</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>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 ("zoomed") to fit
+larger screens using the system's <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a>. When you
+have not designed for larger screen sizes and the normal resizing does not achieve the appropriate
+results, screen compatibility mode will scale your UI by emulating a <em>normal</em> size
+screen and medium density, then zooming in so that it fills the entire screen. Beware that this
+causes pixelation and blurring of your UI, so it's better if you optimize your UI for large
+screens.</p>
+
+<p class="note"><strong>Note:</strong> Android 3.2 introduces new attributes: {@code
+android:requiresSmallestWidthDp}, {@code android:compatibleWidthLimitDp}, and {@code
+android:largestWidthLimitDp}. If you're developing your application for Android 3.2 and higher,
+you should use these attributes to declare your screen size support, instead of the attributes
+based on generalized screen sizes.</p>
 
 <p>For more information about how to properly support different screen sizes so that you can avoid
-using screen compatibility mode, read
+using screen compatibility mode with your application, read
 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
 
 
@@ -62,17 +63,90 @@
 
 <dd>
 <dl class="attr">
+
+  <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 set false, the system will run your application in <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> on large
+screens.</p>
+
+  <p><strong>This attribute is deprecated</strong>. It was introduced to help applications
+transition from Android 1.5 to 1.6, when support for multiple screens was first introduced. You
+should not use it.</p>
+  </dd>
+  
+  <dt><a name="small"></a>{@code android:smallScreens}</dt>
+  <dd>Indicates whether the application supports smaller screen form-factors.
+     A small screen is defined as one with a smaller aspect ratio than
+     the "normal" (traditional HVGA) screen.  An application that does
+     not support small screens <em>will not be available</em> for
+     small screen devices from external services (such as Android Market), because there is little
+the platform can do to make such an application work on a smaller screen. This is {@code "true"} by
+default.
+  </dd>
+  
+  <dt><a name="normal"></a>{@code android:normalScreens}</dt>
+  <dd>Indicates whether an application supports the "normal" screen
+     form-factors.  Traditionally this is an HVGA medium density
+     screen, but WQVGA low density and WVGA high density are also
+     considered to be normal.  This attribute is "true" by default.
+  </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" 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.
+  <p>The default value for this actually varies between some versions, so it's better if
+you explicitly declare this attribute at all times. Beware that setting it "false" will
+generally enable <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen
+compatibility mode</a>.</p>
+  </dd>
+
+  <dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
+  <dd>Indicates whether the application supports extra large screen form-factors.
+     An xlarge screen is defined as a screen that is significantly larger
+     than a "large" screen, such as a tablet (or something larger) and may require 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.
+  <p>The default value for this actually varies between some versions, so it's better if
+you explicitly declare this attribute at all times. Beware that setting it "false" will
+generally enable <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen
+compatibility mode</a>.</p>
+     <p>This attribute was introduced in API level 9.</p>
+  </dd>
+  
+  <dt><a name="any"></a>{@code android:anyDensity}</dt>
+  <dd>Indicates whether the application includes resources to accommodate any screen
+     density.
+     <p>For applications that support Android 1.6 (API level 4) and higher, this is "true"
+by default and <strong>you should not set it "false"</strong> unless you're absolutely certain that
+it's necessary for your application to work. The only time it might be necessary to disable this
+is if your app directly manipulates bitmaps (see the <a
+href="{@docRoot}guide/practices/screens_support.html#DensityConsiderations">Supporting Multiple
+Screens</a> document for more information).</p>
+  </dd>
   
   <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>
+  <dd>Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of
+the screen space (in {@code dp} units) that must be available to your application UI&mdash;that is,
+the shortest of the available screen's two dimensions. So, in order for a device to be considered
+compatible with your application, the device's smallestWidth must be equal to or greater than this
+value. (Usually, the value you supply for this is the "smallest width" that your layout supports,
+regardless of the screen's current orientation.) 
+
+  <p>For example, a typical handset screen has a smallestWidth of 320dp, a 7" tablet has a
+smallestWidth of 600dp, and a 10" tablet has a smallestWidth of 720dp. These values are generally
+the smallestWidth because they are the shortest dimension of the screen's available space.</p>
+
+<p>The size 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 display, the system declares
+the device's smallestWidth 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 minimum width required by your layout, regardless of the screen's current
+orientation.</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
@@ -80,12 +154,14 @@
 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 class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
+attribute, so it does not affect how your application behaves at runtime. Instead, it is used
+to enable filtering for your application on services such as Android Market. However,
+<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+3.2), so you should continue using the other size attributes if your application does not support
+small screens.</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
@@ -95,29 +171,32 @@
 <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.
+  <dd>This attribute allows you to enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> as a
+user-optional feature by specifying the maximum "smallest screen width" for which your application
+is designed. If the smallest side of a device's available screen is greater than your value here,
+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
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode emulates only 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
+  <dd>This attribute allows you to force-enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> by specifying
+the maximum "smallest screen width" for which your application is designed. If the smallest side of
+a device's available screen is greater than your value here, 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
@@ -125,102 +204,11 @@
 {@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
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode emulates only 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
-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. Otherwise, it is false by default. If set false, the system will not resize
-your application when run on <em>large</em> or <em>xlarge</em> screens. Instead, the
-application appears in a "postage stamp" that equals the <em>normal</em> screen size that your
-application does support. This is less than an ideal experience for users, because the
-application appears smaller than the available screen, but it might help your application run
-normally if it were designed only for the <em>normal</em> screen size and some behaviors do not work
-when resized.</p>
-  <p>To provide the best experience on all screen sizes, you should allow resizing and, if your
-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>
-  
-  
-  <dt><a name="small"></a>{@code android:smallScreens}</dt>
-  <dd>Indicates whether the application supports smaller screen form-factors.
-     A small screen is defined as one with a smaller aspect ratio than
-     the "normal" (traditional HVGA) screen.  An application that does
-     not support small screens <em>will not be available</em> for
-     small screen devices from external services (such as Android Market), because there is little
-the platform can do
-     to make such an application work on a smaller screen. If the application has 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,
-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>
-  <dd>Indicates whether an application supports the "normal" screen
-     form-factors.  Traditionally this is an HVGA medium density
-     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" 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
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
-{@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>
-  <dd>Indicates whether the application supports extra large screen form-factors.
-     An xlarge screen is defined as a screen that is significantly larger
-     than a "large" screen, such as a tablet (or something larger) and may require 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
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
-{@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><strong>This attribute is deprecated</strong> as of API level 13.</p>
-  </dd>
-  
-  <dt><a name="any"></a>{@code android:anyDensity}</dt>
-  <dd>Indicates whether the application includes resources to accommodate any screen
-     density.  Older applications (before API Level 4) are assumed unable to
-     accomodate all densities and this is {@code "false"} by default. If the application has 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,
-the default value for this is {@code "true"}. Otherwise, it is {@code "false"}.
-     You can explicitly supply your abilities here.
-     <p>Based on the "standard" device screen density (medium dpi), the Android framework will scale
-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>
   
 
 </dl></dd>
diff --git a/docs/html/guide/topics/providers/content-providers.jd b/docs/html/guide/topics/providers/content-providers.jd
index 2a84c26..513886a 100644
--- a/docs/html/guide/topics/providers/content-providers.jd
+++ b/docs/html/guide/topics/providers/content-providers.jd
@@ -277,7 +277,7 @@
 constants for their columns.  For example, the 
 {@link android.provider.Contacts.Phones android.provider.Contacts.Phones} class 
 defines constants for the names of the columns in the phone table illustrated 
-earlier &mdash {@code _ID}, {@code NUMBER}, {@code NUMBER_KEY}, {@code NAME},
+earlier &mdash; {@code _ID}, {@code NUMBER}, {@code NUMBER_KEY}, {@code NAME},
 and so on.</li>
 
 <li><p>A filter detailing which rows to return, formatted as an SQL {@code WHERE} 
diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd
index 3df669c..480ca78 100644
--- a/docs/html/guide/topics/resources/animation-resource.jd
+++ b/docs/html/guide/topics/resources/animation-resource.jd
@@ -10,8 +10,8 @@
       <li><a href="#Property">Property Animation</a></li>
       <li><a href="#View">View Animation</a>
         <ol>
-          <li><a href="Tween">Tween animation</li>
-          <li><a href="Frame">Frame animation</li>
+          <li><a href="Tween">Tween animation</a></li>
+          <li><a href="Frame">Frame animation</a></li>
         </ol>      
       </li>
     </ol>
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index 89c85e2..912b6fd 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -1418,7 +1418,7 @@
 The filename is used as the resource ID.</dd>
 
 <dt>compiled resource datatype:</dt>
-<dd>Resource pointer to a {@link android.graphics.drawable.ShapeDrawable}.</dd>
+<dd>Resource pointer to a {@link android.graphics.drawable.GradientDrawable}.</dd>
 
 <dt>resource reference:</dt>
 
@@ -1458,9 +1458,7 @@
         android:bottom="<em>integer</em>" /&gt;
     &lt;<a href="#size-element">size</a>
         android:width="<em>integer</em>"
-        android:color="<em>color</em>"
-        android:dashWidth="<em>integer</em>"
-        android:dashGap="<em>integer</em>" /&gt;
+        android:height="<em>integer</em>" /&gt;
     &lt;<a href="#solid-element">solid</a>
         android:color="<em>color</em>" /&gt;
     &lt;<a href="#stroke-element">stroke</a>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index ea778c1..252c153 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -334,7 +334,7 @@
       </td>
     </tr>
     <tr id="SmallestScreenWidthQualifier">
-      <td>Smallest screen width</td>
+      <td>smallestWidth</td>
       <td><code>sw&lt;N&gt;dp</code><br/><br/>
         Examples:<br/>
         <code>sw320dp</code><br/>
@@ -343,18 +343,23 @@
         etc.
       </td>
       <td>
-        <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>The fundamental size of a screen, as indicated by the shortest dimension of the available
+screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
+height and width (you may also think of it as the "smallest possible width" for the screen). You can
+use this qualifier to ensure that, regardless of the screen's current orientation, your
+application's has at least {@code &lt;N&gt;} dps of width available for it UI.</p>
+        <p>For example, if your layout requires that its smallest dimension of screen area be at
+least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
+available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
+height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
+device's smallestWidth does not change when the screen's orientation changes</strong>.</p>
+        <p>The smallestWidth of a device takes into account screen decorations and system UI. For
+example, if the device has some persistent UI elements on the screen that account for space along
+the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual
+screen size, because those are screen pixels not available for your UI. Thus, the value you use
+should be the actual smallest dimension <em>required by your layout</em> (usually, this value is the
+"smallest width" that your layout supports, regardless of the screen's current orientation).</p>
         <p>Some values you might use here for common screen sizes:</p>
         <ul>
           <li>320, for devices with screen configurations such as:
@@ -369,19 +374,22 @@
           <li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
         </ul>
         <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>
+        the smallestWidth qualifier, the system uses the one closest to (without exceeding) the
+device's smallestWidth. </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>
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+android:requiresSmallestWidthDp}</a> attribute, which declares the minimum smallestWidth with which
+your application is compatible, and the {@link
+android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds the
+device's smallestWidth value.</p>
+        <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
       </td>
     </tr>
     <tr id="ScreenWidthQualifier">
-      <td>Screen width</td>
+      <td>Available width</td>
       <td><code>w&lt;N&gt;dp</code><br/><br/>
         Examples:<br/>
         <code>w720dp</code><br/>
@@ -389,7 +397,7 @@
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+        <p>Specifies a minimum available 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>
@@ -403,10 +411,13 @@
         <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>
+        <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
       </td>
     </tr>
     <tr id="ScreenHeightQualifier">
-      <td>Screen height</td>
+      <td>Available height</td>
       <td><code>h&lt;N&gt;dp</code><br/><br/>
         Examples:<br/>
         <code>h720dp</code><br/>
@@ -414,7 +425,7 @@
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen height, in "dp" units at which the resource
+        <p>Specifies a minimum available 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>
@@ -432,6 +443,9 @@
         <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>
+        <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
       </td>
     </tr>
     <tr id="ScreenSizeQualifier">
@@ -444,30 +458,35 @@
       </td>
       <td>
         <ul class="nolist">
-        <li>{@code small}: Screens based on the space available on a
-        low-density QVGA screen.  Considering a portrait HVGA display, this has
-        the same available width but less height&mdash;it is 3:4 vs. HVGA's
-        2:3 aspect ratio.  The minimum layout size for this screen configuration
+        <li>{@code small}: Screens that are of similar size to a
+        low-density QVGA screen. The minimum layout size for a small screen
         is approximately 320x426 dp units.  Examples are QVGA low density and VGA high
         density.</li>
-        <li>{@code normal}: Screens based on the traditional
-        medium-density HVGA screen.  A screen is considered to be normal if it is
-        at least this size (independent of density) and not larger.  The minimum
-        layout size for this screen configuration is approximately 320x470 dp units.  Examples
+        <li>{@code normal}: Screens that are of similar size to a
+        medium-density HVGA screen. The minimum
+        layout size for a normal screen is approximately 320x470 dp units.  Examples
         of such screens a WQVGA low density, HVGA medium density, WVGA
         high density.</li>
-        <li>{@code large}: Screens based on the space available on a
-        medium-density VGA screen.  Such a screen has significantly more
-        available space in both width and height than an HVGA display.
-        The minimum layout size for this screen configuration is approximately 480x640 dp units.
+        <li>{@code large}: Screens that are of similar size to a
+        medium-density VGA screen.
+        The minimum layout size for a large screen is approximately 480x640 dp units.
         Examples are VGA and WVGA medium density screens.</li>
         <li>{@code xlarge}: Screens that are considerably larger than the traditional
-        medium-density HVGA screen. The minimum layout size for this screen configuration
+        medium-density HVGA screen. The minimum layout size for an xlarge screen
         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>
         </ul>
+        <p class="note"><strong>Note:</strong> Using a size qualifier does not imply that the
+resources are <em>only</em> for screens of that size. If you do not provide alternative
+resources with qualifiers that better match the current device configuration, the system may use
+whichever resources are the <a href="#BestMatch">best match</a>.</p>
+        <p class="caution"><strong>Caution:</strong> If all your resources use a size qualifier that
+is <em>larger</em> than the current screen, the system will <strong>not</strong> use them and your
+application will crash at runtime (for example, if all layout resources are tagged with the {@code
+xlarge} qualifier, but the device is a normal-size screen).</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,
@@ -557,7 +576,8 @@
         <code>mdpi</code><br/>
         <code>hdpi</code><br/>
         <code>xhdpi</code><br/>
-        <code>nodpi</code>
+        <code>nodpi</code><br/>
+        <code>tvdpi</code>
       </td>
       <td>
         <ul class="nolist">
@@ -569,21 +589,23 @@
 Level 8</em></li>
           <li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
 to match the device density.</li>
+          <li>{@code tvdpi}: Screens somewhere between mdpi and hdpi; approximately 213dpi. This is
+not considered a "primary" density group. It is mostly intended for televisions and most
+apps shouldn't need it&mdash;providing mdpi and hdpi resources is sufficient for most apps and
+the system will scale them as appropriate. This qualifier was introduced with API level 13.</li>
         </ul>
-        <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,
-         it handles screen density differently than the other qualifiers.
-         In step 1 of <a href="#BestMatch">How Android finds the best
-         matching directory</a> (below), screen density is always considered to
-         be a match. In step 4, if the qualifier being considered is screen
-         density, Android selects the best final match at that point,
-         without any need to move on to step 5.
-         </p>
+        <p>There is a 3:4:6:8 scaling ratio between the four primary densities (ignoring the
+tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
+        <p>If you decide that your image resources don't look good enough on a television or
+other certain devices and want to try tvdpi resources, the scaling factor is 1.33*mdpi. For
+example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.</p>
+        <p class="note"><strong>Note:</strong> Using a density qualifier does not imply that the
+resources are <em>only</em> for screens of that density. If you do not provide alternative
+resources with qualifiers that better match the current device configuration, the system may use
+whichever resources are the <a href="#BestMatch">best match</a>.</p>
         <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
-Screens</a> for more information about how to handle screen sizes and how Android might scale
-your bitmaps.</p>
+Screens</a> for more information about how to handle different screen densities and how Android
+might scale your bitmaps to fit the current density.</p>
        </td>
     </tr>
     <tr id="TouchscreenQualifier">
@@ -993,7 +1015,10 @@
 </p>
 
 <p>By comparing the device configuration to the available alternative resources, Android selects
-drawables from {@code drawable-en-port}. It arrives at this decision using the following logic:</p>
+drawables from {@code drawable-en-port}.</p>
+
+<p>The system arrives at its decision for which resources to use with the following
+logic:</p>
 
 
 <div class="figure" style="width:280px">
@@ -1069,6 +1094,14 @@
 something other than English is never included in the pool of resources checked (though a
 resource directory <em>without</em> the language qualifier is still included).</p>
 
+<p>When selecting resources based on the screen size qualifiers, the system will use resources
+designed for a screen smaller than the current screen if there are no resources that better match
+(for example, a large-size screen will use normal-size screen resources if necessary). However, if
+the only available resources are <em>larger</em> than the current screen, the system will
+<strong>not</strong> use them and your application will crash if no other resources match the device
+configuration (for example, if all layout resources are tagged with the {@code xlarge} qualifier,
+but the device is a normal-size screen).</p>
+
 <p class="note"><strong>Note:</strong> The <em>precedence</em> of the qualifier (in <a
 href="#table2">table 2</a>) is more important
 than the number of qualifiers that exactly match the device. For example, in step 4 above, the last
diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd
index 2db38f1..ecd2d48 100644
--- a/docs/html/guide/topics/resources/string-resource.jd
+++ b/docs/html/guide/topics/resources/string-resource.jd
@@ -107,7 +107,7 @@
 String string = {@link android.content.Context#getString(int) getString}(R.string.hello);
 </pre>
 <p>You can use either {@link android.content.Context#getString(int)} or
-{@link android.content.Context#getText(int)} to retieve a string. {@link
+{@link android.content.Context#getText(int)} to retrieve a string. {@link
 android.content.Context#getText(int)} will retain any rich text styling applied to the string.</p>
 
 </dd> <!-- end example -->
@@ -233,9 +233,9 @@
 
 <p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code>
 in English will be ignored even if the quantity is 0, because 0 isn't grammatically different
-from 2, or any other number except 1 ("zero books", "one book", "two books", et cetera).
+from 2, or any other number except 1 ("zero books", "one book", "two books", and so on).
 Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
-the quantity 2: a language may require that 2, 12, 102 (et cetera) are all treated like one
+the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one
 another but differently to other quantities. Rely on your translator to know what distinctions
 their language actually insists upon.
 
@@ -359,8 +359,15 @@
 int count = getNumberOfsongsAvailable();
 Resources res = {@link android.content.Context#getResources()};
 String songsFound = res.{@link android.content.res.Resources#getQuantityString(int,int)
-getQuantityString}(R.plurals.numberOfSongsAvailable, count);
+getQuantityString}(R.plurals.numberOfSongsAvailable, count, count);
 </pre>
+<p>When using the {@link android.content.res.Resources#getQuantityString(int,int)
+getQuantityString()} method, you need to pass the {@code count} twice if your string includes
+<a href="#FormattingAndStyling">string formatting</a> with a number. For example, for the string
+{@code %d songs found}, the first {@code count} parameter selects the appropriate plural string and
+the second {@code count} parameter is inserted into the {@code %d} placeholder. If your plural
+strings do not include string formatting, you don't need to pass the third parameter to {@link
+android.content.res.Resources#getQuantityString(int,int) getQuantityString}.</p>
 </dd> <!-- end example -->
 
 </dl>
@@ -405,7 +412,7 @@
 </pre>
 
 <p>In this example, the format string has two arguments: {@code %1$s} is a string and {@code %2$d}
-is a decimal number. You can format the string with arguements from your application like this:</p>
+is a decimal number. You can format the string with arguments from your application like this:</p>
 
 <pre>
 Resources res = {@link android.content.Context#getResources()};
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index b5a3f30..463ec9c 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -59,7 +59,6 @@
         <li><a href="https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package</a></li>
       </ol>
 
-
       <h2>See also</h2>
 
       <ol>
@@ -70,22 +69,29 @@
       <h2>Where to buy</h2>
 
       <ol>
+
+      <li><a href="http://store.arduino.cc/">
+        Arduino Store</a></li>
+
+      <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
+        DIY Drones</a></li>
+
+      <li><a href=
+        "http://www.microchip.com/android">
+        Microchip</a></li>
+
       <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">
         Modern Device</a></li>
 
+      <li><a href=
+        "http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
+        RT Corp</a></li>
+
       <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
         Seeed Studio</a></li>
 
-        <li><a href=
-        "http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
-        RT Corp</a></li>
-
-        <li><a href=
-        "http://www.microchip.com/android">
-        Microchip</a></li>
-
-        <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
-        DIY Drones</a></li>
+      <li><a href="http://www.sparkfun.com/products/10748">
+        SparkFun</a></li>
 
       </ol>
     </div>
@@ -114,22 +120,31 @@
   development boards:</p>
 
   <ul>
-    <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern
-    Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
 
-    <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
-    Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
-
-    <li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
-    RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li>
-
-    <li><a href="http://www.microchip.com/android">Microchip</a> provides a A PIC based USB
-    microcontroller board.</li>
+    <li>The <a href="http://store.arduino.cc/">Arduino Store</a> provides the Arduino Mega ADK
+    (in <a href="http://store.arduino.cc/eu/index.php?main_page=product_info&cPath=11_12&products_id=144">EU nations</a>
+    or <a href="http://store.arduino.cc/ww/index.php?main_page=product_info&cPath=11_12&products_id=144">non-EU nations</a>)
+    that is based on the ATmega2560 and supports the ADK firmware.</li>
 
     <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">DIY
     Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV
     (unmanned aerial vehicle) enthusiasts.</li>
 
+    <li><a href="http://www.microchip.com/android">Microchip</a> provides a PIC based USB
+    microcontroller board.</li>
+
+    <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern
+    Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
+    <li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
+    RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li>
+
+    <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
+    Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
+    <li><a href="http://www.sparkfun.com/products/10748">
+    SparkFun</a>'s IOIO board now has beta support for the ADK firmware.</li>
+
   </ul>
 
   <p>We expect more hardware distributers to create a variety of kits, so please stay tuned for
@@ -140,7 +155,7 @@
   accessory that is based on the <a href="http://www.arduino.cc/">Arduino open source electronics
   prototyping platform</a>, the accessory's hardware design files, code that implements the
   accessory's firmware, and the Android application that interacts with the accessory. The hardware
-  design files and firmware code are contained in the <a href=ctive 
+  design files and firmware code are contained in the <a href=
   "https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package download</a>.</p>
   <p>The main hardware and software components of the ADK include:</p>
 
@@ -347,7 +362,7 @@
     2.3.4 devices that support accessory mode. This library is also forward compatible with Android
     3.1 or newer devices that support accessory mode. If you only care about Android 3.1 or newer
     devices, all you need is API Level 12. For more information on deciding which API level to use,
-    see the <a href="{@docRoot}guide/topics/USB/accessory.html#choosing">USB Accessory</a>
+    see the <a href="{@docRoot}guide/topics/usb/accessory.html#choosing">USB Accessory</a>
     documentation.</li>
 
     <li>Click <strong>File &gt; New &gt; Project...</strong>, then select <strong>Android &gt;
@@ -885,4 +900,4 @@
 </pre>
 
   <p>See the <code>firmware/demokit/demokit.pde</code> file for information about how the ADK board
-  reads and writes data.</p>
\ No newline at end of file
+  reads and writes data.</p>
diff --git a/docs/html/guide/topics/usb/host.jd b/docs/html/guide/topics/usb/host.jd
index 942708d..4967033 100644
--- a/docs/html/guide/topics/usb/host.jd
+++ b/docs/html/guide/topics/usb/host.jd
@@ -264,11 +264,7 @@
 UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
 ...  
 HashMap&lt;String, UsbDevice&gt; deviceList = manager.getDeviceList();
-Iterator&lt;UsbDevice&gt; deviceIterator  = deviceList.values().iterator();
-while(deviceIterator.hasNext()){
-    UsbDevice device = deviceIterator.next();
-    // your code
-}
+UsbDevice device = deviceList.get("deviceName");
 </pre>
 
   <p>If desired, you can also just obtain an iterator from the hash map and process each device one
diff --git a/docs/html/images/home/market_icon.png b/docs/html/images/home/market_icon.png
new file mode 100644
index 0000000..ceb76f3
--- /dev/null
+++ b/docs/html/images/home/market_icon.png
Binary files differ
diff --git a/docs/html/images/market/version-codes.png b/docs/html/images/market/version-codes.png
new file mode 100644
index 0000000..c0c9858
--- /dev/null
+++ b/docs/html/images/market/version-codes.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index dce46f9..a8b61bf 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -11,15 +11,14 @@
                             </div><!-- end homeTitle -->
                             <div id="announcement-block">
                             <!-- total max width is 520px -->
-                                  <img src="{@docRoot}assets/images/home/IO-logo-2011.png"
-alt="Android at Google IO 2011" width="200px"
-style="padding-left:22px;padding-bottom:15px;padding-top:15px;"/>
+                                  <img src="{@docRoot}images/home/market_icon.png"
+alt="Android Market" width="120px" style="padding:10px 53px 5px"/>
                                   <div id="announcement" style="width:275px">
-    <p>Thanks to everybody who joined us at Google I/O! If you couldn't make it or would like to
-review any of the Android sessions, they're now available on YouTube at the <a
-href="http://www.youtube.com/googledevelopers">Google Developers</a> channel, along with the keynote
-and other developer sessions. You can also find all the Google I/O Android sessions on this site, on
-the <a href="{@docRoot}videos/index.html">Videos</a> page.</p>
+    <p>We've completely redesigned Android Market for phones to make it easier to
+explore Android apps, games, and other content. Look for the new version coming to your
+Android phone!</p> <p><a
+href="http://android-developers.blogspot.com/2011/07/new-android-market-for-phones.html">Learn more
+&raquo;</a></p>
                                 </div> <!-- end annoucement -->
                             </div> <!-- end annoucement-block -->
                         </div><!-- end topAnnouncement -->
@@ -130,14 +129,14 @@
     'sdk': {
       'layout':"imgLeft",
       'icon':"sdk-small.png",
-      'name':"Android 3.1",
+      'name':"Android 3.2",
       'img':"honeycomb-android.png",
-      'title':"Android 3.1 now available!",
-      'desc': "<p>Android 3.1 includes new developer features such as APIs for USB "
-+ "accessories, MTP/PTP, and RTP, as well as new input events from mice, trackballs, joysticks, "
-+ "and more.</p>"
-+ "<p>For more information about all the new APIs in Android 3.1, read the "
-+ "<a href='{@docRoot}sdk/android-3.1.html'>version notes</a>.</p>"
+      'title':"Android 3.2 is here!",
+      'desc': "<p>Android 3.2 is a minor feature update that includes new APIs that allow you to "
++ "better target your layouts for specific screen sizes and other miscellaneous new APIs.</p>"
++ "<p>For more information about all the changes in Android 3.2, read the "
++ "<a href='{@docRoot}sdk/android-3.2.html'>version notes</a> and <a "
++ "href='{@docRoot}sdk/api_diff/13/changes.html'>diff report</a>.</p>"
 /*
 + "<p>If you have an existing SDK, add Android 3.0 as an "
 + "<a href='{@docRoot}sdk/adding-components.html'>SDK "
@@ -153,10 +152,11 @@
       '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" 
+	        +  " <p>Google TV brings 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>"
+		+  " The average American watches five hours of TV per day. Give them the apps"
+		+  " to update their status, listen to music, watch web videos, and more.</p>"
+                +  "<p><a href='http://code.google.com/tv'>Develop for Google TV &raquo;</a></p>"
     },
 
 
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index 3fcfa89..362ee16 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -74,6 +74,6 @@
 </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/tutorials/views/hello-gallery.jd b/docs/html/resources/tutorials/views/hello-gallery.jd
index 00757f5..5f2ed32 100644
--- a/docs/html/resources/tutorials/views/hello-gallery.jd
+++ b/docs/html/resources/tutorials/views/hello-gallery.jd
@@ -34,10 +34,10 @@
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
 
-    Gallery g = (Gallery) findViewById(R.id.gallery);
-    g.setAdapter(new ImageAdapter(this));
+    Gallery gallery = (Gallery) findViewById(R.id.gallery);
+    gallery.setAdapter(new ImageAdapter(this));
 
-    g.setOnItemClickListener(new OnItemClickListener() {
+    gallery.setOnItemClickListener(new OnItemClickListener() {
         public void onItemClick(AdapterView parent, View v, int position, long id) {
             Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show();
         }
@@ -101,10 +101,10 @@
 
     public ImageAdapter(Context c) {
         mContext = c;
-        TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
-        mGalleryItemBackground = a.getResourceId(
+        TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery);
+        mGalleryItemBackground = attr.getResourceId(
                 R.styleable.HelloGallery_android_galleryItemBackground, 0);
-        a.recycle();
+        attr.recycle();
     }
 
     public int getCount() {
@@ -120,14 +120,14 @@
     }
 
     public View getView(int position, View convertView, ViewGroup parent) {
-        ImageView i = new ImageView(mContext);
+        ImageView imageView = new ImageView(mContext);
 
-        i.setImageResource(mImageIds[position]);
-        i.setLayoutParams(new Gallery.LayoutParams(150, 100));
-        i.setScaleType(ImageView.ScaleType.FIT_XY);
-        i.setBackgroundResource(mGalleryItemBackground);
+        imageView.setImageResource(mImageIds[position]);
+        imageView.setLayoutParams(new Gallery.LayoutParams(150, 100));
+        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+        imageView.setBackgroundResource(mGalleryItemBackground);
 
-        return i;
+        return imageView;
     }
 }
 </pre>
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index 6eba6f09..3f28551 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -73,51 +73,44 @@
 {@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
 the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
 
-<script type="text/javascript">
-function toggleDiv(link) {
-  var toggleable = $(link).parent();
-  if (toggleable.hasClass("closed")) {
-    //$(".toggleme", toggleable).slideDown("fast");
-    toggleable.removeClass("closed");
-    toggleable.addClass("open");
-    $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
-  } else {
-    //$(".toggleme", toggleable).slideUp("fast");
-    toggleable.removeClass("open");
-    toggleable.addClass("closed");
-    $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
-  }
-  return false;
-}
-</script>
-<style>
-.toggleable {
-  padding: .25em 1em 0em 1em;
-  margin-bottom: 0;
-}
-.toggleme {
-  padding: 1em 1em 0 2em;
-  line-height:1em;
-}
-.toggleable a {
-  text-decoration:none;
-}
-.toggleme a {
-  text-decoration:underline;
-}
-.toggleable.closed .toggleme {
-  display:none;
-}
-#jd-content .toggle-img {
-  margin:0;
-}
-</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" />
-        Android 2.1, Revision 2</a> <em>(May 2010)</em></a>
-  <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 2</a> <em>(May 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
 <dl>
 <dt>Dependencies:</dt>
 <dd>
@@ -136,11 +129,15 @@
  </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" />
-        Android 2.1, Revision 1</a> <em>(January 2010)</em></a>
-  <div class="toggleme">
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 1</a> <em>(January 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
 <dl>
 <dt>Dependencies:</dt>
 <dd>
diff --git a/docs/html/sdk/android-2.2.jd b/docs/html/sdk/android-2.2.jd
index 063a10f..c22220c 100644
--- a/docs/html/sdk/android-2.2.jd
+++ b/docs/html/sdk/android-2.2.jd
@@ -74,54 +74,46 @@
 {@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
 the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
 
-<script type="text/javascript">
-function toggleDiv(link) {
-  var toggleable = $(link).parent();
-  if (toggleable.hasClass("closed")) {
-    //$(".toggleme", toggleable).slideDown("fast");
-    toggleable.removeClass("closed");
-    toggleable.addClass("open");
-    $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
-  } else {
-    //$(".toggleme", toggleable).slideUp("fast");
-    toggleable.removeClass("open");
-    toggleable.addClass("closed");
-    $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
-  }
-  return false;
-}
-</script>
-<style>
-.toggleable {
-  padding: .25em 1em 0em 1em;
-  margin-bottom: 0;
-}
-.toggleme {
-  padding: 1em 1em 0 2em;
-  line-height:1em;
-}
-.toggleable a {
-  text-decoration:none;
-}
-.toggleme a {
-  text-decoration:underline;
-}
-.toggleable.closed .toggleme {
-  display:none;
-}
-#jd-content .toggle-img {
-  margin:0;
-}
-</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" />
-        Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2010)</em></a>
-  <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
 <dl>
 <dt>Dependencies:</dt>
 <dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+<dt>Dependencies:</dt>
+<dd>
 <p>Requires SDK Tools r6 or higher.</p>
 </dd>
 
@@ -138,11 +130,15 @@
  </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" />
-        Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2010)</em></a>
-  <div class="toggleme">
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
 <dl>
 <dt>Dependencies:</dt>
 <dd>
diff --git a/docs/html/sdk/android-2.3.3.jd b/docs/html/sdk/android-2.3.3.jd
index 10fc049..7a5b044 100644
--- a/docs/html/sdk/android-2.3.3.jd
+++ b/docs/html/sdk/android-2.3.3.jd
@@ -65,59 +65,52 @@
 {@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
 the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
 
-<script type="text/javascript">
-function toggleDiv(link) {
-  var toggleable = $(link).parent();
-  if (toggleable.hasClass("closed")) {
-    //$(".toggleme", toggleable).slideDown("fast");
-    toggleable.removeClass("closed");
-    toggleable.addClass("open");
-    $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
-  } else {
-    //$(".toggleme", toggleable).slideUp("fast");
-    toggleable.removeClass("open");
-    toggleable.addClass("closed");
-    $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
-  }
-  return false;
-}
-</script>
-<style>
-.toggleable {
-  padding: .25em 1em 0em 1em;
-  margin-bottom: 0;
-}
-.toggleme {
-  padding: 1em 1em 0 2em;
-  line-height:1em;
-}
-.toggleable a {
-  text-decoration:none;
-}
-.toggleme a {
-  text-decoration:underline;
-}
-.toggleable.closed .toggleme {
-  display:none;
-}
-#jd-content .toggle-img {
-  margin:0;
-}
-</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" />
-        Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em></a>
-  <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
 <dl>
 <dt>Dependencies:</dt>
 <dd>
 <p>Requires SDK Tools r9 or higher.</p>
 </dd>
-
 </dl>
- </div>
+
+</div>
 </div>
 
 
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index d73bd63..7b04446 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -62,25 +62,52 @@
 refer to the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
 
 
+
 <div class="toggle-content opened" style="padding-left:1em;">
 
-  <p><a href="#" onclick="return toggleContent(this)">
-    <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt="" />
-    Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
-  </a></p>
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2011)</em>
+</a></p>
 
-  <div class="toggle-content-toggleme" style="padding-left:2em;">
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
     
 <dl>
-  
 <dt>Dependencies:</dt>
 <dd>
 <p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r10</a> or higher.</p>
 </dd>
-
 </dl>
 
-  </div>
+</div>
 </div>
 
 
diff --git a/docs/html/sdk/android-3.1.jd b/docs/html/sdk/android-3.1.jd
index 992b7d1..0d2d7f8 100644
--- a/docs/html/sdk/android-3.1.jd
+++ b/docs/html/sdk/android-3.1.jd
@@ -19,14 +19,14 @@
 <h2>Reference</h2>
 <ol>
 <li><a
-href="{@docRoot}sdk/api_diff/11/changes.html">API
+href="{@docRoot}sdk/api_diff/12/changes.html">API
 Differences Report &raquo;</a> </li>
 </ol>
 
 <h2>See Also</h2>
 <ol>
   <li><a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing
-Apps for Android 3.0</a></li>
+Apps for Android 3.x</a></li>
 </ol>
 
 </div>
@@ -68,25 +68,79 @@
 
 <div class="toggle-content opened" style="padding-left:1em;">
 
-  <p><a href="#" onclick="return toggleContent(this)">
-    <img src="{@docRoot}assets/images/triangle-opened.png"
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-opened.png"
 class="toggle-content-img" alt="" />
-    Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2011)</em>
-  </a></p>
+  Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
 
-  <div class="toggle-content-toggleme" style="padding-left:2em;">
+<div class="toggle-content-toggleme" style="padding-left:2em;">
 
 <dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
 
+</div>
+</div>
+
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 2</a> <em>(May 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
 <dt>Dependencies:</dt>
 <dd>
 <p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r11</a> or
 higher.</p>
 </dd>
-
+<dt>Notes:</dt>
+<dd>
+<p>Fixes an issue with the visual layout editor rendering library that prevented Android 3.1 from
+running in ADT.</p>
+</dd>
 </dl>
 
-  </div>
+</div>
+</div>
+
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+  Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r11</a> or
+higher.</p>
+</dd>
+</dl>
+
+</div>
 </div>
 
 
@@ -765,7 +819,7 @@
 
 </ul>
 
-<h3 if="other">Core utilities</h3>
+<h3 id="other">Core utilities</h3>
 
 <ul>
 <li>LRU cache
diff --git a/docs/html/sdk/android-3.2.jd b/docs/html/sdk/android-3.2.jd
new file mode 100644
index 0000000..5618eae
--- /dev/null
+++ b/docs/html/sdk/android-3.2.jd
@@ -0,0 +1,737 @@
+page.title=Android 3.2 Platform
+sdk.platform.version=3.2
+sdk.platform.apiLevel=13
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#relnotes">Revisions</a></li>
+  <li><a href="#highlights">Highlights</a></li>
+  <li><a href="#api">API Overview</a></li>
+  <li><a href="#api-level">API Level</a></li>
+  <li><a href="#apps">Built-in Applications</a></li>
+  <li><a href="#locs">Locales</a></li>
+  <li><a href="#skins">Emulator Skins</a></li>
+</ol>
+
+<h2>Reference</h2>
+<ol>
+<li><a
+href="{@docRoot}sdk/api_diff/13/changes.html">API
+Differences Report &raquo;</a> </li>
+</ol>
+
+<h2>See Also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting
+  Multiple Screens</a></li>
+  <li><a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing
+Apps for Android 3.x</a></li>
+</ol>
+
+</div>
+</div>
+
+
+<p><em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
+
+<p>Welcome to Android 3.2!</p>
+
+<p>Android 3.2 is an incremental platform release that adds new
+capabilities for users and developers. The sections below provide an overview
+of the new features and developer APIs.</p>
+
+<p>For developers, the Android {@sdkPlatformVersion} platform is available as a
+downloadable component for the Android SDK. The downloadable platform includes
+an Android library and system image, as well as a set of emulator skins and
+more. The downloadable platform includes no external libraries.</p>
+
+<p>To get started developing or testing against Android {@sdkPlatformVersion},
+use the Android SDK Manager to download the platform into your SDK. For more
+information, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK
+Components</a>. If you are new to Android, <a
+href="{@docRoot}sdk/index.html">download the SDK Starter Package</a> first.</p>
+
+<p class="note"><strong>Reminder:</strong> If you've already published an
+Android application, please test and optimize your application on Android 3.2 as
+soon as possible. You should do so to be sure your application provides the best
+experience possible on the latest Android-powered devices. For information about
+what you can do, read <a
+href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for
+Android 3.x</a>.</p>
+
+
+<h2 id="relnotes">Revisions</h2>
+
+<p>To determine what revision of the Android {@sdkPlatformVersion} platform you
+have installed, refer to the "Installed Packages" listing in the Android SDK and
+AVD Manager.</p>
+
+
+<div class="toggle-content opened" style="padding-left:1em;">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+    Android {@sdkPlatformVersion}, Revision 1</a> <em>(July 2011)</em>
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Initial release. SDK Tools r12 or higher is recommended.</dt>
+</dl>
+
+  </div>
+</div>
+
+<h2 id="highlights" style="margin-top:1.5em;">Platform Highlights</h2>
+
+<h3>New user features</h3>
+
+<ul>
+<li><strong>Optimizations for a wider range of tablets</strong>
+
+<p>Android 3.2 includes a variety of optimizations across the system
+to ensure a great user experience on a wider range of tablet devices.</p></li>
+
+<li><strong>Compatibility zoom for fixed-sized apps</strong>
+
+<p>Android 3.2 introduces a new <em>compatibility zoom</em> mode that gives
+users a new way to view fixed-sized apps on larger devices. The new mode provides a
+pixel-scaled alternative to the standard UI stretching for apps that are not
+designed to run on larger screen sizes, such as on tablets. The new mode is
+accessible to users from a menu icon in the system bar, for apps that need
+compatibility support.</p></li>
+
+<li><strong>Media sync from SD card</strong>
+<p>On devices that support an SD card, users can now load media files directly
+from the SD card to apps that use them. A system facility makes the files
+accessible to apps from the system media store.</p></li>
+</ul>
+
+
+<h3>New developer features</h3>
+
+<ul>
+<li><strong>Extended API for managing screens support</strong>
+
+<p>Android 3.2 introduces extensions to the platform's screen support API to
+give developers additional ways to manage application UI across the range of
+Android-powered devices. The API includes new resource qualifiers and new
+manifest attributes that give you more precise control over how your
+apps are displayed on different sizes, rather than relying on generalized
+size categories.</p>
+
+<p>To ensure the best possible display for fixed-sized apps and apps with limited
+support for various screen sizes, the platform also provides a new zoom
+compatibility mode that renders the UI on a smaller screen area, then scales it
+up to fill the space available on the display. For more information about the
+screen support API and the controls it provides, see the sections below. </p></li>
+</ul>
+
+
+<h2 id="api">API Overview</h2>
+
+<h3 id="usb">Screens Support APIs</h3>
+
+<p>Android 3.2 introduces new screens support APIs that give you more
+control over how their applications are displayed across different screen sizes.
+The API builds on the existing screens-support API, including the platform's
+generalized screen density model, but extends it with the ability to precisely
+target specific screen ranges by their dimensions, measured in
+density-independent pixel units (such as 600dp or 720dp wide), rather than
+by their generalized screen sizes (such as large or xlarge)</p>
+
+<p>When designing an application's UI, you can still rely on the platform to
+provide density abstraction, which means that applications do not need to
+compensate for the differences in actual pixel density across devices. You
+can design the application UI according to the amount of horizontal or vertical
+space available. The platform expresses the amount of space available using three new
+characteristics: <em>smallestWidth</em>, <em>width</em>, and
+<em>height</em>.</p>
+
+<ul>
+<li>A screen's <em>smallestWidth</em> is its fundamental minimum size,
+measured in density-independent pixel ("dp") units. Of the screen's height or
+width, it is the shorter of the two. For a screen in portrait orientation, the
+smallestWidth is normally based on its width, while in landscape orientation it is based
+on its height. In all cases, the smallestWidth is derived from a fixed characteristic of the
+screen and the value does not change, regardless of orientation. The smallestWidth
+is important for applications because it represents the shortest possible width
+in which the application UI will need to be drawn, not including screen areas
+reserved by the system.
+</li>
+
+<li>In constrast, a screen's <em>width</em> and <em>height</em> represent the
+current horizontal or vertical space available for application layout, measured
+in "dp" units, not including screen areas reserved by the system. The width and
+height of a screen change when the user switches orientation between landscape
+and portrait. </li>
+
+</ul>
+
+<p>The new screens support API is designed to let you manage application UI
+according to the smallestWidth of the current screen. You can also manage the
+UI according to current width or height, as needed. For those purposes, the API
+provides these tools:</p>
+
+<ul>
+<li>New resource qualifiers for targeting layouts and other resources to a
+minimum smallestWidth, width, or height, and</li> 
+<li>New manifest attributes, for specifying the app's maximum
+screen compatibility range</li>
+</ul>
+
+<p>Additionally, applications can still query the system and manage UI and
+resource loading at runtime, as in the previous versions of the platform.</p>
+
+<p>Since the new API lets you target screens more directly through smallestWidth,
+width, and height, it's helpful to understand the typical
+characteristics of the different screen types. The table below provides some
+examples, measured in "dp" units. </p>
+
+<p class="caption"><strong>Table 1.</strong> Typical devices, with density
+and size in dp.</p>
+
+<table>
+<tr>
+<th>Type</th>
+<th>Density (generalized)</th>
+<th>Dimensions (dp)</th>
+<th>smallestWidth (dp)</th>
+</tr>
+<tr>
+<td>Baseline phone</td>
+<td>mdpi</td>
+<td>320x480</td>
+<td>320</td>
+</td>
+<tr>
+<td>Small tablet/large phone</td>
+<td>mdpi</td>
+<td>480x800</td>
+<td>480</td>
+</tr>
+<tr>
+<td>7-inch tablet</td>
+<td>mdpi</td>
+<td>600x1024</td>
+<td>600</td>
+</tr>
+<tr>
+<td>10-inch tablet</td>
+<td>mdpi</td>
+<td>800x1280</td>
+<td>800</td>
+</tr>
+</table>
+
+<p>The sections below provide more information about the new screen qualifiers
+and manifest attributes. For complete information about how to use the screen
+support API, see <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
+
+<h4>New resource qualifiers for screens support</h4>
+
+<p>The new resource qualifiers in Android 3.2 let you better target your layouts
+for ranges of screen sizes. Using the qualifiers, you can create resource
+configurations designed for a specific minimum smallestWidth, current width, or
+current height, measured in density-independent pixels.</p>
+
+<p>The new qualifiers are:</p>
+<ul>
+<li><code>swNNNdp</code> &mdash; Specifies the minimum smallestWidth on which
+the resource should be used, measured in "dp" units. As mentioned above, a
+screen's smallestWidth is constant, regardless of orientation. Examples:
+<code>sw320dp</code>, <code>sw720dp</code>, <code>sw720dp</code>.</li>
+
+<li><code>wNNNdp</code> and <code>hNNNdp</code> &mdash; Specifies the minimum 
+width or height on which the resource should be used, measured in "dp" units. As
+mentioned above, a screen's width and height are relative to the orientation of
+the screen and change whenever the orientation changes. Examples:
+<code>w320dp</code>, <code>w720dp</code>, <code>h1024dp</code>.</p></li>
+</ul>
+
+<p>You can also create multiple overlapping resource configurations if needed.
+For example, you could tag some resources for use on any screen wider than 480
+dp, others for wider than 600  dp, and others for wider than 720 dp. When
+multiple resource configurations are qualified for a given screen, the system
+selects the configuration that is the closest match. For precise control over
+which resources are loaded on a given screen, you can tag resources with one
+qualifier or combine several new or existing qualifiers. 
+
+<p>Based on the typical dimensions listed earlier, here are some examples of how
+you could use the new qualifiers:</p>
+
+<pre class="classic prettyprint">res/layout/main_activity.xml   # For phones
+res/layout-sw600dp/main_activity.xml   # For 7” tablets
+res/layout-sw720dp/main_activity.xml   # For 10” tablets
+res/layout-w600dp/main_activity.xml   # Multi-pane when enough width
+res/layout-sw600dp-w720dp/main_activity.xml   # For large width</pre>
+
+<p>Older versions of the platform will ignore the new qualifiers, so you can
+mix them as needed to ensure that your app looks great on any device. Here
+are some examples:</p>
+
+<pre class="classic prettyprint">res/layout/main_activity.xml   # For phones
+res/layout-xlarge/main_activity.xml   # For pre-3.2 tablets
+res/layout-sw600dp/main_activity.xml   # For 3.2 and up tablets</pre>
+
+<p>For complete information about how to use the new qualifiers, see <a href="{@docRoot}guide/practices/screens_support.html#NewQualifiers">Using new
+size qualifiers</a>.</p>
+
+<h4>New manifest attributes for screen-size compatibility</h4>
+
+<p>The framework offers a new set of <a
+href="{@docRoot}"><code>&lt;supports-screens&gt;</code></a> manifest attributes that let
+you manage your app's support for different screen sizess.
+Specifically, you can specify the largest and smallest screens on which your app
+is designed to run, as well as the largest screen on which it is designed run
+without needing the system's new <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen
+compatibility mode</a>. Like the resource qualifiers described above, the new
+manifest attributes specify the range of screens that the application supports,
+as specified by the smallestWidth. </p>
+
+<p>The new manifest attributes for screen support are: </p>
+
+<ul>
+<li><code>android:compatibleWidthLimitDp="<em>numDp"</em></code> &mdash; This
+attribute lets you specify the maximum smallestWidth on which the application
+can run without needing compatibility mode. If the current screen is larger than
+the value specified, the system displays the application in normal mode but
+allows the user to optionally switch to compatibility mode through a setting in
+the system bar.</li>
+
+<li><code>android:largestWidthLimitDp="<em>numDp</em>"</code> &mdash; This
+attribute lets you specify the maximum smallestWidth on which the application
+is designed to run.  If the current screen is larger than the value specified,
+the system forces the application into screen compatibility mode, to ensure best
+display on the current screen.</li>
+
+<li><code>android:smallestWidthLimitDp="<em>numDp"</em></code> &mdash; This
+attribute lets you specify the minimum smallestWidth on which the application
+can run. If the current screen is smaller than the value specified, the system
+considers the application incompatible with the device, but does not prevent it
+from being installed and run.</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Android Market does not currently filter
+apps based on any of the attributes above. Support for filtering will be
+added in a later platform release. Applications that require
+filtering based on screen size can use the existing <code>&lt;supports-screens&gt;</code>
+attributes.</p>
+
+<p>For complete information about how to use the new attributes, see <a href="{@docRoot}guide/practices/screens_support.html#DeclaringScreenSizeSupport">Declaring
+screen size support</a>.</p>
+
+<h4>Screen compatibility mode</h4>
+
+<p>Android 3.2 provides a new screen compatibility mode for applications
+explicitly declaring that they do not support screens as large as the one on
+which they are running. This new "zoom" mode is a pixel-scaled &mdash; it
+renders the application in a smaller screen area and then scales the pixels to
+fill the current screen.</p>
+
+<p>By default, the system offers screen compatibility mode as an user option, for apps
+that require it. Users can turn the zoom mode on and off using a control available
+in the system bar. </p>
+
+<p>Because the new screen compatibility mode may not be appropriate for all
+applications, the platform allows the application to disable it using manifest
+attributes. When disabled by the app, the system does not offer "zoom" compatibility
+mode as an option for users when the app is running.</p>
+
+<p class="note"><strong>Note:</strong> For important information about how
+to control compatibility mode in your applications, please review the <a
+href="http://android-developers.blogspot.com/2011/07/new-mode-for-apps-on-large-
+screens.html">New Mode for Apps on Large Screens</a> article on the Android
+Developers Blog. </p>
+
+<h4>New screen density for 720p televisions and similar devices</h4>
+
+<p>To meet the needs of applications running on 720p televisions or similar with
+moderate density screens, Android 3.2 introduces a new generalized density,
+<code>tvdpi</code>, with an approximate dpi of 213. Applications can query for
+the new density in {@link android.util.DisplayMetrics#densityDpi} and can use
+the new <code>tvdpi</code> qualifier to tag resources for televisions and
+similar devices. For example:</p>
+
+<pre class="classic prettyprint">res/drawable-tvdpi/my_icon.png   # Bitmap for tv density</pre>
+
+<p>In general, applications should not need to work with this density. For situations
+where output is needed for a 720p screen, the UI elements can be scaled
+automatically by the platform.</p>
+
+
+<h3 id="ui" style="margin-top:1.25em;">UI framework</h3>
+<ul>
+<li>Fragments
+  <ul>
+    <li>New {@link android.app.Fragment.SavedState} class holds the state
+    information retrieved from a fragment instance through
+    {@link android.app.FragmentManager#saveFragmentInstanceState(android.app.Fragment) saveFragmentInstanceState()}.</li>
+    <li>New method {@link android.app.FragmentManager#saveFragmentInstanceState(android.app.Fragment) saveFragmentInstanceState()}
+    saves the current instance state of
+    the given Fragment. The state can be used later when creating a new instance
+    of the Fragment that matches the current state.</li>
+    <li>New method {@link android.app.Fragment#setInitialSavedState(SavedState) setInitialSavedState()}
+    sets the initial saved state for a Fragment when first constructed.</li>
+    <li>New {@link android.app.Fragment#onViewCreated(android.view.View, android.os.Bundle)
+    onViewCreated()} callback method notifies the Fragment that
+    {@link android.app.Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle) onCreateView()}
+    has returned, but before any saved state has been restored in to the View.</li>
+    <li>{@link android.app.Fragment#isDetached()} method determines whether
+    the Fragment has been explicitly detached from the UI.</li>
+    <li>New {@link android.app.FragmentTransaction#attach(android.app.Fragment) attach()}
+    and {@link android.app.FragmentTransaction#detach(android.app.Fragment) detach()}
+    methods let an application re-attach or detach fragments in the UI.</li>
+    <li>A new {@link android.app.FragmentTransaction#setCustomAnimations(int, int, int, int)
+    setCustomAnimations()} overload method lets you set specific animation
+    resources to run for enter/exit operations and specifically when
+    popping the back stack. The existing implementation does not account
+    for the different behavior of fragments when popping the back stack.</li>
+  </ul>
+</li>
+<li>Screen size information in ActivityInfo and ApplicationInfo
+  <ul>
+    <li>{@link android.content.pm.ActivityInfo} adds {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE}
+    and {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE} as bit masks
+    in {@link android.R.attr#configChanges}. The bits indicate whether an Activity can
+    itself handle the screen size and smallest screen size.</li>
+    <li>{@link android.content.pm.ApplicationInfo} adds
+    {@link android.content.pm.ApplicationInfo#largestWidthLimitDp}, {@link android.content.pm.ApplicationInfo#compatibleWidthLimitDp},
+    and {@link android.content.pm.ApplicationInfo#requiresSmallestWidthDp} fields,
+    derived from the corresponding <code>&lt;supports-screens&gt;</code> attributes
+    in the application manifest file.</li>
+  </ul>
+</li>
+<li>Helpers for getting display size from WindowManager
+  <ul>
+    <li>New methods {@link android.view.Display#getSize(android.graphics.Point)
+    getSize()} and {@link android.view.Display#getRectSize(android.graphics.Rect)
+    getRectSize()} let applications get the raw size of the display.</li>
+  </ul>
+</li>
+<li>New public "holographic" styles
+  <ul>
+    <li>The platform now exposes a variety of public "holographic" styles
+    for text, actionbar widgets and tabs, and more. See
+    {@link android.R.style} for a full list.</li>
+  </ul>
+</li>
+<li>{@link android.app.LocalActivityManager}, {@link android.app.ActivityGroup}, and
+    {@link android.app.LocalActivityManager} are now deprecated
+  <ul>
+    <li>New applications should use Fragments instead of these classes. To
+    continue to run on older versions of the platform, you can use the v4 Support
+    Library (compatibility library), available in the Android SDK. The v4 Support
+    Library provides a version of the Fragment API that is compatible down to
+    Android 1.6 (API level 4).
+    <li>For apps developing against Android 3.0 (API level
+    11) or higher, tabs are typically presented in the UI using the new
+    {@link android.app.ActionBar#newTab() ActionBar.newTab()} and related APIs
+    for placing tabs within their action bar area.</p></li>
+  </ul>
+</li>
+</ul>
+
+<h3 id="media" style="margin-top:1em;">Media framework</h3>
+<ul>
+    <li>Applications that use the platform's media provider ({@link
+    android.provider.MediaStore}) can now read media data directly from the
+    removeable SD card, where supported by the device. Applications can also
+    interact with the SD card files directly, using the MTP API. </li>
+
+</ul>
+<h3 id="graphics" style="margin-top:1.25em;">Graphics</h3>
+<ul>
+<li>Parcelable utilities in Point and PointF
+  <ul>
+    <li>{@link android.graphics.Point} and {@link android.graphics.PointF}
+    classes now include the {@link android.os.Parcelable} interface and utility methods {@link
+    android.graphics.Point#describeContents()}, {@link
+    android.graphics.Point#readFromParcel(android.os.Parcel) readFromParcel()}, and {@link
+    android.graphics.Point#writeToParcel(android.os.Parcel, int) writeToParcel()}.</li>
+  </ul>
+</li>
+</ul>
+
+
+<h3 id="ime" style="margin-top:1.25em;">IME framework</h3>
+<ul>
+    <li>New {@link android.view.KeyEvent#getModifiers()} method for
+    retrieving the current state of the modifier keys.</li>
+</ul>
+
+
+<h3 id="usb" style="margin-top:1.25em;">USB framework</h3>
+<ul>
+    <li>New {@link
+    android.hardware.usb.UsbDeviceConnection#getRawDescriptors()} method for
+    retrieving the raw USB descriptors for the device. You can use the
+    method to access descriptors not supported directly via the higher
+    level APIs.</li>
+</ul>
+
+
+<h3 id="network" style="margin-top:1.25em;">Network</h3>
+<ul>
+<li>Network type constants
+   <ul>
+     <li>{@link android.net.ConnectivityManager} adds the constants {@link
+     android.net.ConnectivityManager#TYPE_ETHERNET} and {@link
+     android.net.ConnectivityManager#TYPE_BLUETOOTH}.</li>
+  </ul>
+</li>
+</ul>
+
+
+<h3 id="telephony" style="margin-top:1.25em;">Telephony</h3>
+<ul>
+    <li>New {@link android.telephony.TelephonyManager#NETWORK_TYPE_HSPAP} network type constant.</li>
+</ul>
+
+<h3 id="other" style="margin-top:1.25em;">Core utilities</h3>
+<ul>
+<li>Parcelable utilities
+  <ul>
+    <li>New interface {@link android.os.Parcelable.ClassLoaderCreator} allows
+    the application to receive the ClassLoader in which the object is being created.</li>
+    <li>New {@link android.os.ParcelFileDescriptor#adoptFd(int) adoptFd}, {@link
+    android.os.ParcelFileDescriptor#dup(java.io.FileDescriptor) dup()}, and {@link
+    android.os.ParcelFileDescriptor#fromFd(int) fromFd()} for managing
+    {@link android.os.ParcelFileDescriptor} objects.</li>
+  </ul>
+</li>
+<li>Binder and IBinder
+  <ul>
+    <li>New method {@link android.os.Binder#dumpAsync(java.io.FileDescriptor, java.lang.String[]) dumpAsync()}
+    in {@link android.os.Binder} and {@link android.os.IBinder} let applications
+    dump to a specified file, ensuring that the target executes asynchronously.</li>
+    <li>New {@link android.os.IBinder} protocol transaction code {@link
+    android.os.IBinder#TWEET_TRANSACTION} lets applications send a tweet
+    to the target object.</li>
+  </ul>
+</li>
+</ul>
+
+
+
+
+<h3 id="features">New feature constants</h3>
+
+<p>The platform adds new hardware feature constants that you can declare
+in their application manifests, to inform external entities such as Android
+Market of required hardware and software capabilities. You declare these
+and other feature constants in <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
+&lt;uses-feature&gt;}</a> manifest elements.
+
+<p>Android Market filters applications based on their <code>&lt;uses-feature&gt;</code> attributes, to ensure that they are available only to devices on which their requirements are met. </p>
+
+<ul>
+<li>Feature constants for landscape or portrait requirements
+
+<p>Android 3.2 introduces new feature constants that let applications specify whether they require display in landscape orientation, portrait orientation, or both. Declaring these constants indicates that the application must not be installed on a device that doesn't offer the associated orientation. Conversely, if one or both of the constants are not declared, it indicates that the application does not have a preference for the undeclared orientations and may be installed on a device that doesn't offer them. </p>
+
+<ul>
+  <li>{@link android.content.pm.PackageManager#FEATURE_SCREEN_LANDSCAPE
+android.hardware.screen.landscape} &mdash; The application requires display in
+landscape orientation.</li>
+  <li>{@link android.content.pm.PackageManager#FEATURE_SCREEN_PORTRAIT
+android.hardware.screen.portrait} &mdash; The application requires display in
+portrait orientation.</li>
+</ul>
+
+<p>A typical application that functions properly in both landscape and portrait orientations would not normally need to declare an orientation requirement. Rather, an application designed primarily for one orientation, such as an app designed for a television, could declare one of the constants to ensure that it isn't available to devices that don't provide that orientation.</p>
+
+<p>If the application is targeting API level 12 or lower, the platform assumes that if app has not specified whether it requires portrait or landscape, both orientations are required.</p>
+</li>
+<li>Other feature constants
+
+<ul>
+  <li>{@link android.content.pm.PackageManager#FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT
+android.hardware.faketouch.multitouch.distinct} &mdash; The application requires support for emulated mulitouch input with distinct tracking of two or more points.</li>
+
+  <li>{@link android.content.pm.PackageManager#FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND
+android.hardware.faketouch.multitouch.jazzhand} &mdash; The application requires support for emulated mulitouch input with distinct tracking of five or more points.</li>
+</ul>
+
+</li>
+</ul>
+
+
+<h3 id="api-diff">API Differences Report</h3>
+
+<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API
+Level
+{@sdkPlatformApiLevel}), see the <a
+href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API
+Differences Report</a>.</p>
+
+
+
+
+
+<h2 id="api-level">API Level</h2>
+
+<p>The Android {@sdkPlatformVersion} platform delivers an updated version of
+the framework API. The Android {@sdkPlatformVersion} API
+is assigned an integer identifier &mdash;
+<strong>{@sdkPlatformApiLevel}</strong> &mdash; that is
+stored in the system itself. This identifier, called the "API Level", allows the
+system to correctly determine whether an application is compatible with
+the system, prior to installing the application. </p>
+
+<p>To use APIs introduced in Android {@sdkPlatformVersion} in your application,
+you need compile the application against the Android library that is provided in
+the Android {@sdkPlatformVersion} SDK platform. Depending on your needs, you
+might
+also need to add an <code>android:minSdkVersion="{@sdkPlatformApiLevel}"</code>
+attribute to the <code>&lt;uses-sdk&gt;</code> element in the application's
+manifest.</p>
+
+<p>For more information about how to use API Level, see the <a
+href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p>
+
+
+<h2 id="apps">Built-in Applications</h2>
+
+<p>The system image included in the downloadable platform provides these
+built-in applications:</p>
+
+<table style="border:0;padding-bottom:0;margin-bottom:0;">
+<tr>
+<td style="border:0;padding-bottom:0;margin-bottom:0;">
+<ul>
+<li>API Demos</li>
+<li>Browser</li>
+<li>Calculator</li>
+<li>Camera</li>
+<li>Clock</li>
+<li>Contacts</li>
+<li>Custom Locale</li>
+<li>Dev Tools</li>
+<li>Downloads</li>
+<li>Email</li>
+</ul>
+</td>
+<td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;">
+<ul>
+<li>Gallery</li>
+<li>Gestures Builder</li>
+<li>Messaging</li>
+<li>Music</li>
+<li>Search</li>
+<li>Settings</li>
+<li>Spare Parts</li>
+<li>Speech Recorder</li>
+<li>Widget Preview</li>
+</ul>
+</td>
+</tr>
+</table>
+
+
+<h2 id="locs" style="margin-top:.75em;">Locales</h2>
+
+<p>The system image included in the downloadable SDK platform provides a variety
+of
+built-in locales. In some cases, region-specific strings are available for the
+locales. In other cases, a default version of the language is used. The
+languages that are available in the Android 3.0 system
+image are listed below (with <em>language</em>_<em>country/region</em> locale
+descriptor).</p>
+
+<table style="border:0;padding-bottom:0;margin-bottom:0;">
+<tr>
+<td style="border:0;padding-bottom:0;margin-bottom:0;">
+<ul>
+<li>Arabic, Egypt (ar_EG)</li>
+<li>Arabic, Israel (ar_IL)</li>
+<li>Bulgarian, Bulgaria (bg_BG)</li>
+<li>Catalan, Spain (ca_ES)</li>
+<li>Czech, Czech Republic (cs_CZ)</li>
+<li>Danish, Denmark(da_DK)</li>
+<li>German, Austria (de_AT)</li>
+<li>German, Switzerland (de_CH)</li>
+<li>German, Germany (de_DE)</li>
+<li>German, Liechtenstein (de_LI)</li>
+<li>Greek, Greece (el_GR)</li>
+<li>English, Australia (en_AU)</li>
+<li>English, Canada (en_CA)</li>
+<li>English, Britain (en_GB)</li>
+<li>English, Ireland (en_IE)</li>
+<li>English, India (en_IN)</li>
+<li>English, New Zealand (en_NZ)</li>
+<li>English, Singapore(en_SG)</li>
+<li>English, US (en_US)</li>
+<li>English, Zimbabwe (en_ZA)</li>
+<li>Spanish (es_ES)</li>
+<li>Spanish, US (es_US)</li>
+<li>Finnish, Finland (fi_FI)</li>
+<li>French, Belgium (fr_BE)</li>
+<li>French, Canada (fr_CA)</li>
+<li>French, Switzerland (fr_CH)</li>
+<li>French, France (fr_FR)</li>
+<li>Hebrew, Israel (he_IL)</li>
+<li>Hindi, India (hi_IN)</li>
+</ul>
+</td>
+<td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;">
+<li>Croatian, Croatia (hr_HR)</li>
+<li>Hungarian, Hungary (hu_HU)</li>
+<li>Indonesian, Indonesia (id_ID)</li>
+<li>Italian, Switzerland (it_CH)</li>
+<li>Italian, Italy (it_IT)</li>
+<li>Japanese (ja_JP)</li>
+<li>Korean (ko_KR)</li>
+<li>Lithuanian, Lithuania (lt_LT)</li>
+<li>Latvian, Latvia (lv_LV)</li>
+<li>Norwegian bokmål, Norway (nb_NO)</li>
+<li>Dutch, Belgium (nl_BE)</li>
+<li>Dutch, Netherlands (nl_NL)</li>
+<li>Polish (pl_PL)</li>
+<li>Portuguese, Brazil (pt_BR)</li>
+<li>Portuguese, Portugal (pt_PT)</li>
+<li>Romanian, Romania (ro_RO)</li>
+<li>Russian (ru_RU)</li></li>
+<li>Slovak, Slovakia (sk_SK)</li>
+<li>Slovenian, Slovenia (sl_SI)</li>
+<li>Serbian (sr_RS)</li>
+<li>Swedish, Sweden (sv_SE)</li>
+<li>Thai, Thailand (th_TH)</li>
+<li>Tagalog, Philippines (tl_PH)</li>
+<li>Turkish, Turkey (tr_TR)</li>
+<li>Ukrainian, Ukraine (uk_UA)</li>
+<li>Vietnamese, Vietnam (vi_VN)</li>
+<li>Chinese, PRC (zh_CN)</li>
+<li>Chinese, Taiwan (zh_TW)</li>
+</td>
+</tr>
+</table>
+
+<p class="note"><strong>Note:</strong> The Android platform may support more
+locales than are included in the SDK system image. All of the supported locales
+are available in the <a href="http://source.android.com/">Android Open Source
+Project</a>.</p>
+
+<h2 id="skins">Emulator Skins</h2>
+
+<p>The downloadable platform includes the following emulator skin:</p>
+
+<ul>
+  <li>
+    WXGA (1280x800, medium density, xlarge screen)
+  </li>
+</ul>
+
+<p>For more information about how to develop an application that displays
+and functions properly on all Android-powered devices, see <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
diff --git a/docs/html/sdk/api_diff/13/changes.html b/docs/html/sdk/api_diff/13/changes.html
new file mode 100644
index 0000000..0a25fca
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Wed Jun 29 10:50:35 PDT 2011 -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+API Differences between 12 and 13
+</TITLE>
+<link href="../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</head>
+<frameset cols="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> 
+<frameset rows="174,**" framespacing="1" frameborder="yes"  border="1" bordercolor="#e9e9e9">
+    <frame src="changes/jdiff_topleftframe.html" scrolling="no" name="topleftframe" frameborder="1">
+    <frame src="changes/alldiffs_index_all.html" scrolling="auto" name="bottomleftframe" frameborder="1">
+  </frameset>
+  <frame src="changes/changes-summary.html" scrolling="auto" name="rightframe" frameborder="1">
+</frameset>
+<noframes>
+<h2>
+Frame Alert
+</h2>
+
+<p>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<br>
+Link to <a href="changes/changes-summary.html" target="_top">Non-frame version.</A>
+</noframes>
+</html>
diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html
new file mode 100644
index 0000000..1d53429
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html
@@ -0,0 +1,663 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<b>Additions</b>
+  <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<!-- Method adoptFd -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method attach -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Field compatibleWidthLimitDp -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>compatibleWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field compatibleWidthLimitDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Field CONFIG_SCREEN_SIZE -->
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A>
+</nobr><br>
+<!-- Field CONFIG_SMALLEST_SCREEN_SIZE -->
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A>
+</nobr><br>
+<!-- Field CREATOR -->
+<i>CREATOR</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A>
+</nobr><br>
+<!-- Field CREATOR -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A>
+</nobr><br>
+<!-- Field DENSITY_TV -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A>
+</nobr><br>
+<!-- Method describeContents -->
+<i>describeContents</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method describeContents -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<!-- Method detach -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Method dumpAsync -->
+<i>dumpAsync</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.Binder
+</A></nobr><br>
+<!-- Method dumpAsync -->
+&nbsp;&nbsp;<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.IBinder
+</A></nobr><br>
+<!-- Method dup -->
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b>
+(<code>FileDescriptor</code>)</A></nobr><br>
+<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A>
+</nobr><br>
+<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A>
+</nobr><br>
+<!-- Field FEATURE_SCREEN_LANDSCAPE -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A>
+</nobr><br>
+<!-- Field FEATURE_SCREEN_PORTRAIT -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A>
+</nobr><br>
+<!-- Class Fragment.SavedState -->
+<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br>
+<!-- Method fromFd -->
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method getModifiers -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b>
+()</A></nobr><br>
+<!-- Method getRawDescriptors -->
+<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b>
+()</A></nobr><br>
+<!-- Method getRectSize -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b>
+(<code>Rect</code>)</A></nobr><br>
+<!-- Method getSize -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b>
+(<code>Point</code>)</A></nobr><br>
+<!-- Field HONEYCOMB_MR2 -->
+<A NAME="H"></A>
+<br><font size="+2">H</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A>
+</nobr><br>
+<!-- Method isDetached -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b>
+()</A></nobr><br>
+<!-- Field largestWidthLimitDp -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>largestWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field largestWidthLimitDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Field NETWORK_TYPE_HSPAP -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A>
+</nobr><br>
+<!-- Method onViewCreated -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b>
+(<code>View, Bundle</code>)</A></nobr><br>
+<!-- Class Parcelable.ClassLoaderCreator -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br>
+<!-- Method readFromParcel -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>readFromParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method readFromParcel -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<!-- Field requiresSmallestWidthDp -->
+<i>requiresSmallestWidthDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field requiresSmallestWidthDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Method saveFragmentInstanceState -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Field SCREEN_HEIGHT_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field SCREEN_WIDTH_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field screenHeightDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A>
+</nobr><br>
+<!-- Field screenWidthDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A>
+</nobr><br>
+<!-- Field SET_POINTER_SPEED -->
+<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A>
+</nobr><br>
+<!-- Method setCustomAnimations -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b>
+(<code>int, int, int, int</code>)</A></nobr><br>
+<!-- Method setInitialSavedState -->
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b>
+(<code>SavedState</code>)</A></nobr><br>
+<!-- Field SMALLEST_SCREEN_WIDTH_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field smallestScreenWidthDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo -->
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_DialogWindowTitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Large -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Large_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Medium -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Medium_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_SearchResult_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_SearchResult_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Small -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Small_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionBar_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionBar_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionMode_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionMode_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_Button -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_DropDownHint -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_DropDownItem -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_EditText -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_IconMenu_Item -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu_Large -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu_Small -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TabWidget -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView_PopupMenu -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView_SpinnerItem -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_WindowTitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A>
+</nobr><br>
+<!-- Field Theme_Holo_Light_NoActionBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A>
+</nobr><br>
+<!-- Field Theme_Holo_Light_NoActionBar_Fullscreen -->
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A>
+</nobr><br>
+<!-- Field TWEET_TRANSACTION -->
+<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A>
+</nobr><br>
+<!-- Field TYPE_BLUETOOTH -->
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A>
+</nobr><br>
+<!-- Field TYPE_ETHERNET -->
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A>
+</nobr><br>
+<!-- Field UI_MODE_TYPE_TELEVISION -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A>
+</nobr><br>
+<!-- Field Widget_ActionBar_TabBar -->
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A>
+</nobr><br>
+<!-- Method writeToParcel -->
+<i>writeToParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method writeToParcel -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html
new file mode 100644
index 0000000..a4e428e
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html
@@ -0,0 +1,941 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>All Differences</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class Activity -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br>
+<!-- Class ActivityGroup -->
+<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br>
+<!-- Class ActivityInfo -->
+<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br>
+<!-- Method adoptFd -->
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Package android -->
+<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br>
+<!-- Package android.app -->
+<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br>
+<!-- Package android.content.pm -->
+<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br>
+<!-- Package android.content.res -->
+<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br>
+<!-- Package android.graphics -->
+<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br>
+<!-- Package android.hardware.usb -->
+<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br>
+<!-- Package android.net -->
+<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br>
+<!-- Package android.os -->
+<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br>
+<!-- Package android.telephony -->
+<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br>
+<!-- Package android.util -->
+<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br>
+<!-- Package android.view -->
+<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br>
+<!-- Class ApplicationInfo -->
+<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br>
+<!-- Method attach -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Class Binder -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br>
+<!-- Class Build.VERSION_CODES -->
+<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br>
+<!-- Field compatibleWidthLimitDp -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>compatibleWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field compatibleWidthLimitDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Field CONFIG_SCREEN_SIZE -->
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A>
+</nobr><br>
+<!-- Field CONFIG_SMALLEST_SCREEN_SIZE -->
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A>
+</nobr><br>
+<!-- Class Configuration -->
+<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br>
+<!-- Class ConnectivityManager -->
+<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br>
+<!-- Field CREATOR -->
+<i>CREATOR</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A>
+</nobr><br>
+<!-- Field CREATOR -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A>
+</nobr><br>
+<!-- Field DENSITY_TV -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A>
+</nobr><br>
+<!-- Method describeContents -->
+<i>describeContents</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method describeContents -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<!-- Method detach -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Method dismissDialog -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog
+(<code>int</code>)</A></nobr><br>
+<!-- Class Display -->
+<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br>
+<!-- Class DisplayMetrics -->
+<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br>
+<!-- Method dumpAsync -->
+<i>dumpAsync</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.Binder
+</A></nobr><br>
+<!-- Method dumpAsync -->
+&nbsp;&nbsp;<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.IBinder
+</A></nobr><br>
+<!-- Method dup -->
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b>
+(<code>FileDescriptor</code>)</A></nobr><br>
+<!-- Method exitKeyguardSecurely -->
+<A NAME="E"></A>
+<br><font size="+2">E</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely
+(<code>OnKeyguardExitResult</code>)</A></nobr><br>
+<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A>
+</nobr><br>
+<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A>
+</nobr><br>
+<!-- Field FEATURE_SCREEN_LANDSCAPE -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A>
+</nobr><br>
+<!-- Field FEATURE_SCREEN_PORTRAIT -->
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A>
+</nobr><br>
+<!-- Class Fragment -->
+<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<!-- Class Fragment.SavedState -->
+<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br>
+<!-- Class FragmentManager -->
+<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<!-- Class FragmentTransaction -->
+<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<!-- Method fromFd -->
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method getHeight -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight
+()</A></nobr><br>
+<!-- Method getLastNonConfigurationInstance -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance
+()</A></nobr><br>
+<!-- Method getModifiers -->
+<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b>
+()</A></nobr><br>
+<!-- Method getRawDescriptors -->
+<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b>
+()</A></nobr><br>
+<!-- Method getRectSize -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b>
+(<code>Rect</code>)</A></nobr><br>
+<!-- Method getSize -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b>
+(<code>Point</code>)</A></nobr><br>
+<!-- Method getWidth -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth
+()</A></nobr><br>
+<!-- Field HONEYCOMB_MR2 -->
+<A NAME="H"></A>
+<br><font size="+2">H</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A>
+</nobr><br>
+<!-- Class IBinder -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br>
+<!-- Method isDetached -->
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b>
+()</A></nobr><br>
+<!-- Class KeyEvent -->
+<A NAME="K"></A>
+<br><font size="+2">K</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br>
+<!-- Class KeyguardManager -->
+<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br>
+<!-- Class KeyguardManager.KeyguardLock -->
+<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br>
+<!-- Field largestWidthLimitDp -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>largestWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field largestWidthLimitDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Class LocalActivityManager -->
+<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br>
+<!-- Class Manifest.permission -->
+<A NAME="M"></A>
+<br><font size="+2">M</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br>
+<!-- Field NETWORK_TYPE_HSPAP -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A>
+</nobr><br>
+<!-- Method newKeyguardLock -->
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock
+(<code>String</code>)</A></nobr><br>
+<!-- Method onCreateDialog -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog
+(<code>int, Bundle</code>)</A></nobr><br>
+<!-- Method onPrepareDialog -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog
+(<code>int, Dialog, Bundle</code>)</A></nobr><br>
+<!-- Method onRetainNonConfigurationInstance -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance
+()</A></nobr><br>
+<!-- Method onViewCreated -->
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b>
+(<code>View, Bundle</code>)</A></nobr><br>
+<!-- Class PackageManager -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br>
+<!-- Class Parcelable.ClassLoaderCreator -->
+<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br>
+<!-- Class ParcelFileDescriptor -->
+<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br>
+<!-- Class Point -->
+<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br>
+<!-- Class PointF -->
+<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br>
+<!-- Class PowerManager -->
+<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br>
+<!-- Class R.attr -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br>
+<!-- Class R.style -->
+<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br>
+<!-- Method readFromParcel -->
+<i>readFromParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method readFromParcel -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<!-- Method removeDialog -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog
+(<code>int</code>)</A></nobr><br>
+<!-- Field requiresSmallestWidthDp -->
+<i>requiresSmallestWidthDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<!-- Field requiresSmallestWidthDp -->
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<!-- Method saveFragmentInstanceState -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b>
+(<code>Fragment</code>)</A></nobr><br>
+<!-- Field SCREEN_BRIGHT_WAKE_LOCK -->
+<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A>
+</nobr><br>
+<!-- Field SCREEN_HEIGHT_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field SCREEN_WIDTH_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field screenHeightDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A>
+</nobr><br>
+<!-- Field screenWidthDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A>
+</nobr><br>
+<!-- Field SET_POINTER_SPEED -->
+<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A>
+</nobr><br>
+<!-- Method setCustomAnimations -->
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b>
+(<code>int, int, int, int</code>)</A></nobr><br>
+<!-- Method setInitialSavedState -->
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b>
+(<code>SavedState</code>)</A></nobr><br>
+<!-- Method showDialog -->
+<i>showDialog</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int, Bundle</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<!-- Method showDialog -->
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<!-- Field SMALLEST_SCREEN_WIDTH_DP_UNDEFINED -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<!-- Field smallestScreenWidthDp -->
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A>
+</nobr><br>
+<!-- Class TabActivity -->
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br>
+<!-- Class TelephonyManager -->
+<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br>
+<!-- Field TextAppearance_Holo -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_DialogWindowTitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Large -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Large_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Medium -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Medium_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_SearchResult_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_SearchResult_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Small -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Small_Inverse -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionBar_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionBar_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionMode_Subtitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_ActionMode_Title -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_Button -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_DropDownHint -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_DropDownItem -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_EditText -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_IconMenu_Item -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu_Large -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_PopupMenu_Small -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TabWidget -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView_PopupMenu -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_Widget_TextView_SpinnerItem -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A>
+</nobr><br>
+<!-- Field TextAppearance_Holo_WindowTitle -->
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A>
+</nobr><br>
+<!-- Field Theme_Holo_Light_NoActionBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A>
+</nobr><br>
+<!-- Field Theme_Holo_Light_NoActionBar_Fullscreen -->
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A>
+</nobr><br>
+<!-- Field TWEET_TRANSACTION -->
+<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A>
+</nobr><br>
+<!-- Field TYPE_BLUETOOTH -->
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A>
+</nobr><br>
+<!-- Field TYPE_ETHERNET -->
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A>
+</nobr><br>
+<!-- Field UI_MODE_TYPE_TELEVISION -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A>
+</nobr><br>
+<!-- Class UsbDeviceConnection -->
+<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br>
+<!-- Field Widget_ActionBar_TabBar -->
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_Holo_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabBar -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabText -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A>
+</nobr><br>
+<!-- Field Widget_Holo_Light_ActionBar_TabView -->
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A>
+</nobr><br>
+<!-- Method writeToParcel -->
+<i>writeToParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+<!-- Method writeToParcel -->
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html
new file mode 100644
index 0000000..59e766b
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html
@@ -0,0 +1,561 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<b>Changes</b>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class Activity -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br>
+<!-- Class ActivityGroup -->
+<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br>
+<!-- Class ActivityInfo -->
+<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br>
+<!-- Package android -->
+<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br>
+<!-- Package android.app -->
+<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br>
+<!-- Package android.content.pm -->
+<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br>
+<!-- Package android.content.res -->
+<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br>
+<!-- Package android.graphics -->
+<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br>
+<!-- Package android.hardware.usb -->
+<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br>
+<!-- Package android.net -->
+<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br>
+<!-- Package android.os -->
+<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br>
+<!-- Package android.telephony -->
+<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br>
+<!-- Package android.util -->
+<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br>
+<!-- Package android.view -->
+<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br>
+<!-- Class ApplicationInfo -->
+<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br>
+<!-- Class Binder -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br>
+<!-- Class Build.VERSION_CODES -->
+<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br>
+<!-- Class Configuration -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br>
+<!-- Class ConnectivityManager -->
+<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br>
+<!-- Method dismissDialog -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog
+(<code>int</code>)</A></nobr><br>
+<!-- Class Display -->
+<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br>
+<!-- Class DisplayMetrics -->
+<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br>
+<!-- Method exitKeyguardSecurely -->
+<A NAME="E"></A>
+<br><font size="+2">E</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely
+(<code>OnKeyguardExitResult</code>)</A></nobr><br>
+<!-- Class Fragment -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<!-- Class FragmentManager -->
+<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<!-- Class FragmentTransaction -->
+<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<!-- Method getHeight -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight
+()</A></nobr><br>
+<!-- Method getLastNonConfigurationInstance -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance
+()</A></nobr><br>
+<!-- Method getWidth -->
+<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth
+()</A></nobr><br>
+<!-- Class IBinder -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br>
+<!-- Class KeyEvent -->
+<A NAME="K"></A>
+<br><font size="+2">K</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br>
+<!-- Class KeyguardManager -->
+<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br>
+<!-- Class KeyguardManager.KeyguardLock -->
+<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br>
+<!-- Class LocalActivityManager -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br>
+<!-- Class Manifest.permission -->
+<A NAME="M"></A>
+<br><font size="+2">M</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br>
+<!-- Method newKeyguardLock -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock
+(<code>String</code>)</A></nobr><br>
+<!-- Method onCreateDialog -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog
+(<code>int, Bundle</code>)</A></nobr><br>
+<!-- Method onPrepareDialog -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog
+(<code>int, Dialog, Bundle</code>)</A></nobr><br>
+<!-- Method onRetainNonConfigurationInstance -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance
+()</A></nobr><br>
+<!-- Class PackageManager -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br>
+<!-- Class ParcelFileDescriptor -->
+<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br>
+<!-- Class Point -->
+<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br>
+<!-- Class PointF -->
+<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br>
+<!-- Class PowerManager -->
+<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br>
+<!-- Class R.attr -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br>
+<!-- Class R.style -->
+<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br>
+<!-- Method removeDialog -->
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog
+(<code>int</code>)</A></nobr><br>
+<!-- Field SCREEN_BRIGHT_WAKE_LOCK -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A>
+</nobr><br>
+<!-- Method showDialog -->
+<i>showDialog</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int, Bundle</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<!-- Method showDialog -->
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<!-- Class TabActivity -->
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br>
+<!-- Class TelephonyManager -->
+<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br>
+<!-- Class UsbDeviceConnection -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html
new file mode 100644
index 0000000..68d2c20
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html b/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html
new file mode 100644
index 0000000..5d3cbda
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.Manifest.permission
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.<A HREF="../../../../reference/android/Manifest.permission.html" target="_top"><font size="+2"><code>Manifest.permission</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.Manifest.permission.SET_POINTER_SPEED"></A>
+  <nobr><code>String</code>&nbsp;<A HREF="../../../../reference/android/Manifest.permission.html#SET_POINTER_SPEED" target="_top"><code>SET_POINTER_SPEED</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.R.attr.html b/docs/html/sdk/api_diff/13/changes/android.R.attr.html
new file mode 100644
index 0000000..f8eb54b
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.R.attr.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.R.attr
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.<A HREF="../../../../reference/android/R.attr.html" target="_top"><font size="+2"><code>R.attr</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.attr.compatibleWidthLimitDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.attr.html#compatibleWidthLimitDp" target="_top"><code>compatibleWidthLimitDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.attr.largestWidthLimitDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.attr.html#largestWidthLimitDp" target="_top"><code>largestWidthLimitDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.attr.requiresSmallestWidthDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.attr.html#requiresSmallestWidthDp" target="_top"><code>requiresSmallestWidthDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.R.style.html b/docs/html/sdk/api_diff/13/changes/android.R.style.html
new file mode 100644
index 0000000..9e385e2
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.R.style.html
@@ -0,0 +1,395 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.R.style
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.<A HREF="../../../../reference/android/R.style.html" target="_top"><font size="+2"><code>R.style</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo" target="_top"><code>TextAppearance_Holo</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_DialogWindowTitle"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_DialogWindowTitle" target="_top"><code>TextAppearance_Holo_DialogWindowTitle</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Inverse"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Inverse" target="_top"><code>TextAppearance_Holo_Inverse</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Large"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Large" target="_top"><code>TextAppearance_Holo_Large</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Large_Inverse"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Large_Inverse" target="_top"><code>TextAppearance_Holo_Large_Inverse</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Medium"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Medium" target="_top"><code>TextAppearance_Holo_Medium</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Medium_Inverse"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Medium_Inverse" target="_top"><code>TextAppearance_Holo_Medium_Inverse</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_SearchResult_Subtitle"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_SearchResult_Subtitle" target="_top"><code>TextAppearance_Holo_SearchResult_Subtitle</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_SearchResult_Title"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_SearchResult_Title" target="_top"><code>TextAppearance_Holo_SearchResult_Title</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Small"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Small" target="_top"><code>TextAppearance_Holo_Small</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Small_Inverse"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Small_Inverse" target="_top"><code>TextAppearance_Holo_Small_Inverse</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget" target="_top"><code>TextAppearance_Holo_Widget</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionBar_Subtitle" target="_top"><code>TextAppearance_Holo_Widget_ActionBar_Subtitle</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionBar_Title"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionBar_Title" target="_top"><code>TextAppearance_Holo_Widget_ActionBar_Title</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionMode_Subtitle" target="_top"><code>TextAppearance_Holo_Widget_ActionMode_Subtitle</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionMode_Title"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionMode_Title" target="_top"><code>TextAppearance_Holo_Widget_ActionMode_Title</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_Button"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_Button" target="_top"><code>TextAppearance_Holo_Widget_Button</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_DropDownHint"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_DropDownHint" target="_top"><code>TextAppearance_Holo_Widget_DropDownHint</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_DropDownItem"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_DropDownItem" target="_top"><code>TextAppearance_Holo_Widget_DropDownItem</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_EditText"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_EditText" target="_top"><code>TextAppearance_Holo_Widget_EditText</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_IconMenu_Item"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_IconMenu_Item" target="_top"><code>TextAppearance_Holo_Widget_IconMenu_Item</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu_Large" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu_Large</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu_Small" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu_Small</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_TabWidget"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TabWidget" target="_top"><code>TextAppearance_Holo_Widget_TabWidget</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView" target="_top"><code>TextAppearance_Holo_Widget_TextView</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView_PopupMenu" target="_top"><code>TextAppearance_Holo_Widget_TextView_PopupMenu</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView_SpinnerItem" target="_top"><code>TextAppearance_Holo_Widget_TextView_SpinnerItem</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.TextAppearance_Holo_WindowTitle"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_WindowTitle" target="_top"><code>TextAppearance_Holo_WindowTitle</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Theme_Holo_Light_NoActionBar"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Theme_Holo_Light_NoActionBar" target="_top"><code>Theme_Holo_Light_NoActionBar</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Theme_Holo_Light_NoActionBar_Fullscreen" target="_top"><code>Theme_Holo_Light_NoActionBar_Fullscreen</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_ActionBar_TabBar"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabBar" target="_top"><code>Widget_ActionBar_TabBar</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_ActionBar_TabText"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabText" target="_top"><code>Widget_ActionBar_TabText</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_ActionBar_TabView"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabView" target="_top"><code>Widget_ActionBar_TabView</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_ActionBar_TabBar"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabBar" target="_top"><code>Widget_Holo_ActionBar_TabBar</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_ActionBar_TabText"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabText" target="_top"><code>Widget_Holo_ActionBar_TabText</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_ActionBar_TabView"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabView" target="_top"><code>Widget_Holo_ActionBar_TabView</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabBar"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabBar" target="_top"><code>Widget_Holo_Light_ActionBar_TabBar</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabText"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabText" target="_top"><code>Widget_Holo_Light_ActionBar_TabText</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabView"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabView" target="_top"><code>Widget_Holo_Light_ActionBar_TabView</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.Activity.html b/docs/html/sdk/api_diff/13/changes/android.app.Activity.html
new file mode 100644
index 0000000..b27816b
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.Activity.html
@@ -0,0 +1,195 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.Activity
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/Activity.html" target="_top"><font size="+2"><code>Activity</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.dismissDialog_changed(int)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#dismissDialog(int)" target="_top"><code>dismissDialog</code></A>(<code>int</code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.getLastNonConfigurationInstance_changed()"></A>
+  <nobr><code>Object</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#getLastNonConfigurationInstance()" target="_top"><code>getLastNonConfigurationInstance</code></A>()  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.onRetainNonConfigurationInstance_changed()"></A>
+  <nobr><code>Object</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#onRetainNonConfigurationInstance()" target="_top"><code>onRetainNonConfigurationInstance</code></A>()  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.removeDialog_changed(int)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#removeDialog(int)" target="_top"><code>removeDialog</code></A>(<code>int</code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)"></A>
+  <nobr><code>Dialog</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#onCreateDialog(int, android.os.Bundle)" target="_top"><code>onCreateDialog</code></A>(<code>int,</nobr> Bundle<nobr><nobr></code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#onPrepareDialog(int, android.app.Dialog, android.os.Bundle)" target="_top"><code>onPrepareDialog</code></A>(<code>int,</nobr> Dialog<nobr>,</nobr> Bundle<nobr><nobr></code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.showDialog_changed(int, android.os.Bundle)"></A>
+  <nobr><code>boolean</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#showDialog(int, android.os.Bundle)" target="_top"><code>showDialog</code></A>(<code>int,</nobr> Bundle<nobr><nobr></code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Activity.showDialog_changed(int)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Activity.html#showDialog(int)" target="_top"><code>showDialog</code></A>(<code>int</code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html b/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html
new file mode 100644
index 0000000..c755228e
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.ActivityGroup
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/ActivityGroup.html" target="_top"><font size="+2"><code>ActivityGroup</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html b/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html
new file mode 100644
index 0000000..074d4b3
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.Fragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/Fragment.html" target="_top"><font size="+2"><code>Fragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Fragment.isDetached_added()"></A>
+  <nobr><code>boolean</code>&nbsp;<A HREF="../../../../reference/android/app/Fragment.html#isDetached()" target="_top"><code>isDetached</code></A>()</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Fragment.html#onViewCreated(android.view.View, android.os.Bundle)" target="_top"><code>onViewCreated</code></A>(<code>View,</nobr> Bundle<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/Fragment.html#setInitialSavedState(android.app.Fragment.SavedState)" target="_top"><code>setInitialSavedState</code></A>(<code>SavedState</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html b/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html
new file mode 100644
index 0000000..159b9c9
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.FragmentManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/FragmentManager.html" target="_top"><font size="+2"><code>FragmentManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)"></A>
+  <nobr><code>SavedState</code>&nbsp;<A HREF="../../../../reference/android/app/FragmentManager.html#saveFragmentInstanceState(android.app.Fragment)" target="_top"><code>saveFragmentInstanceState</code></A>(<code>Fragment</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html b/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html
new file mode 100644
index 0000000..dbb7deb
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.FragmentTransaction
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/FragmentTransaction.html" target="_top"><font size="+2"><code>FragmentTransaction</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.FragmentTransaction.attach_added(android.app.Fragment)"></A>
+  <nobr><code>FragmentTransaction</code>&nbsp;<A HREF="../../../../reference/android/app/FragmentTransaction.html#attach(android.app.Fragment)" target="_top"><code>attach</code></A>(<code>Fragment</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.FragmentTransaction.detach_added(android.app.Fragment)"></A>
+  <nobr><code>FragmentTransaction</code>&nbsp;<A HREF="../../../../reference/android/app/FragmentTransaction.html#detach(android.app.Fragment)" target="_top"><code>detach</code></A>(<code>Fragment</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)"></A>
+  <nobr><code>FragmentTransaction</code>&nbsp;<A HREF="../../../../reference/android/app/FragmentTransaction.html#setCustomAnimations(int, int, int, int)" target="_top"><code>setCustomAnimations</code></A>(<code>int,</nobr> int<nobr>,</nobr> int<nobr>,</nobr> int<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html
new file mode 100644
index 0000000..3ae02ea
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.KeyguardManager.KeyguardLock
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/KeyguardManager.KeyguardLock.html" target="_top"><font size="+2"><code>KeyguardManager.KeyguardLock</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html
new file mode 100644
index 0000000..bc38771
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.KeyguardManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/KeyguardManager.html" target="_top"><font size="+2"><code>KeyguardManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/app/KeyguardManager.html#exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult)" target="_top"><code>exitKeyguardSecurely</code></A>(<code>OnKeyguardExitResult</code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)"></A>
+  <nobr><code>KeyguardLock</code>&nbsp;<A HREF="../../../../reference/android/app/KeyguardManager.html#newKeyguardLock(java.lang.String)" target="_top"><code>newKeyguardLock</code></A>(<code>String</code>)  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html b/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html
new file mode 100644
index 0000000..4ea08489
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.LocalActivityManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/LocalActivityManager.html" target="_top"><font size="+2"><code>LocalActivityManager</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html b/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html
new file mode 100644
index 0000000..405f7d8
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app.TabActivity
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.app.<A HREF="../../../../reference/android/app/TabActivity.html" target="_top"><font size="+2"><code>TabActivity</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html
new file mode 100644
index 0000000..70149a3
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.pm.ActivityInfo
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.content.pm.<A HREF="../../../../reference/android/content/pm/ActivityInfo.html" target="_top"><font size="+2"><code>ActivityInfo</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/pm/ActivityInfo.html#CONFIG_SCREEN_SIZE" target="_top"><code>CONFIG_SCREEN_SIZE</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/pm/ActivityInfo.html#CONFIG_SMALLEST_SCREEN_SIZE" target="_top"><code>CONFIG_SMALLEST_SCREEN_SIZE</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html
new file mode 100644
index 0000000..4aef492
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.pm.ApplicationInfo
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.content.pm.<A HREF="../../../../reference/android/content/pm/ApplicationInfo.html" target="_top"><font size="+2"><code>ApplicationInfo</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.ApplicationInfo.compatibleWidthLimitDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#compatibleWidthLimitDp" target="_top"><code>compatibleWidthLimitDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.ApplicationInfo.largestWidthLimitDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#largestWidthLimitDp" target="_top"><code>largestWidthLimitDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.ApplicationInfo.requiresSmallestWidthDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#requiresSmallestWidthDp" target="_top"><code>requiresSmallestWidthDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html
new file mode 100644
index 0000000..ca75d7a
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.pm.PackageManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.content.pm.<A HREF="../../../../reference/android/content/pm/PackageManager.html" target="_top"><font size="+2"><code>PackageManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT"></A>
+  <nobr><code>String</code>&nbsp;<A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" target="_top"><code>FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND"></A>
+  <nobr><code>String</code>&nbsp;<A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" target="_top"><code>FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE"></A>
+  <nobr><code>String</code>&nbsp;<A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_SCREEN_LANDSCAPE" target="_top"><code>FEATURE_SCREEN_LANDSCAPE</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT"></A>
+  <nobr><code>String</code>&nbsp;<A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_SCREEN_PORTRAIT" target="_top"><code>FEATURE_SCREEN_PORTRAIT</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html b/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html
new file mode 100644
index 0000000..110a142
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.res.Configuration
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.content.res.<A HREF="../../../../reference/android/content/res/Configuration.html" target="_top"><font size="+2"><code>Configuration</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#SCREEN_HEIGHT_DP_UNDEFINED" target="_top"><code>SCREEN_HEIGHT_DP_UNDEFINED</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#SCREEN_WIDTH_DP_UNDEFINED" target="_top"><code>SCREEN_WIDTH_DP_UNDEFINED</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" target="_top"><code>SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.UI_MODE_TYPE_TELEVISION"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#UI_MODE_TYPE_TELEVISION" target="_top"><code>UI_MODE_TYPE_TELEVISION</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.screenHeightDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#screenHeightDp" target="_top"><code>screenHeightDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.screenWidthDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#screenWidthDp" target="_top"><code>screenWidthDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res.Configuration.smallestScreenWidthDp"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/content/res/Configuration.html#smallestScreenWidthDp" target="_top"><code>smallestScreenWidthDp</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html b/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html
new file mode 100644
index 0000000..e3324d2
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.graphics.Point
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.graphics.<A HREF="../../../../reference/android/graphics/Point.html" target="_top"><font size="+2"><code>Point</code></font></A>
+</H2>
+<p><font xsize="+1">Added interface <code>android.os.Parcelable</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.Point.describeContents_added()"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/graphics/Point.html#describeContents()" target="_top"><code>describeContents</code></A>()</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.Point.readFromParcel_added(android.os.Parcel)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/graphics/Point.html#readFromParcel(android.os.Parcel)" target="_top"><code>readFromParcel</code></A>(<code>Parcel</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.Point.writeToParcel_added(android.os.Parcel, int)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/graphics/Point.html#writeToParcel(android.os.Parcel, int)" target="_top"><code>writeToParcel</code></A>(<code>Parcel,</nobr> int<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.Point.CREATOR"></A>
+  <nobr><code>Creator</code>&nbsp;<A HREF="../../../../reference/android/graphics/Point.html#CREATOR" target="_top"><code>CREATOR</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html b/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html
new file mode 100644
index 0000000..665c259
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.graphics.PointF
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.graphics.<A HREF="../../../../reference/android/graphics/PointF.html" target="_top"><font size="+2"><code>PointF</code></font></A>
+</H2>
+<p><font xsize="+1">Added interface <code>android.os.Parcelable</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.PointF.describeContents_added()"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/graphics/PointF.html#describeContents()" target="_top"><code>describeContents</code></A>()</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.PointF.readFromParcel_added(android.os.Parcel)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/graphics/PointF.html#readFromParcel(android.os.Parcel)" target="_top"><code>readFromParcel</code></A>(<code>Parcel</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/graphics/PointF.html#writeToParcel(android.os.Parcel, int)" target="_top"><code>writeToParcel</code></A>(<code>Parcel,</nobr> int<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics.PointF.CREATOR"></A>
+  <nobr><code>Creator</code>&nbsp;<A HREF="../../../../reference/android/graphics/PointF.html#CREATOR" target="_top"><code>CREATOR</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html b/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html
new file mode 100644
index 0000000..1eb15ed
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.hardware.usb.UsbDeviceConnection
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.hardware.usb.<A HREF="../../../../reference/android/hardware/usb/UsbDeviceConnection.html" target="_top"><font size="+2"><code>UsbDeviceConnection</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()"></A>
+  <nobr><code>byte[]</code>&nbsp;<A HREF="../../../../reference/android/hardware/usb/UsbDeviceConnection.html#getRawDescriptors()" target="_top"><code>getRawDescriptors</code></A>()</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html b/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html
new file mode 100644
index 0000000..977649f
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.net.ConnectivityManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.net.<A HREF="../../../../reference/android/net/ConnectivityManager.html" target="_top"><font size="+2"><code>ConnectivityManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.net.ConnectivityManager.TYPE_BLUETOOTH"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/net/ConnectivityManager.html#TYPE_BLUETOOTH" target="_top"><code>TYPE_BLUETOOTH</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.net.ConnectivityManager.TYPE_ETHERNET"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/net/ConnectivityManager.html#TYPE_ETHERNET" target="_top"><code>TYPE_ETHERNET</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.os.Binder.html b/docs/html/sdk/api_diff/13/changes/android.os.Binder.html
new file mode 100644
index 0000000..fd11dd1
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.os.Binder.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os.Binder
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.os.<A HREF="../../../../reference/android/os/Binder.html" target="_top"><font size="+2"><code>Binder</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/os/Binder.html#dumpAsync(java.io.FileDescriptor, java.lang.String[])" target="_top"><code>dumpAsync</code></A>(<code>FileDescriptor,</nobr> String[]<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html b/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html
new file mode 100644
index 0000000..0e50af4
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os.Build.VERSION_CODES
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.os.<A HREF="../../../../reference/android/os/Build.VERSION_CODES.html" target="_top"><font size="+2"><code>Build.VERSION_CODES</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.Build.VERSION_CODES.HONEYCOMB_MR2"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/os/Build.VERSION_CODES.html#HONEYCOMB_MR2" target="_top"><code>HONEYCOMB_MR2</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html b/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html
new file mode 100644
index 0000000..1a251cd
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os.IBinder
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Interface android.os.<A HREF="../../../../reference/android/os/IBinder.html" target="_top"><font size="+2"><code>IBinder</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/os/IBinder.html#dumpAsync(java.io.FileDescriptor, java.lang.String[])" target="_top"><code>dumpAsync</code></A>(<code>FileDescriptor,</nobr> String[]<nobr><nobr></code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.IBinder.TWEET_TRANSACTION"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/os/IBinder.html#TWEET_TRANSACTION" target="_top"><code>TWEET_TRANSACTION</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html b/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html
new file mode 100644
index 0000000..3d3d1c3
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os.ParcelFileDescriptor
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.os.<A HREF="../../../../reference/android/os/ParcelFileDescriptor.html" target="_top"><font size="+2"><code>ParcelFileDescriptor</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.ParcelFileDescriptor.adoptFd_added(int)"></A>
+  <nobr><code>ParcelFileDescriptor</code>&nbsp;<A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#adoptFd(int)" target="_top"><code>adoptFd</code></A>(<code>int</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)"></A>
+  <nobr><code>ParcelFileDescriptor</code>&nbsp;<A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#dup(java.io.FileDescriptor)" target="_top"><code>dup</code></A>(<code>FileDescriptor</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.ParcelFileDescriptor.fromFd_added(int)"></A>
+  <nobr><code>ParcelFileDescriptor</code>&nbsp;<A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#fromFd(int)" target="_top"><code>fromFd</code></A>(<code>int</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html b/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html
new file mode 100644
index 0000000..4af746d
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os.PowerManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.os.<A HREF="../../../../reference/android/os/PowerManager.html" target="_top"><font size="+2"><code>PowerManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=3>Changed Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/os/PowerManager.html#SCREEN_BRIGHT_WAKE_LOCK" target="_top"><code>SCREEN_BRIGHT_WAKE_LOCK</code></font></A></nobr>  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html b/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html
new file mode 100644
index 0000000..43d6cf6
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.telephony.TelephonyManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.telephony.<A HREF="../../../../reference/android/telephony/TelephonyManager.html" target="_top"><font size="+2"><code>TelephonyManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/telephony/TelephonyManager.html#NETWORK_TYPE_HSPAP" target="_top"><code>NETWORK_TYPE_HSPAP</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html b/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html
new file mode 100644
index 0000000..01c329f
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.util.DisplayMetrics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.util.<A HREF="../../../../reference/android/util/DisplayMetrics.html" target="_top"><font size="+2"><code>DisplayMetrics</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.util.DisplayMetrics.DENSITY_TV"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/util/DisplayMetrics.html#DENSITY_TV" target="_top"><code>DENSITY_TV</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.view.Display.html b/docs/html/sdk/api_diff/13/changes/android.view.Display.html
new file mode 100644
index 0000000..872532a
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.view.Display.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.view.Display
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.view.<A HREF="../../../../reference/android/view/Display.html" target="_top"><font size="+2"><code>Display</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view.Display.getRectSize_added(android.graphics.Rect)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/view/Display.html#getRectSize(android.graphics.Rect)" target="_top"><code>getRectSize</code></A>(<code>Rect</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view.Display.getSize_added(android.graphics.Point)"></A>
+  <nobr><code>void</code>&nbsp;<A HREF="../../../../reference/android/view/Display.html#getSize(android.graphics.Point)" target="_top"><code>getSize</code></A>(<code>Point</code>)</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view.Display.getHeight_changed()"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/view/Display.html#getHeight()" target="_top"><code>getHeight</code></A>()  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view.Display.getWidth_changed()"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/view/Display.html#getWidth()" target="_top"><code>getWidth</code></A>()  </nobr>
+  </TD>
+  <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html b/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html
new file mode 100644
index 0000000..eaccac4
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.view.KeyEvent
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.view.<A HREF="../../../../reference/android/view/KeyEvent.html" target="_top"><font size="+2"><code>KeyEvent</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view.KeyEvent.getModifiers_added()"></A>
+  <nobr><code>int</code>&nbsp;<A HREF="../../../../reference/android/view/KeyEvent.html#getModifiers()" target="_top"><code>getModifiers</code></A>()</nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<a NAME="fields"></a>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/changes-summary.html b/docs/html/sdk/api_diff/13/changes/changes-summary.html
new file mode 100644
index 0000000..082fcfb
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/changes-summary.html
@@ -0,0 +1,205 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Android API Differences Report
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+    <div id="docTitleContainer">
+<h1>Android&nbsp;API&nbsp;Differences&nbsp;Report</h1>
+<p>This report details the changes in the core Android framework API between two <a 
+href="http://developer.android.com/guide/appendix/api-levels.html" target="_top">API Level</a> 
+specifications. It shows additions, modifications, and removals for packages, classes, methods, and fields. 
+The report also includes general statistics that characterize the extent and type of the differences.</p>
+<p>This report is based a comparison of the Android API specifications 
+whose API Level identifiers are given in the upper-right corner of this page. It compares a 
+newer "to" API to an older "from" API, noting all changes relative to the 
+older API. So, for example, API elements marked as removed are no longer present in the "to" 
+API specification.</p>
+<p>To navigate the report, use the "Select a Diffs Index" and "Filter the Index" 
+controls on the left. The report uses text formatting to indicate <em>interface names</em>, 
+<a href= ><code>links to reference documentation</code></a>, and <a href= >links to change 
+description</a>. The statistics are accessible from the "Statistics" link in the upper-right corner.</p>
+<p>For more information about the Android framework API and SDK, 
+see the <a href="http://developer.android.com/index.html" target="_top">Android Developers site</a>.</p>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Packages" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=3>Changed Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android"></A>
+  <nobr><A HREF="pkg_android.html">android</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.app"></A>
+  <nobr><A HREF="pkg_android.app.html">android.app</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.pm"></A>
+  <nobr><A HREF="pkg_android.content.pm.html">android.content.pm</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.content.res"></A>
+  <nobr><A HREF="pkg_android.content.res.html">android.content.res</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.graphics"></A>
+  <nobr><A HREF="pkg_android.graphics.html">android.graphics</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.hardware.usb"></A>
+  <nobr><A HREF="pkg_android.hardware.usb.html">android.hardware.usb</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.net"></A>
+  <nobr><A HREF="pkg_android.net.html">android.net</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.os"></A>
+  <nobr><A HREF="pkg_android.os.html">android.os</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.telephony"></A>
+  <nobr><A HREF="pkg_android.telephony.html">android.telephony</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.util"></A>
+  <nobr><A HREF="pkg_android.util.html">android.util</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="android.view"></A>
+  <nobr><A HREF="pkg_android.view.html">android.view</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- End of API section -->
+<!-- Start of packages section -->
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_additions.html b/docs/html/sdk/api_diff/13/changes/classes_index_additions.html
new file mode 100644
index 0000000..9ca1958
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/classes_index_additions.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<b>Additions</b>
+  <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#P"><font size="-2">P</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#F"><font size="-2">F</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_all.html b/docs/html/sdk/api_diff/13/changes/classes_index_all.html
new file mode 100644
index 0000000..6bd1021
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/classes_index_all.html
@@ -0,0 +1,300 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Classes</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br>
+<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br>
+<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br>
+<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br>
+<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br>
+<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br>
+<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br>
+<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br>
+<A NAME="K"></A>
+<br><font size="+2">K</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br>
+<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br>
+<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br>
+<A NAME="M"></A>
+<br><font size="+2">M</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br>
+<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br>
+<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br>
+<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br>
+<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br>
+<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br>
+<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br>
+<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_changes.html b/docs/html/sdk/api_diff/13/changes/classes_index_changes.html
new file mode 100644
index 0000000..d76983f
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/classes_index_changes.html
@@ -0,0 +1,298 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<b>Changes</b>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br>
+<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br>
+<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br>
+<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br>
+<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br>
+<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br>
+<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br>
+<A NAME="K"></A>
+<br><font size="+2">K</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br>
+<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br>
+<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br>
+<A NAME="M"></A>
+<br><font size="+2">M</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br>
+<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br>
+<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br>
+<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br>
+<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br>
+<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br>
+<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#B"><font size="-2">B</font></a> 
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#K"><font size="-2">K</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#M"><font size="-2">M</font></a> 
+<a href="#P"><font size="-2">P</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_removals.html b/docs/html/sdk/api_diff/13/changes/classes_index_removals.html
new file mode 100644
index 0000000..e6da73f
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/classes_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html b/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html
new file mode 100644
index 0000000..3237ba3
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<font color="#999999">Changes</font>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_all.html b/docs/html/sdk/api_diff/13/changes/constructors_index_all.html
new file mode 100644
index 0000000..637582e
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/constructors_index_all.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Constructors</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<font color="#999999">Changes</font>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html b/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html
new file mode 100644
index 0000000..728fa2d
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<font color="#999999">Changes</font>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html b/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html
new file mode 100644
index 0000000..1b95544
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<font color="#999999">Changes</font>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_additions.html b/docs/html/sdk/api_diff/13/changes/fields_index_additions.html
new file mode 100644
index 0000000..271c9aa
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/fields_index_additions.html
@@ -0,0 +1,363 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<b>Additions</b>
+  <br>
+<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>compatibleWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A>
+</nobr><br>
+<i>CREATOR</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A>
+</nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A>
+</nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A>
+</nobr><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A>
+</nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>largestWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A>
+</nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>requiresSmallestWidthDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A>
+</nobr><br>
+<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A>
+</nobr><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A>
+</nobr><br>
+<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A>
+</nobr><br>
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A>
+</nobr><br>
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A>
+</nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A>
+</nobr><br>
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A>
+</nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_all.html b/docs/html/sdk/api_diff/13/changes/fields_index_all.html
new file mode 100644
index 0000000..f183408
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/fields_index_all.html
@@ -0,0 +1,365 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Fields</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="C"></A>
+<br><font size="+2">C</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>compatibleWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A>
+</nobr><br>
+<i>CREATOR</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A>
+</nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A>
+</nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A>
+</nobr><br>
+<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A>
+</nobr><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A>
+</nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>largestWidthLimitDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A>
+</nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>requiresSmallestWidthDp</i><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A>
+</nobr><br>
+<nobr>&nbsp;in&nbsp;
+<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A>
+</nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A>
+</nobr><br>
+<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A>
+</nobr><br>
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A>
+</nobr><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A>
+</nobr><br>
+<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A>
+</nobr><br>
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A>
+</nobr><br>
+<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A>
+</nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A>
+</nobr><br>
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#C"><font size="-2">C</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#H"><font size="-2">H</font></a> 
+<a href="#L"><font size="-2">L</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#T"><font size="-2">T</font></a> 
+<a href="#U"><font size="-2">U</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A>
+</nobr><br>
+<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A>
+</nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_changes.html b/docs/html/sdk/api_diff/13/changes/fields_index_changes.html
new file mode 100644
index 0000000..953047c
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/fields_index_changes.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<b>Changes</b>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A>
+</nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_removals.html b/docs/html/sdk/api_diff/13/changes/fields_index_removals.html
new file mode 100644
index 0000000..9f62d88
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/fields_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_help.html b/docs/html/sdk/api_diff/13/changes/jdiff_help.html
new file mode 100644
index 0000000..ec659d4
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/jdiff_help.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+JDiff Help
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<TABLE summary="Navigation bar" BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+  <TABLE summary="Navigation bar" BORDER="0" CELLPADDING="0" CELLSPACING="3">
+    <TR ALIGN="center" VALIGN="top">
+      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../reference/index.html" target="_top"><FONT CLASS="NavBarFont1"><B><code>13</code></B></FONT></A>&nbsp;</TD>
+      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="changes-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
+      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> &nbsp;<FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+      <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> &nbsp;<FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="jdiff_statistics.html"><FONT CLASS="NavBarFont1"><B>Statistics</B></FONT></A>&nbsp;</TD>
+      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+    </TR>
+  </TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Generated by<br><a href="http://www.jdiff.org" class="staysblack" target="_top">JDiff</a></b></EM></TD>
+</TR>
+<TR>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"></FONT>
+</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../changes.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+  &nbsp;<A HREF="jdiff_help.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<HR>
+<!-- End of nav bar -->
+<center>
+<H1>JDiff Documentation</H1>
+</center>
+<BLOCKQUOTE>
+JDiff is a <a href="http://java.sun.com/j2se/javadoc/" target="_top">Javadoc</a> doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does. 
+This help page describes the different parts of the output from JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+ See the reference page in the <a href="http://www.jdiff.org">source for JDiff</a> for information about how to generate a report like this one.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order. 
+These indexes all use the same format:
+<ul>
+<li>Removed packages, classes, constructors, methods and fields are <strike>struck through</strike>.</li>
+<li>Added packages, classes, constructors, methods and fields appear in <b>bold</b>.</li>
+<li>Changed packages, classes, constructors, methods and fields appear in normal text.</li>
+</ul>
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background. 
+Links which take you to a Javadoc page are always in a <code>typewriter</code> font. 
+Just like Javadoc, all interface names are in <i>italic</i>, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3><b><code>Javadoc</code></b></H3>
+This is a link to the <a href="../../../../reference/index.html" target="_top">top-level</a> Javadoc page for the new version of the product.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Overview</H3>
+The <a href="changes-summary.html">overview</a> is the top-level summary of what was removed, added and changed between versions.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Package</H3>
+This is a link to the package containing the current changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Class</H3>
+This is highlighted when you are looking at the changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Text Changes</H3>
+This is a link to the top-level index of all documentation changes for the current package or class. 
+If it is not present, then there are no documentation changes for the current package or class. 
+This link can be removed entirely by not using the <code>-docchanges</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Statistics</H3>
+This is a link to a page which shows statistics about the changes between the two APIs.
+This link can be removed entirely by not using the <code>-stats</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Help</H3>
+A link to this Help page for JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Prev/Next</H3>
+These links take you to the previous  and next changed package or class.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H2>Complex Changes</H2>
+There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
+In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
+</BLOCKQUOTE>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html b/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html
new file mode 100644
index 0000000..626c765
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html
@@ -0,0 +1,382 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+API Change Statistics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;xborder-bottom:none;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="../changes.html" target="_top">Top of Report</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<h1>API&nbsp;Change&nbsp;Statistics</h1>
+<p>The overall difference between API Levels 12 and 13 is approximately <span style="color:222;font-weight:bold;">0.04%</span>.
+</p>
+<br>
+<a name="numbers"></a>
+<h2>Total of Differences, by Number and Type</h2>
+<p>
+The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements &mdash; that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class.
+</p>
+<TABLE summary="Number of differences" WIDTH="100%">
+<TR>
+  <th>Type</th>
+  <TH ALIGN="center"><b>Additions</b></TH>
+  <TH ALIGN="center"><b>Changes</b></TH>
+  <TH ALIGN="center">Removals</TH>
+  <TH ALIGN="center"><b>Total</b></TH>
+</TR>
+<TR>
+  <TD>Packages</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">11</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">11</TD>
+</TR>
+<TR>
+  <TD>Classes and <i>Interfaces</i></TD>
+  <TD ALIGN="right">2</TD>
+  <TD ALIGN="right">29</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">31</TD>
+</TR>
+<TR>
+  <TD>Constructors</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">0</TD>
+</TR>
+<TR>
+  <TD>Methods</TD>
+  <TD ALIGN="right">22</TD>
+  <TD ALIGN="right">12</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">34</TD>
+</TR>
+<TR>
+  <TD>Fields</TD>
+  <TD ALIGN="right">68</TD>
+  <TD ALIGN="right">1</TD>
+  <TD ALIGN="right">0</TD>
+  <TD ALIGN="right">69</TD>
+</TR>
+<TR>
+  <TD style="background-color:#FAFAFA"><b>Total</b></TD>
+  <TD  style="background-color:#FAFAFA" ALIGN="right"><strong>92</strong></TD>
+  <TD  style="background-color:#FAFAFA" ALIGN="right"><strong>53</strong></TD>
+  <TD  style="background-color:#FAFAFA" ALIGN="right"><strong>0</strong></TD>
+  <TD  style="background-color:#FAFAFA" ALIGN="right"><strong>145</strong></TD>
+</TR>
+</TABLE>
+<br>
+<a name="packages"></a>
+<h2>Changed Packages, Sorted by Percentage Difference</h2>
+<TABLE summary="Packages sorted by percentage difference" WIDTH="100%">
+<TR>
+  <TH  WIDTH="10%">Percentage Difference*</TH>
+  <TH>Package</TH>
+</TR>
+<TR>
+  <TD ALIGN="center">2</TD>
+  <TD><A HREF="pkg_android.app.html">android.app</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">1</TD>
+  <TD><A HREF="pkg_android.os.html">android.os</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.hardware.usb.html">android.hardware.usb</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.graphics.html">android.graphics</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.html">android</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.content.res.html">android.content.res</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.content.pm.html">android.content.pm</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.view.html">android.view</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.net.html">android.net</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.util.html">android.util</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="pkg_android.telephony.html">android.telephony</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<a name="classes"></a>
+<h2>Changed Classes and <i>Interfaces</i>, Sorted by Percentage Difference</h2>
+<TABLE summary="Classes sorted by percentage difference" WIDTH="100%">
+<TR WIDTH="20%">
+  <TH WIDTH="10%">Percentage<br>Difference*</TH>
+  <TH><b>Class or <i>Interface</i></b></TH>
+</TR>
+<TR>
+  <TD ALIGN="center">33</TD>
+  <TD><A HREF="android.app.KeyguardManager.html">
+android.app.KeyguardManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">25</TD>
+  <TD><A HREF="android.app.KeyguardManager.KeyguardLock.html">
+android.app.KeyguardManager.KeyguardLock</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">20</TD>
+  <TD><A HREF="android.view.Display.html">
+android.view.Display</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">18</TD>
+  <TD><A HREF="android.graphics.Point.html">
+android.graphics.Point</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">14</TD>
+  <TD><A HREF="android.graphics.PointF.html">
+android.graphics.PointF</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">12</TD>
+  <TD><A HREF="android.app.ActivityGroup.html">
+android.app.ActivityGroup</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">10</TD>
+  <TD><A HREF="android.app.TabActivity.html">
+android.app.TabActivity</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">7</TD>
+  <TD><A HREF="android.R.style.html">
+android.R.style</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">6</TD>
+  <TD><A HREF="android.os.ParcelFileDescriptor.html">
+android.os.ParcelFileDescriptor</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">6</TD>
+  <TD><A HREF="android.os.IBinder.html">
+<i>android.os.IBinder</i></A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">5</TD>
+  <TD><A HREF="android.hardware.usb.UsbDeviceConnection.html">
+android.hardware.usb.UsbDeviceConnection</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">4</TD>
+  <TD><A HREF="android.app.FragmentTransaction.html">
+android.app.FragmentTransaction</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">4</TD>
+  <TD><A HREF="android.content.res.Configuration.html">
+android.content.res.Configuration</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">4</TD>
+  <TD><A HREF="android.os.PowerManager.html">
+android.os.PowerManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.app.LocalActivityManager.html">
+android.app.LocalActivityManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.net.ConnectivityManager.html">
+android.net.ConnectivityManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.app.Activity.html">
+android.app.Activity</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.os.Build.VERSION_CODES.html">
+android.os.Build.VERSION_CODES</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.content.pm.ApplicationInfo.html">
+android.content.pm.ApplicationInfo</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">3</TD>
+  <TD><A HREF="android.util.DisplayMetrics.html">
+android.util.DisplayMetrics</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">2</TD>
+  <TD><A HREF="android.os.Binder.html">
+android.os.Binder</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">2</TD>
+  <TD><A HREF="android.app.Fragment.html">
+android.app.Fragment</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">2</TD>
+  <TD><A HREF="android.app.FragmentManager.html">
+android.app.FragmentManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">1</TD>
+  <TD><A HREF="android.content.pm.ActivityInfo.html">
+android.content.pm.ActivityInfo</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">1</TD>
+  <TD><A HREF="android.content.pm.PackageManager.html">
+android.content.pm.PackageManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="android.telephony.TelephonyManager.html">
+android.telephony.TelephonyManager</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="android.Manifest.permission.html">
+android.Manifest.permission</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="android.R.attr.html">
+android.R.attr</A></TD>
+</TR>
+<TR>
+  <TD ALIGN="center">&lt;1</TD>
+  <TD><A HREF="android.view.KeyEvent.html">
+android.view.KeyEvent</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<h2 id="calculation">Calculation of Change Percentages</h2>
+<p>
+The percent change statistic reported for all elements in the &quot;to&quot; API Level specification is defined recursively as follows:</p>
+<pre>
+Percentage difference = 100 * (added + removed + 2*changed)
+                        -----------------------------------
+                        sum of public elements in BOTH APIs
+</pre>
+<p>where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed.
+This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed.
+The definition ensures that if all packages are removed and all new packages are
+added, the change will be 100%.</p>
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY></HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html b/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html
new file mode 100644
index 0000000..36f9836
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Android API Version Differences
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<table class="jdiffIndex" summary="Links to diff index files" BORDER="0" WIDTH="100%" cellspacing="0" cellpadding="0" style="margin:0">
+<TR>
+  <th class="indexHeader" nowrap>
+  Select a Diffs Index:</th>
+</TR>
+<TR>
+  <TD><FONT CLASS="indexText" size="-2"><A HREF="alldiffs_index_all.html" TARGET="bottomleftframe">All Differences</A></FONT><br></TD>
+</TR>
+<TR>
+  <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="packages_index_all.html" TARGET="bottomleftframe">By Package</A></FONT><br></TD>
+</TR>
+<TR>
+  <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="classes_index_all.html" TARGET="bottomleftframe">By Class</A></FONT><br></TD>
+</TR>
+<TR>
+  <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="constructors_index_all.html" TARGET="bottomleftframe">By Constructor</A></FONT><br></TD>
+</TR>
+<TR>
+  <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="methods_index_all.html" TARGET="bottomleftframe">By Method</A></FONT><br></TD>
+</TR>
+<TR>
+  <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
+</TR>
+</TABLE>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_additions.html b/docs/html/sdk/api_diff/13/changes/methods_index_additions.html
new file mode 100644
index 0000000..fbbf5a6
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/methods_index_additions.html
@@ -0,0 +1,225 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<b>Additions</b>
+  <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b>
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>describeContents</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<i>dumpAsync</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.Binder
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.IBinder
+</A></nobr><br>
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b>
+(<code>FileDescriptor</code>)</A></nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b>
+(<code>int</code>)</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b>
+()</A></nobr><br>
+<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b>
+()</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b>
+(<code>Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b>
+(<code>Point</code>)</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b>
+()</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b>
+(<code>View, Bundle</code>)</A></nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>readFromParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b>
+(<code>Fragment</code>)</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b>
+(<code>int, int, int, int</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b>
+(<code>SavedState</code>)</A></nobr><br>
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>writeToParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_all.html b/docs/html/sdk/api_diff/13/changes/methods_index_all.html
new file mode 100644
index 0000000..84d0a2c
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/methods_index_all.html
@@ -0,0 +1,298 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Methods</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b>
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>describeContents</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type&nbsp;<b>
+()</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b>
+(<code>Fragment</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog
+(<code>int</code>)</A></nobr><br>
+<i>dumpAsync</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.Binder
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>FileDescriptor, String[]</code>)</b>&nbsp;in&nbsp;android.os.IBinder
+</A></nobr><br>
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b>
+(<code>FileDescriptor</code>)</A></nobr><br>
+<A NAME="E"></A>
+<br><font size="+2">E</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely
+(<code>OnKeyguardExitResult</code>)</A></nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b>
+(<code>int</code>)</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight
+()</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance
+()</A></nobr><br>
+<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b>
+()</A></nobr><br>
+<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b>
+()</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b>
+(<code>Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b>
+(<code>Point</code>)</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b>
+()</A></nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock
+(<code>String</code>)</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog
+(<code>int, Bundle</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog
+(<code>int, Dialog, Bundle</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance
+()</A></nobr><br>
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b>
+(<code>View, Bundle</code>)</A></nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>readFromParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog
+(<code>int</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#W"><font size="-2">W</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b>
+(<code>Fragment</code>)</A></nobr><br>
+<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b>
+(<code>int, int, int, int</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b>
+(<code>SavedState</code>)</A></nobr><br>
+<i>showDialog</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int, Bundle</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<A NAME="W"></A>
+<br><font size="+2">W</font>&nbsp;
+<a href="#A"><font size="-2">A</font></a> 
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#F"><font size="-2">F</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#I"><font size="-2">I</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>writeToParcel</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.Point
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type&nbsp;<b>
+(<code>Parcel, int</code>)</b>&nbsp;in&nbsp;android.graphics.PointF
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_changes.html b/docs/html/sdk/api_diff/13/changes/methods_index_changes.html
new file mode 100644
index 0000000..97cc3ef
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/methods_index_changes.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<b>Changes</b>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="D"></A>
+<br><font size="+2">D</font>&nbsp;
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog
+(<code>int</code>)</A></nobr><br>
+<A NAME="E"></A>
+<br><font size="+2">E</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely
+(<code>OnKeyguardExitResult</code>)</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight
+()</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance
+()</A></nobr><br>
+<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth
+()</A></nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock
+(<code>String</code>)</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog
+(<code>int, Bundle</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog
+(<code>int, Dialog, Bundle</code>)</A></nobr><br>
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance
+()</A></nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#S"><font size="-2">S</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog
+(<code>int</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>&nbsp;
+<a href="#D"><font size="-2">D</font></a> 
+<a href="#E"><font size="-2">E</font></a> 
+<a href="#G"><font size="-2">G</font></a> 
+<a href="#N"><font size="-2">N</font></a> 
+<a href="#O"><font size="-2">O</font></a> 
+<a href="#R"><font size="-2">R</font></a> 
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>showDialog</i><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int, Bundle</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+&nbsp;&nbsp;<nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type&nbsp;
+(<code>int</code>)&nbsp;in&nbsp;android.app.Activity
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_removals.html b/docs/html/sdk/api_diff/13/changes/methods_index_removals.html
new file mode 100644
index 0000000..b5aea4f
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/methods_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+  <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_additions.html b/docs/html/sdk/api_diff/13/changes/packages_index_additions.html
new file mode 100644
index 0000000..1776064
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/packages_index_additions.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_all.html b/docs/html/sdk/api_diff/13/changes/packages_index_all.html
new file mode 100644
index 0000000..c23f4a6
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/packages_index_all.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Packages</b>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br>
+<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br>
+<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br>
+<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br>
+<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br>
+<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br>
+<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br>
+<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br>
+<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br>
+<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br>
+<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_changes.html b/docs/html/sdk/api_diff/13/changes/packages_index_changes.html
new file mode 100644
index 0000000..d00b449
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/packages_index_changes.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<b>Changes</b>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br>
+<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br>
+<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br>
+<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br>
+<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br>
+<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br>
+<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br>
+<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br>
+<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br>
+<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br>
+<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_removals.html b/docs/html/sdk/api_diff/13/changes/packages_index_removals.html
new file mode 100644
index 0000000..9fd0f7e
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/packages_index_removals.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+  <tr>
+  <th class="indexHeader">
+    Filter the Index:
+  </th>
+  </tr>
+  <tr>
+  <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+  <br>
+<font color="#999999">Removals</font>
+  <br>
+<font color="#999999">Additions</font>
+  <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+  </td>
+  </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.app.html b/docs/html/sdk/api_diff/13/changes/pkg_android.app.html
new file mode 100644
index 0000000..d728895
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.app.html
@@ -0,0 +1,190 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/app/package-summary.html" target="_top"><font size="+1"><code>android.app</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Fragment.SavedState"></A>
+  <nobr><A HREF="../../../../reference/android/app/Fragment.SavedState.html" target="_top"><code>Fragment.SavedState</code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Activity"></A>
+  <nobr><A HREF="android.app.Activity.html">Activity</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="ActivityGroup"></A>
+  <nobr><A HREF="android.app.ActivityGroup.html">ActivityGroup</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Fragment"></A>
+  <nobr><A HREF="android.app.Fragment.html">Fragment</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="FragmentManager"></A>
+  <nobr><A HREF="android.app.FragmentManager.html">FragmentManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="FragmentTransaction"></A>
+  <nobr><A HREF="android.app.FragmentTransaction.html">FragmentTransaction</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="KeyguardManager"></A>
+  <nobr><A HREF="android.app.KeyguardManager.html">KeyguardManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="KeyguardManager.KeyguardLock"></A>
+  <nobr><A HREF="android.app.KeyguardManager.KeyguardLock.html">KeyguardManager.KeyguardLock</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="LocalActivityManager"></A>
+  <nobr><A HREF="android.app.LocalActivityManager.html">LocalActivityManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="TabActivity"></A>
+  <nobr><A HREF="android.app.TabActivity.html">TabActivity</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html b/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html
new file mode 100644
index 0000000..60ab502
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.pm
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/content/pm/package-summary.html" target="_top"><font size="+1"><code>android.content.pm</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="ActivityInfo"></A>
+  <nobr><A HREF="android.content.pm.ActivityInfo.html">ActivityInfo</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="ApplicationInfo"></A>
+  <nobr><A HREF="android.content.pm.ApplicationInfo.html">ApplicationInfo</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="PackageManager"></A>
+  <nobr><A HREF="android.content.pm.PackageManager.html">PackageManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html b/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html
new file mode 100644
index 0000000..01c31d04
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.content.res
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/content/res/package-summary.html" target="_top"><font size="+1"><code>android.content.res</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Configuration"></A>
+  <nobr><A HREF="android.content.res.Configuration.html">Configuration</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html b/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html
new file mode 100644
index 0000000..31ddb13
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.graphics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/graphics/package-summary.html" target="_top"><font size="+1"><code>android.graphics</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Point"></A>
+  <nobr><A HREF="android.graphics.Point.html">Point</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="PointF"></A>
+  <nobr><A HREF="android.graphics.PointF.html">PointF</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html b/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html
new file mode 100644
index 0000000..ec768c93
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.hardware.usb
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/hardware/usb/package-summary.html" target="_top"><font size="+1"><code>android.hardware.usb</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="UsbDeviceConnection"></A>
+  <nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html">UsbDeviceConnection</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.html b/docs/html/sdk/api_diff/13/changes/pkg_android.html
new file mode 100644
index 0000000..6b14637
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/package-summary.html" target="_top"><font size="+1"><code>android</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Manifest.permission"></A>
+  <nobr><A HREF="android.Manifest.permission.html">Manifest.permission</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="R.attr"></A>
+  <nobr><A HREF="android.R.attr.html">R.attr</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="R.style"></A>
+  <nobr><A HREF="android.R.style.html">R.style</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.net.html b/docs/html/sdk/api_diff/13/changes/pkg_android.net.html
new file mode 100644
index 0000000..f3f82cc
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.net.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.net
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/net/package-summary.html" target="_top"><font size="+1"><code>android.net</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="ConnectivityManager"></A>
+  <nobr><A HREF="android.net.ConnectivityManager.html">ConnectivityManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.os.html b/docs/html/sdk/api_diff/13/changes/pkg_android.os.html
new file mode 100644
index 0000000..b9a8c09
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.os.html
@@ -0,0 +1,162 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.os
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/os/package-summary.html" target="_top"><font size="+1"><code>android.os</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Interfaces" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Added Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Parcelable.ClassLoaderCreator"></A>
+  <nobr><A HREF="../../../../reference/android/os/Parcelable.ClassLoaderCreator.html" target="_top"><code><I>Parcelable.ClassLoaderCreator</I></code></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes and Interfaces" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Binder"></A>
+  <nobr><A HREF="android.os.Binder.html">Binder</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Build.VERSION_CODES"></A>
+  <nobr><A HREF="android.os.Build.VERSION_CODES.html">Build.VERSION_CODES</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="IBinder"></A>
+  <nobr><A HREF="android.os.IBinder.html"><I>IBinder</I></A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="ParcelFileDescriptor"></A>
+  <nobr><A HREF="android.os.ParcelFileDescriptor.html">ParcelFileDescriptor</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="PowerManager"></A>
+  <nobr><A HREF="android.os.PowerManager.html">PowerManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html b/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html
new file mode 100644
index 0000000..9a00876
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.telephony
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/telephony/package-summary.html" target="_top"><font size="+1"><code>android.telephony</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="TelephonyManager"></A>
+  <nobr><A HREF="android.telephony.TelephonyManager.html">TelephonyManager</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.util.html b/docs/html/sdk/api_diff/13/changes/pkg_android.util.html
new file mode 100644
index 0000000..0d92956
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.util.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.util
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/util/package-summary.html" target="_top"><font size="+1"><code>android.util</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="DisplayMetrics"></A>
+  <nobr><A HREF="android.util.DisplayMetrics.html">DisplayMetrics</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.view.html b/docs/html/sdk/api_diff/13/changes/pkg_android.view.html
new file mode 100644
index 0000000..22fde46
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/changes/pkg_android.view.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.view
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+  <div id="headerRight">
+  <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- &nbsp;<a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+  <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td colspan="2" class="diffspechead">API Diff Specification</td>
+      </tr>
+      <tr>
+        <td class="diffspec" style="padding-top:.25em">To Level:</td>
+        <td class="diffvaluenew" style="padding-top:.25em">13</td>
+      </tr>
+      <tr>
+        <td class="diffspec">From Level:</td>
+        <td class="diffvalueold">12</td>
+      </tr>
+      <tr>
+        <td class="diffspec">Generated</td>
+        <td class="diffvalue">2011.06.29 10:50</td>
+      </tr>
+    </table>
+    </div><!-- End and-diff-id -->
+  <div class="and-diff-id" style="margin-right:8px;">
+    <table class="diffspectable">
+      <tr>
+        <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+      </tr>
+    </table>
+  </div> <!-- End and-diff-id -->
+  </div> <!-- End headerRight -->
+  </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/view/package-summary.html" target="_top"><font size="+1"><code>android.view</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+  <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="Display"></A>
+  <nobr><A HREF="android.view.Display.html">Display</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+  <TD VALIGN="TOP" WIDTH="25%">
+  <A NAME="KeyEvent"></A>
+  <nobr><A HREF="android.view.KeyEvent.html">KeyEvent</A></nobr>
+  </TD>
+  <TD>&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+      </div>	
+      <div id="footer">
+        <div id="copyright">
+        Except as noted, this content is licensed under 
+        <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+        For details and restrictions, see the <a href="/license.html">Content License</a>.
+        </div>
+      <div id="footerlinks">
+      <p>
+        <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+        <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+        <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+      </p>
+    </div>
+    </div> <!-- end footer -->
+    </div><!-- end doc-content -->
+    </div> <!-- end body-content --> 
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+  try {
+    var pageTracker = _gat._getTracker("UA-5831155-1");
+    pageTracker._setAllowAnchor(true);
+    pageTracker._initData();
+    pageTracker._trackPageview();
+  } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/api_diff/13/stylesheet-jdiff.css b/docs/html/sdk/api_diff/13/stylesheet-jdiff.css
new file mode 100644
index 0000000..edafaa3
--- /dev/null
+++ b/docs/html/sdk/api_diff/13/stylesheet-jdiff.css
@@ -0,0 +1,44 @@
+
+/* (http://www.jdiff.org) */
+
+div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;}
+table.diffspectable {border:1px;padding:0px;margin:0px;}
+.diffspechead {background-color:#eee;}
+.diffspectable tr {border:0px;padding:0px;}
+.diffspectable td  {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;}
+td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;}
+tt {font-size:11pt;font-family:monospace;}
+.indexHeader {
+  font-size:96%;
+  line-height:.8em;}
+.jdiffIndex td {
+  font-size:96%;
+  xline-height:.8em;
+  padding:2px;
+  padding-left:1em;}
+.indexText {
+  font-size:100%;
+  padding-left:1em;}
+#indexTableCaption {
+  font-size:96%;
+  margin-top:.25em;
+  margin-bottom:0;
+  }
+.hiddenlink {
+  font-size:96%;
+  line-height:.8em;
+  text-decoration:none;}
+a {
+  text-decoration:none;}
+a:hover {
+  text-decoration:underline;}
+.indexBox {
+  border: 1px solid red;
+  margin:1em 0 0 0;}
+.letterIndexHead {
+  font-size: 1.5em;font-weight:9;
+  margin:0 0 0em 0;
+  border: 1px solid red;}
diff --git a/docs/html/sdk/compatibility-library.jd b/docs/html/sdk/compatibility-library.jd
index d4669e5..c8cd5b2 100644
--- a/docs/html/sdk/compatibility-library.jd
+++ b/docs/html/sdk/compatibility-library.jd
@@ -1,4 +1,4 @@
-page.title=Compatibility Library
+page.title=Compatibility Package
 
 @jd:body
 
@@ -8,9 +8,10 @@
 <h2>In this document</h2>
 <ol>
   <li><a href="#Notes">Revisions</a></li>
-  <li><a href="#Installing">Installing the Compatibility Library</a></li>
-  <li><a href="#SettingUp">Setting Up a Project to Use the Library</a></li>
-  <li><a href="#Using">Using Some of the Library APIs</a></li>
+  <li><a href="#Downloading">Downloading the Compatibility Package</a></li>
+  <li><a href="#SettingUp">Setting Up a Project to Use a Library</a></li>
+  <li><a href="#Using">Using the v4 Library APIs</a></li>
+  <li><a href="#Docs">Reference Docs</a></li>
   <li><a href="#Samples">Samples</a></li>
 </ol>
 
@@ -26,42 +27,92 @@
 
 <p><em>Minimum API level supported:</em> <b>4</b></p>
 
-<p>The Compatibility Library is a static library you can add to your Android application in order to
-use APIs not available in older versions of the Android platform. The primary goal of the library is
-to provide APIs introduced in Andriod 3.0 for older versions of Android so that all applications can
-use them.</p>
+<p>The Compatibility Package includes static "support libraries" that you can add to your Android
+application in order to use APIs that are either not available for older platform versions or that
+offer "utility" APIs that aren't a part of the framework APIs. The goal is to simplify your
+development by offering more APIs that you can bundle with your application so you can
+worry less about platform versions.</p>
 
-<p>If you're not able to use APIs introduced in Android 3.0 directly, because you want to remain
-backward-compatible, the Compatibility Library provides your application access to self-contained
-versions of some of the latest APIs that you can use with older versions of Android. Most
-importantly, the library provides implementations of the {@link android.app.Fragment} and {@link
-android.content.Loader} APIs, so you can use them in a way that's compatible with devices running
-Android 1.6 (API level 4) and higher. Thus, you can more easily create a single APK that supports a
-majority of devices and provide larger devices (such as tablets) a fully optimized experience by
-using <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> in your activity
-design.</p>
+<p class="note"><strong>Note:</strong> The Compatibility Package includes more than one support
+library. Each one has a different <em>minimum API level</em>. For example, one library requires API
+level 4 or higher, while another requires API level 13 or higher. The minimum version is indicated
+by the directory name, such as {@code v4/} and {@code v13/}.</p>
 
 
 <h2 id="Notes">Revisions</h2>
 
 <p>The sections below provide notes about successive releases of
-the Compatibility Library, as denoted by revision number.</p>
+the Compatibility Package, as denoted by revision number.</p>
 
 
 <div class="toggle-content open">
 
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" />
-    Compatibility Library, revision 2 (May 2011)
+    Compatibility Package, revision 3 (July 2011)
   </a></p>
 
   <div class="toggle-content-toggleme" style="padding-left:2em"> 
     <dl>
-    <dt>Changes:</dt>
+      <dt>Changes for v4 support library:</dt>
+      <dd>
+        <ul>
+          <li>Adds support for {@link android.app.Fragment.SavedState}</li>
+          <li>Adds {@code MotionEventCompat} to support newer {@link
+android.view.MotionEvent} APIs</li>
+          <li>Adds {@code VelocityTrackerCompat} to support a newer {@link
+android.view.VelocityTracker} APIs</li>
+          <li>Adds {@code ViewConfigurationCompat} to support a newer {@link
+android.view.ViewConfiguration} APIs</li>
+          <li>All new APIs (available only in the support library) that allow you to create UIs
+with horizontal paging, allowing users to swipe left and right between content views. Classes to
+support this include:
+            <ul>
+              <li>{@code ViewPager}: A {@link android.view.ViewGroup} that manages the
+layout for the child views, which the user can swipe between.</li>
+              <li>{@code PagerAdapter}: An adapter that populates the {@code ViewPager} with the
+views that represent each page.</li>
+              <li>{@code FragmentPagerAdapter}: An extension of {@code PagerAdapter} for flipping
+between fragments.</li>
+              <li>{@code FragmentStatePagerAdapter}: An extension of {@code PagerAdapter} for
+flipping between fragments that uses the library's support for {@link
+android.app.Fragment.SavedState}.</li>
+            </ul>
+          </li>
+        </ul>
+      </dd>
+      <dt>New v13 support library:</dt>
+      <dd>
+        <ul>
+          <li>Includes the {@code FragmentPagerAdapter} and {@code FragmentStatePagerAdapter}
+to support the horizontal paging.
+          <p>These are exactly the same as the APIs added to the v4 support library, but rely on
+other platform components in Android 3.2. Use this library instead of v4 if you're developing for
+Android 3.2 and higher (all other APIs in the v4 library are already available with API level
+13).</p>
+          </li>
+        </ul>
+      </dd>
+    </dl>
+  </div>
+
+</div>
+
+
+<div class="toggle-content closed">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" />
+    Compatibility Package, revision 2 (May 2011)
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em"> 
+    <dl>
+    <dt>Changes for v4 library:</dt>
     <dd>
       <ul>
-        <li>Support for fragment animations.</li>
-        <li>Fix {@code Fragment.onActivityResult()} bug.</li>
+        <li>Support for fragment animations</li>
+        <li>Fix {@code Fragment.onActivityResult()} bug</li>
       </ul>
     </dd>
     </dl>
@@ -74,21 +125,21 @@
 
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" />
-    Compatibility Library, revision 1 (March 2011)
+    Compatibility Package, revision 1 (March 2011)
   </a></p>
 
   <div class="toggle-content-toggleme" style="padding-left:2em"> 
-      <p>Initial release of the library.</p>
+      <p>Initial release with the v4 library.</p>
   </div>
 
 </div>
 
 
 
-<h2 id="Installing">Installing the Compatibility Library</h2>
+<h2 id="Downloading">Downloading the Compatibility Package</h2>
 
-<p>The Compatibility Library is provided as a downloadable package from the Android SDK and AVD
-Manager. To install the library:</p>
+<p>The Compatibility Package is provided as a downloadable package from the Android SDK and AVD
+Manager. To install:</p>
 
 <ol>
   <li>Launch the SDK and AVD Manager. 
@@ -101,43 +152,53 @@
   <li>Proceed to install the package.</li>
 </ol>
 
-<p>When done, all files (including source code, samples, and the {@code .jar} file) are saved
-into the <code>&lt;sdk&gt;/extras/android/compatibility/</code> directory. The next directory
-name is {@code v4}, which indicates the lowest compatible version for the library within. That
-is, the code in {@code v4/} supports API level 4 and above. (There may be future libraries that
-have a different minimum version, so they will be saved alongside this one.)</p>
+<p>When done, all files (including source code, samples, and the {@code .jar} files) are saved
+into the <code>&lt;sdk&gt;/extras/android/compatibility/</code> directory. This directory contains
+each of the different support libraries, such as the library for API level 4 and up and the library
+for API level 13 and up, each named with the respective version (such as {@code v4/}).</p>
 
 
-<h2 id="SettingUp">Setting Up a Project to Use the Library</h2>
+<h2 id="SettingUp">Setting Up a Project to Use a Library</h2>
 
-<p>To add the Compatibility Library to your Android project:</p>
+<p>To add one of the libraries to your Android project:</p>
 <ol>
   <li>In your Android project, create a directory named {@code libs} at the root of your
 project (next to {@code src/}, {@code res/}, etc.)</li>
-  <li>Navigate to {@code &lt;sdk&gt;/extras/android/compatibility/v4/}.</li>
-  <li>Copy the {@code android-support-v4.jar} file into your project {@code libs/} directory.</li>
-  <li>Add the JAR to your project build path. In Eclipse, right-click the JAR file in the
-Package Explorer, select <strong>Build Path</strong> &gt; <strong>Add to Build Path</strong>.
-You should then see the JAR file appear in a new directory called Referenced Libraries.</li>
+  <li>Locate the JAR file for the library you want to use and copy it into the {@code
+libs/} directory.
+    <p>For example, the library that supports API level 4 and up is located at {@code
+&lt;sdk&gt;/extras/android/compatibility/v4/android-support-v4.jar}.</p>
+  </li>
+  <li>Add the JAR to your project build path. 
+    <p>In Eclipse, right-click the JAR file in the Package Explorer, select <strong>Build
+Path</strong> &gt; <strong>Add to Build Path</strong>. You should then see the JAR file appear in a
+new directory called Referenced Libraries.</p>
+  </li>
 </ol>
 
-<p>Your application is now ready to use fragments, loaders and other APIs from the library. All the
-provided APIs are in the {@code android.support.v4} package.</p>
+<p>Your application is now ready to use the library APIs. All the
+provided APIs are available in the {@code android.support} package (for
+example, {@code android.support.v4}).</p>
+
+<p class="note"><strong>Tip:</strong> To see the library APIs in action, take a look at the sample
+apps in {@code extras/android/compatibility/&lt;version&gt;/samples/}.</p>
 
 <p class="warning"><strong>Warning:</strong> Be certain that you not confuse the standard
-{@code android} packages with those in {@code android.support.v4}. Some code completion tools might
+{@code android} packages with those in {@code android.support} library. Some code completion tools
+might
 get this wrong, especially if you're building against recent versions of the platform. To be safe,
 keep your build target set to the same version as you have defined for your <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
-and double check the import statements for classes that are duplicated in the Compatibility
-Library, such as {@code SimpleCursorAdapter}.</p>
+and double check the import statements for classes that also exist in the support library, such as
+{@code SimpleCursorAdapter}.</p>
 
 
-<h2 id="Using">Using Some of the Library APIs</h2>
+<h2 id="Using">Using the v4 Library APIs</h2>
 
-<p>The Compatibility Library provides access to several classes introduced with Android 3.0, plus
-some updated version of existing classes. Some of the most useful and notable classes in the
-library are:</p>
+<p>The support library for v4 provides access to several classes introduced with Android 3.0 and
+beyond, plus some updated version of existing classes, and even some APIs that currently don't
+exist in the Android platform. Some of the most useful and notable classes that have
+counterparts in the v4 support library are:</p>
 
 <ul>
   <li>{@link android.app.Fragment}</li>
@@ -152,8 +213,8 @@
 </ul>
 
 <p>For each of the classes above (and others not listed), the APIs work almost exactly the same
-as the counterparts in the latest version of the Android platform. Thus, you can usually refer to
-the latest reference documentation for information about the supported APIs. There are some
+as the counterparts in the latest Android platform. Thus, you can usually refer to
+the online documentation for information about the supported APIs. There are some
 differences, however. Most notably:</p>
 
 <ul>
@@ -181,18 +242,6 @@
 </li>
 </ul>
 
-<p>The Compatibility Library currently does not provide reference documentation for the included
-APIs. To generate your own set, using the {@code javadoc} tool, perform the
-following from a command line:</p>
-
-<pre class="no-pretty-print">
-cd &lt;sdk&gt;/extras/android/compatibility/v4/
-mkdir docs
-javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs
-</pre>
-<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p>
-
-
 <div class="note"><p><strong>Tip:</strong> To enable the Holographic theme on devices
 running Android 3.0 or higher, declare in your manifest file that your application targets
 API level 11. For example:</p>
@@ -208,16 +257,30 @@
 Apps for Android 3.0</a>.</p>
 
 
+<h2 id="Docs">Reference Docs</h2>
+
+<p>The libraries currently do not provide reference documentation for the included APIs. To generate
+your own set using the {@code javadoc} tool, perform the following from a command (as appropriate
+for the library version you're using). In this example, documentation is generated for the v4
+library:</p>
+
+<pre class="no-pretty-print">
+cd &lt;sdk&gt;/extras/android/compatibility/v4/
+mkdir docs
+javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs
+</pre>
+<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p>
+
+
 <h2 id="Samples">Samples</h2>
 
-<p>If you want to see some sample code that uses the Compatibility Library, take a look at the
-<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/support/index.html">API
-Demos</a> sample code that's included with the Samples package you can download from the AVD and SDK
-Manager.</p>
+<p>If you want to see some code that uses the support libraries, samples are included with the
+Compatibility Package, inside each support library directory. For example, at {@code
+extras/android/compatibility/v4/samples/}.</p>
 
 <p>Additionally, the <a href="http://code.google.com/p/iosched/">Google I/O App</a> is a complete
-application that uses the library to provide a single APK for both handsets and tablets and also
-demonstrates some of Android's best practices in Android UI design.</p>
+application that uses the v4 support library to provide a single APK for both handsets and tablets
+and also demonstrates some of Android's best practices in Android UI design.</p>
 
 
 
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index e980ca5..97df84f 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
 ndk=true
 
-ndk.win_download=android-ndk-r5c-windows.zip
-ndk.win_bytes=61627716
-ndk.win_checksum=2c7423842fa0f46871eab118495d4b45
+ndk.win_download=android-ndk-r6-windows.zip
+ndk.win_bytes=67642809
+ndk.win_checksum=9c7d5ccc02151a3e5e950c70dc05ac6d
 
-ndk.mac_download=android-ndk-r5c-darwin-x86.tar.bz2
-ndk.mac_bytes=50714712
-ndk.mac_checksum=183bfbbd85cf8e4c0bd7531e8803e75d
+ndk.mac_download=android-ndk-r6-darwin-x86.tar.bz2
+ndk.mac_bytes=52682746
+ndk.mac_checksum=a154905e49a6246abd823b75b6eda738
 
-ndk.linux_download=android-ndk-r5c-linux-x86.tar.bz2
-ndk.linux_bytes=44539890
-ndk.linux_checksum=7659dfdc97026ed1d913e224d0531f61
+ndk.linux_download=android-ndk-r6-linux-x86.tar.bz2
+ndk.linux_bytes=46425290
+ndk.linux_checksum=ff0a43085fe206696d5cdcef3f4f4637
 
 page.title=Android NDK
 @jd:body
@@ -62,6 +62,58 @@
 <div class="toggleable open">
   <a href="#" onclick="return toggleDiv(this)"><img src=
   "{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px">
+  Android NDK, Revision 6</a> <em>(July 2011)</em>
+
+   <div class="toggleme">
+      <p>This release of the NDK includes support for the x86 ABI and other minor changes.
+      For detailed information describing the changes in this release, read the
+      <code>CHANGES.HTML</code> document included in the NDK package.
+      </p>
+      <dl>
+        <dt>General notes:</dt>
+        <dd>
+          <ul>
+            <li>Adds support for the x86 ABI, which allows you to generate machine code
+            that runs on compatible x86-based Android devices. Major features for x86
+            include x86-specific toolchains, system headers, libraries and
+            debugging support. For all of the details regarding x86 support,
+            see <code>docs/CPU-X86.html</code> in the NDK package.
+
+              <p>By default, code is generated for ARM-based devices, but you can add x86 to your
+              <code>APP_ABI</code> definition in your <code>Application.mk</code> file to build
+              for x86 platforms. For example, the following line instructs <code>ndk-build</code>
+              to build your code for three distinct ABIs:</p>
+
+              <pre>APP_ABI := armeabi armeabi-v7a x86</pre>
+
+              <p>Unless you rely on ARM-based assembly sources, you shouldn't need to touch
+              your <code>Android.mk</code> files to build x86 machine code.</p>
+
+            </li>
+
+            <li>You can build a standalone x86 toolchain using the <code>--toolchain=x86-4.4.3</code>
+            option when calling <code>make-standalone-toolchain.sh</code>. See
+            <code>docs/STANDALONE-TOOLCHAIN.html</code> for more details.
+            </li>
+            <li>The new <code>ndk-stack</code> tool lets you translate stack traces in
+            <code>logcat</code> that are generated by native code. The tool translates
+            instruction addresses into a readable format that contains things such
+            as the function, source file, and line number corresponding to each stack frame.
+            For more information and a usage example, see <code>docs/NDK-STACK.html</code>.
+            </li>
+          </ul>
+        </dd>
+        <dt>Other changes:</dt>
+        <dd><code>arm-eabi-4.4.0</code>, which had been deprecated since NDK r5, has been
+        removed from the NDK distribution.</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">
   Android NDK, Revision 5c</a> <em>(June 2011)</em>
 
   <div class="toggleme">
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index 2562a25..93c664d 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -53,11 +53,7 @@
 
     <li>ARMv7-A (including Thumb-2 and VFPv3-D16 instructions, with optional support for
     NEON/VFPv3-D32 instructions)</li>
-  </ul>
 
-  <p>Future releases of the NDK will also support:</p>
-
-  <ul>
     <li>x86 instructions (see CPU-ARCH-ABIS.HTML for more information)</li>
   </ul>
 
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 0607aad..1b1fc8d 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -76,8 +76,16 @@
     </ul>
     <ul>
       <li class="toggle-list">
+        <div><a href="<?cs var:toroot ?>sdk/android-3.2.html">
+        <span class="en">Android 3.2 Platform</span></a> <span class="new">new!</span></div>
+        <ul>
+          <!-- <li><a href="<?cs var:toroot ?>sdk/android-3.2-highlights.html">Platform Highlights</a></li> -->
+          <li><a href="<?cs var:toroot ?>sdk/api_diff/13/changes.html">API Differences Report &raquo;</a></li>
+        </ul>
+      </li>
+      <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>sdk/android-3.1.html">
-        <span class="en">Android 3.1 Platform</span></a> <span class="new">new!</span></div>
+        <span class="en">Android 3.1 Platform</span></a></div>
         <ul>
           <li><a href="<?cs var:toroot ?>sdk/android-3.1-highlights.html">Platform Highlights</a></li> 
           <li><a href="<?cs var:toroot ?>sdk/api_diff/12/changes.html">API Differences Report &raquo;</a></li>
@@ -91,7 +99,7 @@
           <li><a href="<?cs var:toroot ?>sdk/api_diff/11/changes.html">API Differences Report &raquo;</a></li>
         </ul>
       </li>
-      <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a> <span class="new">new!</span></li>
+      <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a></li>
       <li class="toggle-list">
       <div><a href="<?cs var:toroot ?>sdk/android-2.3.3.html">
       <span class="en">Android 2.3.3 Platform</span></a></div>
@@ -137,8 +145,8 @@
       <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
-class="new">new!</span></li>
+      <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Package,
+r3</a> <span class="new">new!</span></li>
     </ul>
   </li>
   <li>
@@ -175,8 +183,8 @@
       <span style="display:none" class="zh-TW"></span>
     </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5c <span
-       class="new">new!</span></a>
+      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6</a> 
+        <span class="new">new!</span>
         </li>
       <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
     </ul>
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 2d8e877..986f32c 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -110,11 +110,11 @@
     handle->extendedData.clear();
 }
 
-int BpDrmManagerService::addUniqueId(int uniqueId) {
+int BpDrmManagerService::addUniqueId(bool isNative) {
     LOGV("add uniqueid");
     Parcel data, reply;
     data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
-    data.writeInt32(uniqueId);
+    data.writeInt32(isNative);
     remote()->transact(ADD_UNIQUEID, data, &reply);
     return reply.readInt32();
 }
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1809619..3e4fe8c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -49,32 +49,42 @@
 
 }
 
-int DrmManager::addUniqueId(int uniqueId) {
+int DrmManager::addUniqueId(bool isNative) {
     Mutex::Autolock _l(mLock);
-    if (0 == uniqueId) {
-        int temp = 0;
-        bool foundUniqueId = false;
-        srand(time(NULL));
 
-        while (!foundUniqueId) {
-            const int size = mUniqueIdVector.size();
-            temp = rand() % 100;
+    int temp = 0;
+    bool foundUniqueId = false;
+    const int size = mUniqueIdVector.size();
+    const int uniqueIdRange = 0xfff;
+    int maxLoopTimes = (uniqueIdRange - 1) / 2;
+    srand(time(NULL));
 
-            int index = 0;
-            for (; index < size; ++index) {
-                if (mUniqueIdVector.itemAt(index) == temp) {
-                    foundUniqueId = false;
-                    break;
-                }
-            }
-            if (index == size) {
-                foundUniqueId = true;
+    while (!foundUniqueId) {
+        temp = rand() & uniqueIdRange;
+
+        if (isNative) {
+            // set a flag to differentiate DrmManagerClient
+            // created from native side and java side
+            temp |= 0x1000;
+        }
+
+        int index = 0;
+        for (; index < size; ++index) {
+            if (mUniqueIdVector.itemAt(index) == temp) {
+                foundUniqueId = false;
+                break;
             }
         }
-        uniqueId = temp;
+        if (index == size) {
+            foundUniqueId = true;
+        }
+
+        maxLoopTimes --;
+        LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session");
     }
-    mUniqueIdVector.push(uniqueId);
-    return uniqueId;
+
+    mUniqueIdVector.push(temp);
+    return temp;
 }
 
 void DrmManager::removeUniqueId(int uniqueId) {
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 583669e..7ebcac3 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -78,8 +78,8 @@
     delete mDrmManager; mDrmManager = NULL;
 }
 
-int DrmManagerService::addUniqueId(int uniqueId) {
-    return mDrmManager->addUniqueId(uniqueId);
+int DrmManagerService::addUniqueId(bool isNative) {
+    return mDrmManager->addUniqueId(isNative);
 }
 
 void DrmManagerService::removeUniqueId(int uniqueId) {
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index f3a0343..9a7194c 100755
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -248,9 +248,7 @@
         mEventHandler = new EventHandler(eventThread.getLooper());
 
         // save the unique id
-        mUniqueId = hashCode();
-
-        _initialize(mUniqueId, new WeakReference<DrmManagerClient>(this));
+        mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this));
     }
 
     protected void finalize() {
@@ -794,7 +792,7 @@
     }
 
     // private native interfaces
-    private native void _initialize(int uniqueId, Object weak_this);
+    private native int _initialize(Object weak_this);
 
     private native void _finalize(int uniqueId);
 
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index e131839..80a8447 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -224,11 +224,12 @@
     return sp<DrmManagerClientImpl>(client);
 }
 
-static void android_drm_DrmManagerClient_initialize(
-        JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
+static jint android_drm_DrmManagerClient_initialize(
+        JNIEnv* env, jobject thiz, jobject weak_thiz) {
     LOGV("initialize - Enter");
 
-    sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId);
+    int uniqueId = 0;
+    sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
     drmManager->addClient(uniqueId);
 
     // Set the listener to DrmManager
@@ -237,6 +238,8 @@
 
     setDrmManagerClientImpl(env, thiz, drmManager);
     LOGV("initialize - Exit");
+
+    return uniqueId;
 }
 
 static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) {
@@ -711,7 +714,7 @@
 
 static JNINativeMethod nativeMethods[] = {
 
-    {"_initialize", "(ILjava/lang/Object;)V",
+    {"_initialize", "(Ljava/lang/Object;)I",
                                     (void*)android_drm_DrmManagerClient_initialize},
 
     {"_finalize", "(I)V",
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index b50199f..c9c0d57 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -24,7 +24,7 @@
 
 DrmManagerClient::DrmManagerClient():
         mUniqueId(0), mDrmManagerClientImpl(NULL) {
-    mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+    mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true);
     mDrmManagerClientImpl->addClient(mUniqueId);
 }
 
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a36bd4a..67f58ca 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -33,13 +33,10 @@
 sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier;
 const String8 DrmManagerClientImpl::EMPTY_STRING("");
 
-DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
-    if (0 == *pUniqueId) {
-        int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId);
-        *pUniqueId = uniqueId;
-    } else {
-        getDrmManagerService()->addUniqueId(*pUniqueId);
-    }
+DrmManagerClientImpl* DrmManagerClientImpl::create(
+        int* pUniqueId, bool isNative) {
+    *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+
     return new DrmManagerClientImpl();
 }
 
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index af2c2a8..ac2b946 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -53,7 +53,7 @@
     virtual ~DrmManager();
 
 public:
-    int addUniqueId(int uniqueId);
+    int addUniqueId(bool isNative);
 
     void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 564896b..e3338d9 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -38,7 +38,7 @@
     DrmManagerClientImpl() { }
 
 public:
-    static DrmManagerClientImpl* create(int* pUniqueId);
+    static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
 
     static void remove(int uniqueId);
 
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index 227496a..9cb5804 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -46,7 +46,7 @@
     virtual ~DrmManagerService();
 
 public:
-    int addUniqueId(int uniqueId);
+    int addUniqueId(bool isNative);
 
     void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 7727e55..b9618bb 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -81,7 +81,7 @@
     DECLARE_META_INTERFACE(DrmManagerService);
 
 public:
-    virtual int addUniqueId(int uniqueId) = 0;
+    virtual int addUniqueId(bool isNative) = 0;
 
     virtual void removeUniqueId(int uniqueId) = 0;
 
@@ -167,7 +167,7 @@
     BpDrmManagerService(const sp<IBinder>& impl)
             : BpInterface<IDrmManagerService>(impl) {}
 
-    virtual int addUniqueId(int uniqueId);
+    virtual int addUniqueId(bool isNative);
 
     virtual void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index b61e3d3..4a5afcf 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -143,7 +143,13 @@
      * Register a callback to be invoked when the caller required to
      * receive necessary information
      *
-     * @param[in] uniqueId Unique identifier for a session
+     * @param[in] uniqueId Unique identifier for a session. uniqueId is a random
+     *                     number generated in the DRM service. If the DrmManagerClient
+     *                     is created in native code, uniqueId will be a number ranged
+     *                     from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId
+     *                     will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in
+     *                     uniqueId could be used in DRM plugins to differentiate native
+     *                     OnInfoListener and Java OnInfoListener.
      * @param[in] infoListener Listener
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 5b50f8f..35ed4d2 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1414,77 +1414,13 @@
         } else {
             char[] buf = TemporaryBuffer.obtain(end - start);
             TextUtils.getChars(text, start, end, buf, 0);
-            native_drawText(mNativeCanvas, buf, 0, end - start, x, y, 
+            native_drawText(mNativeCanvas, buf, 0, end - start, x, y,
                     paint.mBidiFlags, paint.mNativePaint);
             TemporaryBuffer.recycle(buf);
         }
     }
 
     /**
-     * Draw the text, with origin at (x,y), using the specified paint. The
-     * origin is interpreted based on the Align setting in the paint.
-     *
-     * @param text  The text to be drawn
-     * @param x     The x-coordinate of the origin of the text being drawn
-     * @param y     The y-coordinate of the origin of the text being drawn
-     * @param paint The paint used for the text (e.g. color, size, style)
-     *
-     * @hide
-     *
-     * Used only for BiDi / RTL Tests
-     */
-    public void drawTextWithGlyphs(char[] text, int index, int count, float x, float y,
-                         Paint paint) {
-        if ((index | count | (index + count) |
-            (text.length - index - count)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        native_drawTextWithGlyphs(mNativeCanvas, text, index, count, x, y, paint.mBidiFlags,
-                paint.mNativePaint);
-    }
-
-    /**
-     * Draw the text, with origin at (x,y), using the specified paint. The
-     * origin is interpreted based on the Align setting in the paint.
-     *
-     * @param text  The text to be drawn
-     * @param x     The x-coordinate of the origin of the text being drawn
-     * @param y     The y-coordinate of the origin of the text being drawn
-     * @param paint The paint used for the text (e.g. color, size, style)
-     *
-     * @hide
-     *
-     * Used only for BiDi / RTL Tests
-     */
-    public void drawTextWithGlyphs(String text, float x, float y, Paint paint) {
-        native_drawTextWithGlyphs(mNativeCanvas, text, 0, text.length(), x, y, paint.mBidiFlags,
-                paint.mNativePaint);
-    }
-
-    /**
-     * Draw the glyphs, with origin at (x,y), using the specified paint. The
-     * origin is interpreted based on the Align setting in the paint.
-     *
-     * @param glyphs The glyphs to be drawn
-     * @param x      The x-coordinate of the origin of the text being drawn
-     * @param y      The y-coordinate of the origin of the text being drawn
-     * @param paint  The paint used for the text (e.g. color, size, style)
-     *
-     * @hide
-     *
-     * Used only for BiDi / RTL Tests
-     */
-    public void drawGlyphs(char[] glyphs, int index, int count, float x, float y,
-                         Paint paint) {
-        if ((index | count | (index + count) |
-            (glyphs.length - index - count)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        native_drawGlyphs(mNativeCanvas, glyphs, index, count, x, y, paint.mBidiFlags,
-                paint.mNativePaint);
-    }
-
-    /**
      * Render a run of all LTR or all RTL text, with shaping. This does not run
      * bidi on the provided text, but renders it as a uniform right-to-left or
      * left-to-right run, as indicated by dir. Alignment of the text is as
@@ -1813,16 +1749,6 @@
                                                int start, int end, float x,
                                                float y, int flags, int paint);
 
-    private static native void native_drawTextWithGlyphs(int nativeCanvas, char[] text,
-                                               int index, int count, float x,
-                                               float y, int flags, int paint);
-    private static native void native_drawTextWithGlyphs(int nativeCanvas, String text,
-                                               int start, int end, float x,
-                                               float y, int flags, int paint);
-    private static native void native_drawGlyphs(int nativeCanvas, char[] glyphs,
-                                               int index, int count, float x,
-                                               float y, int flags, int paint);
-
     private static native void native_drawTextRun(int nativeCanvas, String text,
             int start, int end, int contextStart, int contextEnd,
             float x, float y, int flags, int paint);
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 2220f96..7efdc6c 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -33,7 +33,7 @@
  * <p>
  * The simplest way to create a frame-by-frame animation is to define the animation in an XML
  * file, placed in the res/drawable/ folder, and set it as the background to a View object. Then, call
- * {@link #run()} to start the animation.
+ * {@link #start()} to run the animation.
  * <p>
  * An AnimationDrawable defined in XML consists of a single <code>&lt;animation-list></code> element,
  * and a series of nested <code>&lt;item></code> tags. Each item defines a frame of the animation.
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 63e7dd1..2e55c48 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -97,6 +97,13 @@
         }
     }
 
+    /**
+     * @return name of the renderscript object
+     */
+    public String getName() {
+        return mName;
+    }
+
     protected void finalize() throws Throwable {
         if (!mDestroyed) {
             if(mID != 0 && mRS.isAlive()) {
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java
index 6046ee1..b8dd577 100644
--- a/graphics/java/android/renderscript/RSTextureView.java
+++ b/graphics/java/android/renderscript/RSTextureView.java
@@ -29,9 +29,9 @@
 import android.view.TextureView;
 
 /**
- * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
+ * The Texture View for a graphics renderscript (RenderScriptGL)
+ * to draw on.
  *
- * @hide
  */
 public class RSTextureView extends TextureView implements TextureView.SurfaceTextureListener {
     private RenderScriptGL mRS;
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 8b14f99..935b75a 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -200,8 +200,6 @@
     /**
      * Bind an os surface
      *
-     * @hide
-     *
      * @param w
      * @param h
      * @param sur
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 11aa134..d00c428 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -44,7 +44,6 @@
     }
 
     /**
-     * @hide
      * Only intended for use by generated reflected code.
      *
      * @param slot
diff --git a/graphics/java/com/android/internal/graphics/NativeUtils.java b/graphics/java/com/android/internal/graphics/NativeUtils.java
deleted file mode 100644
index c91b7d9..0000000
--- a/graphics/java/com/android/internal/graphics/NativeUtils.java
+++ /dev/null
@@ -1,40 +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.internal.graphics;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-
-public final class NativeUtils {
-    /**
-     * This class is uninstantiable.
-     */
-    private NativeUtils() {
-        // This space intentionally left blank.
-    }
-
-    /**
-     * Scroll a rectangular portion of a canvas.
-     * 
-     * @param canvas the canvas to manipulate
-     * @param src the source rectangle
-     * @param dx horizontal offset
-     * @param dy vertical offset
-     */
-    public static native boolean nativeScrollRect(Canvas canvas, Rect src,
-            int dx, int dy);
-}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 4a85faf..3476bd5 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -504,6 +504,7 @@
     void* ptr = bitmap.getPixels();
     rsAllocationCopyToBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
     bitmap.unlockPixels();
+    bitmap.notifyPixelsChanged();
 }
 
 static void ReleaseBitmapCallback(void *bmp)
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 83d4f6d..d2f398a 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -455,6 +455,16 @@
     // Example: "176x144,1280x720". Read only.
     static const char KEY_SUPPORTED_VIDEO_SIZES[];
 
+    // The maximum number of detected faces supported by hardware face
+    // detection. If the value is 0, hardware face detection is not supported.
+    // Example: "5". Read only
+    static const char KEY_MAX_NUM_DETECTED_FACES_HW[];
+
+    // The maximum number of detected faces supported by software face
+    // detection. If the value is 0, software face detection is not supported.
+    // Example: "5". Read only
+    static const char KEY_MAX_NUM_DETECTED_FACES_SW[];
+
     // Preferred preview frame size in pixels for video recording.
     // The width and height must be one of the supported sizes retrieved
     // via KEY_SUPPORTED_PREVIEW_SIZES. This key can be used only when
diff --git a/include/cpustats/CentralTendencyStatistics.h b/include/cpustats/CentralTendencyStatistics.h
new file mode 100644
index 0000000..21b6981
--- /dev/null
+++ b/include/cpustats/CentralTendencyStatistics.h
@@ -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.
+ */
+
+#ifndef _CENTRAL_TENDENCY_STATISTICS_H
+#define _CENTRAL_TENDENCY_STATISTICS_H
+
+#include <math.h>
+
+// Not multithread safe
+class CentralTendencyStatistics {
+
+public:
+
+    CentralTendencyStatistics() :
+            mMean(NAN), mMedian(NAN), mMinimum(INFINITY), mMaximum(-INFINITY), mN(0), mM2(0),
+            mVariance(NAN), mVarianceKnownForN(0), mStddev(NAN), mStddevKnownForN(0) { }
+
+    ~CentralTendencyStatistics() { }
+
+    // add x to the set of samples
+    void sample(double x);
+
+    // return the arithmetic mean of all samples so far
+    double mean() const { return mMean; }
+
+    // return the minimum of all samples so far
+    double minimum() const { return mMinimum; }
+
+    // return the maximum of all samples so far
+    double maximum() const { return mMaximum; }
+
+    // return the variance of all samples so far
+    double variance() const;
+
+    // return the standard deviation of all samples so far
+    double stddev() const;
+
+    // return the number of samples added so far
+    unsigned n() const { return mN; }
+
+    // reset the set of samples to be empty
+    void reset();
+
+private:
+    double mMean;
+    double mMedian;
+    double mMinimum;
+    double mMaximum;
+    unsigned mN;    // number of samples so far
+    double mM2;
+
+    // cached variance, and n at time of caching
+    mutable double mVariance;
+    mutable unsigned mVarianceKnownForN;
+
+    // cached standard deviation, and n at time of caching
+    mutable double mStddev;
+    mutable unsigned mStddevKnownForN;
+
+};
+
+#endif // _CENTRAL_TENDENCY_STATISTICS_H
diff --git a/include/cpustats/README.txt b/include/cpustats/README.txt
new file mode 100644
index 0000000..14439f0
--- /dev/null
+++ b/include/cpustats/README.txt
@@ -0,0 +1,6 @@
+This is a static library of CPU usage statistics, originally written
+for audio but most are not actually specific to audio.
+
+Requirements to be here:
+ * should be related to CPU usage statistics
+ * should be portable to host; avoid Android OS dependencies without a conditional
diff --git a/include/cpustats/ThreadCpuUsage.h b/include/cpustats/ThreadCpuUsage.h
new file mode 100644
index 0000000..24012a4
--- /dev/null
+++ b/include/cpustats/ThreadCpuUsage.h
@@ -0,0 +1,113 @@
+/*
+ * 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 _THREAD_CPU_USAGE_H
+#define _THREAD_CPU_USAGE_H
+
+#include <cpustats/CentralTendencyStatistics.h>
+
+// Track CPU usage for the current thread, and maintain statistics on
+// the CPU usage.  Units are in per-thread CPU ns, as reported by
+// clock_gettime(CLOCK_THREAD_CPUTIME_ID).  Simple usage: for cyclic
+// threads where you want to measure the execution time of the whole
+// cycle, just call sampleAndEnable() at the start of each cycle.
+// Then call statistics() to get the results, and resetStatistics()
+// to start a new set of measurements.
+// For acyclic threads, or for cyclic threads where you want to measure
+// only part of each cycle, call enable(), disable(), and/or setEnabled()
+// to demarcate the region(s) of interest, and then call sample() periodically.
+// This class is not thread-safe for concurrent calls from multiple threads;
+// the methods of this class may only be called by the current thread
+// which constructed the object.
+
+class ThreadCpuUsage
+{
+
+public:
+    ThreadCpuUsage() :
+        mIsEnabled(false),
+        mWasEverEnabled(false),
+        mAccumulator(0),
+        // mPreviousTs
+        // mMonotonicTs
+        mMonotonicKnown(false)
+        // mStatistics
+        { }
+
+    ~ThreadCpuUsage() { }
+
+    // Return whether currently tracking CPU usage by current thread
+    bool isEnabled()    { return mIsEnabled; }
+
+    // Enable tracking of CPU usage by current thread;
+    // any CPU used from this point forward will be tracked.
+    // Returns the previous enabled status.
+    bool enable()       { return setEnabled(true); }
+
+    // Disable tracking of CPU usage by current thread;
+    // any CPU used from this point forward will be ignored.
+    // Returns the previous enabled status.
+    bool disable()      { return setEnabled(false); }
+
+    // Set the enabled status and return the previous enabled status.
+    // This method is intended to be used for safe nested enable/disabling.
+    bool setEnabled(bool isEnabled);
+
+    // Add a sample point for central tendency statistics, and also
+    // enable tracking if needed.  If tracking has never been enabled, then
+    // enables tracking but does not add a sample (it is not possible to add
+    // a sample the first time because no previous).  Otherwise if tracking is
+    // enabled, then adds a sample for tracked CPU ns since the previous
+    // sample, or since the first call to sampleAndEnable(), enable(), or
+    // setEnabled(true).  If there was a previous sample but tracking is
+    // now disabled, then adds a sample for the tracked CPU ns accumulated
+    // up until the most recent disable(), resets this accumulator, and then
+    // enables tracking.  Calling this method rather than enable() followed
+    // by sample() avoids a race condition for the first sample.
+    void sampleAndEnable();
+
+    // Add a sample point for central tendency statistics, but do not
+    // change the tracking enabled status.  If tracking has either never been
+    // enabled, or has never been enabled since the last sample, then log a warning
+    // and don't add sample.  Otherwise, adds a sample for tracked CPU ns since
+    // the previous sample or since the first call to sampleAndEnable(),
+    // enable(), or setEnabled(true) if no previous sample.
+    void sample();
+
+    // Return the elapsed delta wall clock ns since initial enable or statistics reset,
+    // as reported by clock_gettime(CLOCK_MONOTONIC).
+    long long elapsed() const;
+
+    // Reset statistics and elapsed.  Has no effect on tracking or accumulator.
+    void resetStatistics();
+
+    // Return a const reference to the central tendency statistics.
+    // Note that only the const methods can be called on this object.
+    const CentralTendencyStatistics& statistics() const {
+        return mStatistics;
+    }
+
+private:
+    bool mIsEnabled;                // whether tracking is currently enabled
+    bool mWasEverEnabled;           // whether tracking was ever enabled
+    long long mAccumulator;         // accumulated thread CPU time since last sample, in ns
+    struct timespec mPreviousTs;    // most recent thread CPU time, valid only if mIsEnabled is true
+    struct timespec mMonotonicTs;   // most recent monotonic time
+    bool mMonotonicKnown;           // whether mMonotonicTs has been set
+    CentralTendencyStatistics mStatistics;
+};
+
+#endif //  _THREAD_CPU_USAGE_H
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index e705c6f..1eda646 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -51,7 +51,7 @@
     // the given slot index, and the client is expected to mirror the
     // slot->buffer mapping so that it's not necessary to transfer a
     // GraphicBuffer for every dequeue operation.
-    virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
 
     // setBufferCount sets the number of buffer slots available. Calling this
     // will also cause all buffer slots to be emptied. The caller should empty
@@ -78,7 +78,12 @@
     // client for this buffer. The timestamp is measured in nanoseconds, and
     // must be monotonically increasing. Its other properties (zero point, etc)
     // are client-dependent, and should be documented by the client.
-    virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
+    //
+    // outWidth, outHeight and outTransform are filled with the default width
+    // and height of the window and current transform applied to buffers,
+    // respectively.
+    virtual status_t queueBuffer(int slot, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) = 0;
 
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
@@ -87,12 +92,7 @@
 
     virtual status_t setCrop(const Rect& reg) = 0;
     virtual status_t setTransform(uint32_t transform) = 0;
-
-    // getAllocator retrieves the binder object that must be referenced as long
-    // as the GraphicBuffers dequeued from this ISurfaceTexture are referenced.
-    // Holding this binder reference prevents SurfaceFlinger from freeing the
-    // buffers before the client is done with them.
-    virtual sp<IBinder> getAllocator() = 0;
+    virtual status_t setScalingMode(int mode) = 0;
 
     // query retrieves some information for this surface
     // 'what' tokens allowed are that of android_natives.h
@@ -104,6 +104,24 @@
     // queued buffers will be retired in order.
     // The default mode is asynchronous.
     virtual status_t setSynchronousMode(bool enabled) = 0;
+
+    // connect attempts to connect a client API to the SurfaceTexture.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceTexture and no corresponding disconnect call was made.
+    virtual status_t connect(int api) = 0;
+
+    // disconnect attempts to disconnect a client API from the SurfaceTexture.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceTexture is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index e36360c..2a8e725 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -44,6 +44,7 @@
         MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
     };
     enum { NUM_BUFFER_SLOTS = 32 };
+    enum { NO_CONNECTED_API = 0 };
 
     struct FrameAvailableListener : public virtual RefBase {
         // onFrameAvailable() is called from queueBuffer() each time an
@@ -68,7 +69,7 @@
     // SurfaceTexture object (i.e. they are not owned by the client).
     virtual status_t setBufferCount(int bufferCount);
 
-    virtual sp<GraphicBuffer> requestBuffer(int buf);
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
 
     // dequeueBuffer gets the next buffer slot index for the client to use. If a
     // buffer slot is available then that slot index is written to the location
@@ -83,10 +84,12 @@
     // nanoseconds, and must be monotonically increasing. Its other semantics
     // (zero point, etc) are client-dependent and should be documented by the
     // client.
-    virtual status_t queueBuffer(int buf, int64_t timestamp);
+    virtual status_t queueBuffer(int buf, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
     virtual void cancelBuffer(int buf);
     virtual status_t setCrop(const Rect& reg);
     virtual status_t setTransform(uint32_t transform);
+    virtual status_t setScalingMode(int mode);
 
     virtual int query(int what, int* value);
 
@@ -97,6 +100,24 @@
     // The default mode is asynchronous.
     virtual status_t setSynchronousMode(bool enabled);
 
+    // connect attempts to connect a client API to the SurfaceTexture.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceTexture and no corresponding disconnect call was made.
+    virtual status_t connect(int api);
+
+    // disconnect attempts to disconnect a client API from the SurfaceTexture.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceTexture is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api);
+
     // updateTexImage sets the image contents of the target texture to that of
     // the most recently queued buffer.
     //
@@ -166,6 +187,20 @@
     // getCurrentTransform returns the transform of the current buffer
     uint32_t getCurrentTransform() const;
 
+    // getCurrentScalingMode returns the scaling mode of the current buffer
+    uint32_t getCurrentScalingMode() const;
+
+    // abandon frees all the buffers and puts the SurfaceTexture into the
+    // 'abandoned' state.  Once put in this state the SurfaceTexture can never
+    // leave it.  When in the 'abandoned' state, all methods of the
+    // ISurfaceTexture interface will fail with the NO_INIT error.
+    //
+    // Note that while calling this method causes all the buffers to be freed
+    // from the perspective of the the SurfaceTexture, if there are additional
+    // references on the buffers (e.g. if a buffer is referenced by a client or
+    // by OpenGL ES as a texture) then those buffer will remain allocated.
+    void abandon();
+
     // dump our state in a String
     void dump(String8& result) const;
     void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@@ -176,7 +211,6 @@
     // all slots.
     void freeAllBuffers();
     static bool isExternalFormat(uint32_t format);
-    static GLenum getTextureTarget(uint32_t format);
 
 private:
 
@@ -201,6 +235,7 @@
               mBufferState(BufferSlot::FREE),
               mRequestBufferCalled(false),
               mTransform(0),
+              mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
               mTimestamp(0) {
             mCrop.makeInvalid();
         }
@@ -262,6 +297,11 @@
         // slot.
         uint32_t mTransform;
 
+        // mScalingMode is the current scaling mode for this buffer slot. This
+        // gets set to mNextScalingMode each time queueBuffer gets called for
+        // this slot.
+        uint32_t mScalingMode;
+
         // mTimestamp is the current timestamp for this buffer slot. This gets
         // to set by queueBuffer each time this slot is queued.
         int64_t mTimestamp;
@@ -307,31 +347,30 @@
     // reset mCurrentTexture to INVALID_BUFFER_SLOT.
     int mCurrentTexture;
 
-    // mCurrentTextureTarget is the GLES texture target to be used with the
-    // current texture.
-    GLenum mCurrentTextureTarget;
-
     // mCurrentTextureBuf is the graphic buffer of the current texture. It's
     // possible that this buffer is not associated with any buffer slot, so we
-    // must track it separately in order to properly use
-    // IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+    // must track it separately in order to support the getCurrentBuffer method.
     sp<GraphicBuffer> mCurrentTextureBuf;
 
     // mCurrentCrop is the crop rectangle that applies to the current texture.
-    // It gets set to mLastQueuedCrop each time updateTexImage is called.
+    // It gets set each time updateTexImage is called.
     Rect mCurrentCrop;
 
     // mCurrentTransform is the transform identifier for the current texture. It
-    // gets set to mLastQueuedTransform each time updateTexImage is called.
+    // gets set each time updateTexImage is called.
     uint32_t mCurrentTransform;
 
+    // mCurrentScalingMode is the scaling mode for the current texture. It gets
+    // set to each time updateTexImage is called.
+    uint32_t mCurrentScalingMode;
+
     // mCurrentTransformMatrix is the transform matrix for the current texture.
     // It gets computed by computeTransformMatrix each time updateTexImage is
     // called.
     float mCurrentTransformMatrix[16];
 
     // mCurrentTimestamp is the timestamp for the current texture. It
-    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+    // gets set each time updateTexImage is called.
     int64_t mCurrentTimestamp;
 
     // mNextCrop is the crop rectangle that will be used for the next buffer
@@ -342,6 +381,10 @@
     // buffer that gets queued. It is set by calling setTransform.
     uint32_t mNextTransform;
 
+    // mNextScalingMode is the scaling mode that will be used for the next
+    // buffers that get queued. It is set by calling setScalingMode.
+    int mNextScalingMode;
+
     // 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
     // changed with a call to setTexName.
@@ -362,6 +405,11 @@
     // mAllowSynchronousMode whether we allow synchronous mode or not
     const bool mAllowSynchronousMode;
 
+    // mConnectedApi indicates the API that is currently connected to this
+    // SurfaceTexture.  It defaults to NO_CONNECTED_API (= 0), and gets updated
+    // by the connect and disconnect methods.
+    int mConnectedApi;
+
     // mDequeueCondition condition used for dequeueBuffer in synchronous mode
     mutable Condition mDequeueCondition;
 
@@ -369,6 +417,13 @@
     typedef Vector<int> Fifo;
     Fifo mQueue;
 
+    // mAbandoned indicates that the SurfaceTexture will no longer be used to
+    // consume images buffers pushed to it using the ISurfaceTexture interface.
+    // It is initialized to false, and set to true in the abandon method.  A
+    // SurfaceTexture that has been abandoned will return the NO_INIT error from
+    // all ISurfaceTexture methods capable of returning an error.
+    bool mAbandoned;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 9db7364..57f9e15 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -21,6 +21,7 @@
 #include <gui/SurfaceTexture.h>
 
 #include <ui/egl/android_natives.h>
+#include <ui/Region.h>
 
 #include <utils/RefBase.h>
 #include <utils/threads.h>
@@ -37,29 +38,24 @@
 
     sp<ISurfaceTexture> getISurfaceTexture() const;
 
-private:
-    friend class Surface;
+protected:
+    SurfaceTextureClient();
+    void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture);
 
+private:
     // can't be copied
     SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs);
     SurfaceTextureClient(const SurfaceTextureClient& rhs);
+    void init();
 
     // ANativeWindow hooks
-    static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
-    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int perform(ANativeWindow* window, int operation, ...);
-    static int query(const ANativeWindow* window, int what, int* value);
-    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int setSwapInterval(ANativeWindow* window, int interval);
-
-    int cancelBuffer(ANativeWindowBuffer* buffer);
-    int dequeueBuffer(ANativeWindowBuffer** buffer);
-    int lockBuffer(ANativeWindowBuffer* buffer);
-    int perform(int operation, va_list args);
-    int query(int what, int* value) const;
-    int queueBuffer(ANativeWindowBuffer* buffer);
-    int setSwapInterval(int interval);
+    static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
+    static int hook_lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int hook_perform(ANativeWindow* window, int operation, ...);
+    static int hook_query(const ANativeWindow* window, int what, int* value);
+    static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int hook_setSwapInterval(ANativeWindow* window, int interval);
 
     int dispatchConnect(va_list args);
     int dispatchDisconnect(va_list args);
@@ -67,39 +63,49 @@
     int dispatchSetBuffersGeometry(va_list args);
     int dispatchSetBuffersDimensions(va_list args);
     int dispatchSetBuffersFormat(va_list args);
+    int dispatchSetScalingMode(va_list args);
     int dispatchSetBuffersTransform(va_list args);
     int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
     int dispatchSetUsage(va_list args);
+    int dispatchLock(va_list args);
+    int dispatchUnlockAndPost(va_list args);
 
-    int connect(int api);
-    int disconnect(int api);
-    int setBufferCount(int bufferCount);
-    int setBuffersDimensions(int w, int h);
-    int setBuffersFormat(int format);
-    int setBuffersTransform(int transform);
-    int setBuffersTimestamp(int64_t timestamp);
-    int setCrop(Rect const* rect);
-    int setUsage(uint32_t reqUsage);
+protected:
+    virtual int cancelBuffer(ANativeWindowBuffer* buffer);
+    virtual int dequeueBuffer(ANativeWindowBuffer** buffer);
+    virtual int lockBuffer(ANativeWindowBuffer* buffer);
+    virtual int perform(int operation, va_list args);
+    virtual int query(int what, int* value) const;
+    virtual int queueBuffer(ANativeWindowBuffer* buffer);
+    virtual int setSwapInterval(int interval);
 
-    void freeAllBuffers();
-    int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
-
-    int getConnectedApi() const;
+    virtual int connect(int api);
+    virtual int disconnect(int api);
+    virtual int setBufferCount(int bufferCount);
+    virtual int setBuffersDimensions(int w, int h);
+    virtual int setBuffersFormat(int format);
+    virtual int setScalingMode(int mode);
+    virtual int setBuffersTransform(int transform);
+    virtual int setBuffersTimestamp(int64_t timestamp);
+    virtual int setCrop(Rect const* rect);
+    virtual int setUsage(uint32_t reqUsage);
+    virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
+    virtual int unlockAndPost();
 
     enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS };
     enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
 
+private:
+    void freeAllBuffers();
+    int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
+
     // mSurfaceTexture is the interface to the surface texture server. All
     // operations on the surface texture client ultimately translate into
     // interactions with the server using this interface.
     sp<ISurfaceTexture> mSurfaceTexture;
 
-    // mAllocator is the binder object that is referenced to prevent the
-    // dequeued buffers from being freed prematurely.
-    sp<IBinder> mAllocator;
-
     // mSlots stores the buffers that have been allocated for each buffer slot.
     // It is initialized to null pointers, and gets filled in with the result of
     // ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
@@ -129,25 +135,28 @@
     // a timestamp is auto-generated when queueBuffer is called.
     int64_t mTimestamp;
 
-    // mConnectedApi holds the currently connected API to this surface
-    int mConnectedApi;
+    // mDefaultWidth is default width of the window, regardless of the
+    // native_window_set_buffers_dimensions call
+    uint32_t mDefaultWidth;
 
-    // mQueryWidth is the width returned by query(). It is set to width
-    // of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
-    uint32_t mQueryWidth;
+    // mDefaultHeight is default width of the window, regardless of the
+    // native_window_set_buffers_dimensions call
+    uint32_t mDefaultHeight;
 
-    // mQueryHeight is the height returned by query(). It is set to height
-    // of the last dequeued buffer or to mReqHeight if no buffer was dequeued.
-    uint32_t mQueryHeight;
-
-    // mQueryFormat is the format returned by query(). It is set to the last
-    // dequeued format or to mReqFormat if no buffer was dequeued.
-    uint32_t mQueryFormat;
+    // mTransformHint is the transform probably applied to buffers of this
+    // window. this is only a hint, actual transform may differ.
+    uint32_t mTransformHint;
 
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
     mutable Mutex mMutex;
+
+    // must be used from the lock/unlock thread
+    sp<GraphicBuffer>           mLockedBuffer;
+    sp<GraphicBuffer>           mPostedBuffer;
+    mutable Region              mOldDirtyRegion;
+    bool                        mConnectedToCpu;
 };
 
 }; // namespace android
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index dd93fd8c1..1417416 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 
 #include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
 #include <media/IEffect.h>
 #include <media/IEffectClient.h>
 #include <hardware/audio_effect.h>
@@ -111,6 +112,36 @@
 
 
     /*
+     * Returns a list of descriptors corresponding to the pre processings enabled by default
+     * on an AudioRecord with the supplied audio session ID.
+     *
+     * Parameters:
+     *      audioSession:  audio session ID.
+     *      descriptors: address where the effect descriptors should be returned.
+     *      count: as input, the maximum number of descriptor than should be returned
+     *             as output, the number of descriptor returned if status is NO_ERROR or the actual
+     *             number of enabled pre processings if status is NO_MEMORY
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      NO_MEMORY       the number of descriptor to return is more than the maximum number
+     *                      indicated by count.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid audio session or descriptor pointers
+     *
+     * Returned value
+     *   *descriptor updated with descriptors of pre processings enabled by default
+     *   *count      number of descriptors returned if returned status is N_ERROR.
+     *               total number of pre processing enabled by default if returned status is
+     *               NO_MEMORY. This happens if the count passed as input is less than the number
+     *               of descriptors to return
+     */
+    static status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count);
+
+    /*
      * Events used by callback function (effect_callback_t).
      */
     enum event_type {
@@ -188,7 +219,7 @@
      * sessionID:   audio session this effect is associated to. If 0, the effect will be global to
      *      the output mix. If not 0, the effect will be applied to all players
      *      (AudioTrack or MediaPLayer) within the same audio session.
-     * output:  HAL audio output stream to which this effect must be attached. Leave at 0 for
+     * io:  HAL audio output or input stream to which this effect must be attached. Leave at 0 for
      *      automatic output selection by AudioFlinger.
      */
 
@@ -198,7 +229,7 @@
                   effect_callback_t cbf = 0,
                   void* user = 0,
                   int sessionId = 0,
-                  audio_io_handle_t output = 0
+                  audio_io_handle_t io = 0
                   );
 
     /* Constructor.
@@ -210,7 +241,7 @@
                     effect_callback_t cbf = 0,
                     void* user = 0,
                     int sessionId = 0,
-                    audio_io_handle_t output = 0
+                    audio_io_handle_t io = 0
                     );
 
     /* Terminates the AudioEffect and unregisters it from AudioFlinger.
@@ -232,7 +263,7 @@
                             effect_callback_t cbf = 0,
                             void* user = 0,
                             int sessionId = 0,
-                            audio_io_handle_t output = 0
+                            audio_io_handle_t io = 0
                             );
 
     /* Result of constructing the AudioEffect. This must be checked
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 89213b7..f20e234 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -160,7 +160,8 @@
                                     uint32_t samplingRate = 0,
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = AUDIO_CHANNEL_IN_MONO,
-                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0);
+                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+                                    int sessionId = 0);
     static status_t startInput(audio_io_handle_t input);
     static status_t stopInput(audio_io_handle_t input);
     static void releaseInput(audio_io_handle_t input);
@@ -175,7 +176,7 @@
 
     static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     static status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id);
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 0fc8dbf..ed265e1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -65,7 +65,8 @@
                                     uint32_t samplingRate = 0,
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = 0,
-                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0) = 0;
+                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+                                    int audioSession = 0) = 0;
     virtual status_t startInput(audio_io_handle_t input) = 0;
     virtual status_t stopInput(audio_io_handle_t input) = 0;
     virtual void releaseInput(audio_io_handle_t input) = 0;
@@ -78,12 +79,15 @@
     virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0;
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id) = 0;
     virtual status_t unregisterEffect(int id) = 0;
     virtual bool     isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count) = 0;
 };
 
 
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index a73267d..ec84e25 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -26,6 +26,7 @@
 class ICamera;
 class ICameraRecordingProxy;
 class IMediaRecorderClient;
+class ISurfaceTexture;
 
 class IMediaRecorder: public IInterface
 {
@@ -42,7 +43,6 @@
     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;
@@ -55,6 +55,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 3c65147..02ad703 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -184,6 +184,11 @@
             uint32_t flags = 0);
 };
 
+struct CodecProfileLevel {
+    OMX_U32 mProfile;
+    OMX_U32 mLevel;
+};
+
 }  // namespace android
 
 #endif  // ANDROID_IOMX_H_
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index ed26e63..69d5001 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -45,6 +45,18 @@
     CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1006,
 };
 
+/**
+ *Set CIF as default maximum import and export resolution of video editor.
+ *The maximum import and export resolutions are platform specific,
+ *which should be defined in media_profiles.xml.
+ */
+enum videoeditor_capability {
+    VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352,
+    VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288,
+    VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352,
+    VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288,
+};
+
 enum video_decoder {
     VIDEO_DECODER_WMV,
 };
@@ -117,6 +129,17 @@
     int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
 
     /**
+     * Returns the value for the given param name for the video editor cap
+     * param or -1 if error.
+     * Supported param name are:
+     * videoeditor.input.width.max - max input video frame width
+     * videoeditor.input.height.max - max input video frame height
+     * videoeditor.output.width.max - max output video frame width
+     * videoeditor.output.height.max - max output video frame height
+     */
+    int getVideoEditorCapParamByName(const char *name) const;
+
+    /**
      * Returns the audio encoders supported.
      */
     Vector<audio_encoder> getAudioEncoders() const;
@@ -164,7 +187,7 @@
 
     MediaProfiles& operator=(const MediaProfiles&);  // Don't call me
     MediaProfiles(const MediaProfiles&);             // Don't call me
-    MediaProfiles() {}                               // Dummy default constructor
+    MediaProfiles() { mVideoEditorCap = NULL; }        // Dummy default constructor
     ~MediaProfiles();                                // Don't delete me
 
     struct VideoCodec {
@@ -310,6 +333,22 @@
         Vector<int> mLevels;
     };
 
+    struct VideoEditorCap {
+        VideoEditorCap(int inFrameWidth, int inFrameHeight,
+            int outFrameWidth, int outFrameHeight)
+            : mMaxInputFrameWidth(inFrameWidth),
+              mMaxInputFrameHeight(inFrameHeight),
+              mMaxOutputFrameWidth(outFrameWidth),
+              mMaxOutputFrameHeight(outFrameHeight) {}
+
+        ~VideoEditorCap() {}
+
+        int mMaxInputFrameWidth;
+        int mMaxInputFrameHeight;
+        int mMaxOutputFrameWidth;
+        int mMaxOutputFrameHeight;
+    };
+
     int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
     void initRequiredProfileRefs(const Vector<int>& cameraIds);
     int getRequiredProfileRefIndex(int cameraId);
@@ -321,6 +360,7 @@
     static void logAudioEncoderCap(const AudioEncoderCap& cap);
     static void logVideoDecoderCap(const VideoDecoderCap& cap);
     static void logAudioDecoderCap(const AudioDecoderCap& cap);
+    static void logVideoEditorCap(const VideoEditorCap& cap);
 
     // If the xml configuration file does exist, use the settings
     // from the xml
@@ -332,6 +372,8 @@
     static VideoDecoderCap* createVideoDecoderCap(const char **atts);
     static VideoEncoderCap* createVideoEncoderCap(const char **atts);
     static AudioEncoderCap* createAudioEncoderCap(const char **atts);
+    static VideoEditorCap* createVideoEditorCap(
+                const char **atts, MediaProfiles *profiles);
 
     static CamcorderProfile* createCamcorderProfile(
                 int cameraId, const char **atts, Vector<int>& cameraIds);
@@ -375,6 +417,7 @@
     static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
     static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles);
     static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles);
+    static void createDefaultVideoEditorCap(MediaProfiles *profiles);
     static VideoEncoderCap* createDefaultH263VideoEncoderCap();
     static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
     static AudioEncoderCap* createDefaultAmrNBEncoderCap();
@@ -431,6 +474,7 @@
 
     RequiredProfiles *mRequiredProfileRefs;
     Vector<int>              mCameraIds;
+    VideoEditorCap* mVideoEditorCap;
 };
 
 }; // namespace android
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 1c08969..ef799f5 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -26,6 +26,7 @@
 
 class ICameraRecordingProxy;
 class Surface;
+class ISurfaceTexture;
 
 struct MediaRecorderBase {
     MediaRecorderBase() {}
@@ -54,6 +55,7 @@
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() const = 0;
 
 private:
     MediaRecorderBase(const MediaRecorderBase &);
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index ea5a9d3..1a67671 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -25,6 +25,8 @@
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 
+class ANativeWindow;
+
 namespace android {
 
 class Surface;
@@ -128,13 +130,22 @@
     MEDIA_PLAYER_PLAYBACK_COMPLETE  = 1 << 7
 };
 
-enum media_set_parameter_keys {
-    KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
-    KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,
+// Keep KEY_PARAMETER_* in sync with MediaPlayer.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get.  But as of now, all parameters are either set only or get only.
+enum media_parameter_keys {
+    KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,                // set only
+    KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,     // set only
 
     // Streaming/buffering parameters
-    KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
+    KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,            // set only
+
+    // Return a Parcel containing a single int, which is the channel count of the
+    // audio track, or zero for error (e.g. no audio track) or unknown.
+    KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200,                   // get only
+
 };
+
 // ----------------------------------------------------------------------------
 // ref-counted object for callbacks
 class MediaPlayerListener: virtual public RefBase
@@ -196,6 +207,8 @@
             status_t        prepareAsync_l();
             status_t        getDuration_l(int *msec);
             status_t        setDataSource(const sp<IMediaPlayer>& player);
+            void            disconnectNativeWindow();
+            status_t        reset_l();
 
     sp<IMediaPlayer>            mPlayer;
     thread_id_t                 mLockThreadId;
@@ -218,6 +231,8 @@
     int                         mVideoHeight;
     int                         mAudioSessionId;
     float                       mSendLevel;
+    sp<ANativeWindow>           mConnectedWindow;
+    sp<IBinder>                 mConnectedWindowBinder;
 };
 
 }; // namespace android
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index af12d3c..30db642 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -31,12 +31,15 @@
 class IMediaRecorder;
 class ICamera;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
+class SurfaceTextureClient;
 
 typedef void (*media_completion_f)(status_t status, void *cookie);
 
 enum video_source {
     VIDEO_SOURCE_DEFAULT = 0,
     VIDEO_SOURCE_CAMERA = 1,
+    VIDEO_SOURCE_GRALLOC_BUFFER = 2,
 
     VIDEO_SOURCE_LIST_END  // must be last - used to validate audio source type
 };
@@ -212,7 +215,6 @@
     status_t    setAudioEncoder(int ae);
     status_t    setOutputFile(const char* path);
     status_t    setOutputFile(int fd, int64_t offset, int64_t length);
-    status_t    setOutputFileAuxiliary(int fd);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
     status_t    setParameters(const String8& params);
@@ -226,6 +228,7 @@
     status_t    close();
     status_t    release();
     void        notify(int msg, int ext1, int ext2);
+    sp<ISurfaceTexture>     querySurfaceMediaSourceFromMediaServer();
 
 private:
     void                    doCleanUp();
@@ -233,13 +236,18 @@
 
     sp<IMediaRecorder>          mMediaRecorder;
     sp<MediaRecorderListener>   mListener;
+
+    // Reference toISurfaceTexture
+    // for encoding GL Frames. That is useful only when the
+    // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
+    sp<ISurfaceTexture>         mSurfaceMediaSource;
+
     media_recorder_states       mCurrentState;
     bool                        mIsAudioSourceSet;
     bool                        mIsVideoSourceSet;
     bool                        mIsAudioEncoderSet;
     bool                        mIsVideoEncoderSet;
     bool                        mIsOutputFileSet;
-    bool                        mIsAuxiliaryOutputFileSet;
     Mutex                       mLock;
     Mutex                       mNotifyLock;
 };
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
index 765c039..803bffb 100644
--- a/include/media/mediascanner.h
+++ b/include/media/mediascanner.h
@@ -23,23 +23,33 @@
 #include <utils/Errors.h>
 #include <pthread.h>
 
+struct dirent;
+
 namespace android {
 
 class MediaScannerClient;
 class StringArray;
 
+enum MediaScanResult {
+    // This file or directory was scanned successfully.
+    MEDIA_SCAN_RESULT_OK,
+    // This file or directory was skipped because it was not found, could
+    // not be opened, was of an unsupported type, or was malfored in some way.
+    MEDIA_SCAN_RESULT_SKIPPED,
+    // The scan should be aborted due to a fatal error such as out of memory
+    // or an exception.
+    MEDIA_SCAN_RESULT_ERROR,
+};
+
 struct MediaScanner {
     MediaScanner();
     virtual ~MediaScanner();
 
-    virtual status_t processFile(
-            const char *path, const char *mimeType,
-            MediaScannerClient &client) = 0;
+    virtual MediaScanResult processFile(
+            const char *path, const char *mimeType, MediaScannerClient &client) = 0;
 
-    typedef bool (*ExceptionCheck)(void* env);
-    virtual status_t processDirectory(
-            const char *path, MediaScannerClient &client,
-            ExceptionCheck exceptionCheck, void *exceptionEnv);
+    virtual MediaScanResult processDirectory(
+            const char *path, MediaScannerClient &client);
 
     void setLocale(const char *locale);
 
@@ -53,9 +63,11 @@
     // current locale (like "ja_JP"), created/destroyed with strdup()/free()
     char *mLocale;
 
-    status_t doProcessDirectory(
-            char *path, int pathRemaining, MediaScannerClient &client,
-            bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv);
+    MediaScanResult doProcessDirectory(
+            char *path, int pathRemaining, MediaScannerClient &client, bool noMedia);
+    MediaScanResult doProcessDirectoryEntry(
+            char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+            struct dirent* entry, char* fileSpot);
 
     MediaScanner(const MediaScanner &);
     MediaScanner &operator=(const MediaScanner &);
@@ -68,13 +80,13 @@
     virtual ~MediaScannerClient();
     void setLocale(const char* locale);
     void beginFile();
-    bool addStringTag(const char* name, const char* value);
+    status_t addStringTag(const char* name, const char* value);
     void endFile();
 
-    virtual bool scanFile(const char* path, long long lastModified,
+    virtual status_t scanFile(const char* path, long long lastModified,
             long long fileSize, bool isDirectory, bool noMedia) = 0;
-    virtual bool handleStringTag(const char* name, const char* value) = 0;
-    virtual bool setMimeType(const char* mimeType) = 0;
+    virtual status_t handleStringTag(const char* name, const char* value) = 0;
+    virtual status_t setMimeType(const char* mimeType) = 0;
 
 protected:
     void convertValues(uint32_t encoding);
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index f07ebba..0e264c7 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -53,27 +53,10 @@
     void startQuickReadReturns();
 
 private:
-    // If true, will use still camera takePicture() for time lapse frames
-    // If false, will use the videocamera frames instead.
-    bool mUseStillCameraForTimeLapse;
-
-    // Size of picture taken from still camera. This may be larger than the size
-    // of the video, as still camera may not support the exact video resolution
-    // demanded. See setPictureSizeToClosestSupported().
-    int32_t mPictureWidth;
-    int32_t mPictureHeight;
-
     // size of the encoded video.
     int32_t mVideoWidth;
     int32_t mVideoHeight;
 
-    // True if we need to crop the still camera image to get the video frame.
-    bool mNeedCropping;
-
-    // Start location of the cropping rectangle.
-    int32_t mCropRectStartX;
-    int32_t mCropRectStartY;
-
     // Time between capture of two frames during time lapse recording
     // Negative value indicates that timelapse is disabled.
     int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -84,9 +67,6 @@
     // Real timestamp of the last encoded time lapse frame
     int64_t mLastTimeLapseFrameRealTimestampUs;
 
-    // Thread id of thread which takes still picture and sleeps in a loop.
-    pthread_t mThreadTimeLapse;
-
     // Variable set in dataCallbackTimestamp() to help skipCurrentFrame()
     // to know if current frame needs to be skipped.
     bool mSkipCurrentFrame;
@@ -111,9 +91,6 @@
     // Lock for accessing quick stop variables.
     Mutex mQuickStopLock;
 
-    // Condition variable to wake up still picture thread.
-    Condition mTakePictureCondition;
-
     // mQuickStop is set to true if we use quick read() returns, otherwise it is set
     // to false. Once in this mode read() return a copy of the last read frame
     // with the same time stamp. See startQuickReadReturns().
@@ -148,32 +125,13 @@
     // Wrapper over CameraSource::read() to implement quick stop.
     virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
 
-    // For still camera case starts a thread which calls camera's takePicture()
-    // in a loop. For video camera case, just starts the camera's video recording.
-    virtual void startCameraRecording();
-
-    // For still camera case joins the thread created in startCameraRecording().
     // For video camera case, just stops the camera's video recording.
     virtual void stopCameraRecording();
 
-    // For still camera case don't need to do anything as memory is locally
-    // allocated with refcounting.
-    // For video camera case just tell the camera to release the frame.
-    virtual void releaseRecordingFrame(const sp<IMemory>& frame);
-
     // mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
     // frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
     virtual bool skipCurrentFrame(int64_t timestampUs);
 
-    // Handles the callback to handle raw frame data from the still camera.
-    // Creates a copy of the frame data as the camera can reuse the frame memory
-    // once this callback returns. The function also sets a new timstamp corresponding
-    // to one frame time ahead of the last encoded frame's time stamp. It then
-    // calls dataCallbackTimestamp() of the base class with the copied data and the
-    // modified timestamp, which will think that it recieved the frame from a video
-    // camera and proceed as usual.
-    virtual void dataCallback(int32_t msgType, const sp<IMemory> &data);
-
     // In the video camera case calls skipFrameAndModifyTimeStamp() to modify
     // timestamp and set mSkipCurrentFrame.
     // Then it calls the base CameraSource::dataCallbackTimestamp()
@@ -189,24 +147,6 @@
     // Otherwise returns false.
     bool trySettingVideoSize(int32_t width, int32_t height);
 
-    // The still camera may not support the demanded video width and height.
-    // We look for the supported picture sizes from the still camera and
-    // choose the smallest one with either dimensions higher than the corresponding
-    // video dimensions. The still picture will be cropped to get the video frame.
-    // The function returns true if the camera supports picture sizes greater than
-    // or equal to the passed in width and height, and false otherwise.
-    bool setPictureSizeToClosestSupported(int32_t width, int32_t height);
-
-    // Computes the offset of the rectangle from where to start cropping the
-    // still image into the video frame. We choose the center of the image to be
-    // cropped. The offset is stored in (mCropRectStartX, mCropRectStartY).
-    bool computeCropRectangleOffset();
-
-    // Crops the source data into a smaller image starting at
-    // (mCropRectStartX, mCropRectStartY) and of the size of the video frame.
-    // The data is returned into a newly allocated IMemory.
-    sp<IMemory> cropYUVImage(const sp<IMemory> &source_data);
-
     // When video camera is used for time lapse capture, returns true
     // until enough time has passed for the next time lapse frame. When
     // the frame needs to be encoded, it returns false and also modifies
@@ -217,22 +157,6 @@
     // Wrapper to enter threadTimeLapseEntry()
     static void *ThreadTimeLapseWrapper(void *me);
 
-    // Runs a loop which sleeps until a still picture is required
-    // and then calls mCamera->takePicture() to take the still picture.
-    // Used only in the case mUseStillCameraForTimeLapse = true.
-    void threadTimeLapseEntry();
-
-    // Wrapper to enter threadStartPreview()
-    static void *ThreadStartPreviewWrapper(void *me);
-
-    // Starts the camera's preview.
-    void threadStartPreview();
-
-    // Starts thread ThreadStartPreviewWrapper() for restarting preview.
-    // Needs to be done in a thread so that dataCallback() which calls this function
-    // can return, and the camera can know that takePicture() is done.
-    void restartPreview();
-
     // Creates a copy of source_data into a new memory of final type MemoryBase.
     sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);
 
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 48d1464..713af92 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 
+#include <media/stagefright/MediaErrors.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
@@ -61,6 +62,10 @@
         return 0;
     }
 
+    virtual status_t reconnectAtOffset(off64_t offset) {
+        return ERROR_UNSUPPORTED;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
 
     bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 946a0aa..32eed3f 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -99,6 +99,13 @@
     OMX_U32 nUsage;             // OUT
 };
 
+// An enum OMX_COLOR_FormatAndroidOpaque to indicate an opaque colorformat
+// is declared in media/stagefright/openmax/OMX_IVCommon.h
+// This will inform the encoder that the actual
+// colorformat will be relayed by the GRalloc Buffers.
+// OMX_COLOR_FormatAndroidOpaque  = 0x7F000001,
+
+
 }  // namespace android
 
 extern android::OMXPluginBase *createOMXPlugin();
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index 37dbcd8..3818e63 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -29,7 +29,7 @@
 class MediaBuffer;
 class MetaData;
 
-struct MediaSource : public RefBase {
+struct MediaSource : public virtual RefBase {
     MediaSource();
 
     // To be called before any other methods on this object, except
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 52a3257..4eaf8ac 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -69,6 +69,16 @@
      * kMetadataBufferTypeGrallocSource is used to indicate that
      * the payload of the metadata buffers can be interpreted as
      * a buffer_handle_t.
+     * So in this case,the metadata that the encoder receives
+     * will have a byte stream that consists of two parts:
+     * 1. First, there is an integer indicating that it is a GRAlloc
+     * source (kMetadataBufferTypeGrallocSource)
+     * 2. This is followed by the buffer_handle_t that is a handle to the
+     * GRalloc buffer. The encoder needs to interpret this GRalloc handle
+     * and encode the frames.
+     * --------------------------------------------------------------
+     * |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+     * --------------------------------------------------------------
      */
     kMetadataBufferTypeGrallocSource = 1,
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 7f3c497..2932744 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -329,6 +329,7 @@
     void restorePatchedDataPointer(BufferInfo *info);
 
     status_t applyRotation();
+    status_t waitForBufferFilled_l();
 
     int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
 
@@ -336,11 +337,6 @@
     OMXCodec &operator=(const OMXCodec &);
 };
 
-struct CodecProfileLevel {
-    OMX_U32 mProfile;
-    OMX_U32 mLevel;
-};
-
 struct CodecCapabilities {
     String8 mComponentName;
     Vector<CodecProfileLevel> mProfileLevels;
@@ -353,6 +349,8 @@
 // that encode content of the given type.
 // profile and level indications only make sense for h.263, mpeg4 and avc
 // video.
+// If hwCodecOnly==true, only returns hardware-based components, software and
+// hardware otherwise.
 // The profile/level values correspond to
 // OMX_VIDEO_H263PROFILETYPE, OMX_VIDEO_MPEG4PROFILETYPE,
 // OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263LEVELTYPE, OMX_VIDEO_MPEG4LEVELTYPE
@@ -360,6 +358,11 @@
 
 status_t QueryCodecs(
         const sp<IOMX> &omx,
+        const char *mimeType, bool queryDecoders, bool hwCodecOnly,
+        Vector<CodecCapabilities> *results);
+
+status_t QueryCodecs(
+        const sp<IOMX> &omx,
         const char *mimeType, bool queryDecoders,
         Vector<CodecCapabilities> *results);
 
diff --git a/include/media/stagefright/ShoutcastSource.h b/include/media/stagefright/ShoutcastSource.h
deleted file mode 100644
index bc67156..0000000
--- a/include/media/stagefright/ShoutcastSource.h
+++ /dev/null
@@ -1,61 +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 SHOUTCAST_SOURCE_H_
-
-#define SHOUTCAST_SOURCE_H_
-
-#include <sys/types.h>
-
-#include <media/stagefright/MediaSource.h>
-
-namespace android {
-
-class HTTPStream;
-class MediaBufferGroup;
-
-class ShoutcastSource : public MediaSource {
-public:
-    // Assumes ownership of "http".
-    ShoutcastSource(HTTPStream *http);
-
-    virtual status_t start(MetaData *params = NULL);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options = NULL);
-
-protected:
-    virtual ~ShoutcastSource();
-
-private:
-    HTTPStream *mHttp;
-    size_t mMetaDataOffset;
-    size_t mBytesUntilMetaData;
-
-    MediaBufferGroup *mGroup;
-    bool mStarted;
-
-    ShoutcastSource(const ShoutcastSource &);
-    ShoutcastSource &operator= (const ShoutcastSource &);
-};
-
-}  // namespace android
-
-#endif  // SHOUTCAST_SOURCE_H_
-
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
index 108acb4..6510a59 100644
--- a/include/media/stagefright/StagefrightMediaScanner.h
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -26,7 +26,7 @@
     StagefrightMediaScanner();
     virtual ~StagefrightMediaScanner();
 
-    virtual status_t processFile(
+    virtual MediaScanResult processFile(
             const char *path, const char *mimeType,
             MediaScannerClient &client);
 
@@ -35,6 +35,10 @@
 private:
     StagefrightMediaScanner(const StagefrightMediaScanner &);
     StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
+
+    MediaScanResult processFileInternal(
+            const char *path, const char *mimeType,
+            MediaScannerClient &client);
 };
 
 }  // namespace android
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
new file mode 100644
index 0000000..fab258c
--- /dev/null
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -0,0 +1,354 @@
+/*
+ * 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_GUI_SURFACEMEDIASOURCE_H
+#define ANDROID_GUI_SURFACEMEDIASOURCE_H
+
+#include <gui/ISurfaceTexture.h>
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc;
+class String8;
+class GraphicBuffer;
+
+class SurfaceMediaSource : public BnSurfaceTexture, public MediaSource,
+                                            public MediaBufferObserver {
+public:
+    enum { MIN_UNDEQUEUED_BUFFERS = 3 };
+    enum {
+        MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
+        MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
+    };
+    enum { NUM_BUFFER_SLOTS = 32 };
+    enum { NO_CONNECTED_API = 0 };
+
+    struct FrameAvailableListener : public virtual RefBase {
+        // onFrameAvailable() is called from queueBuffer() is the FIFO is
+        // empty. You can use SurfaceMediaSource::getQueuedCount() to
+        // figure out if there are more frames waiting.
+        // This is called without any lock held can be called concurrently by
+        // multiple threads.
+        virtual void onFrameAvailable() = 0;
+    };
+
+    SurfaceMediaSource(uint32_t bufW, uint32_t bufH);
+
+    virtual ~SurfaceMediaSource();
+
+
+    // For the MediaSource interface for use by StageFrightRecorder:
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+    virtual sp<MetaData> getFormat();
+
+    // Pass the metadata over to the buffer, call when you have the lock
+    void passMetadataBufferLocked(MediaBuffer **buffer);
+    bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
+    // Get / Set the frame rate used for encoding. Default fps = 30
+    status_t setFrameRate(int32_t fps) ;
+    int32_t getFrameRate( ) const;
+
+    // The call for the StageFrightRecorder to tell us that
+    // it is done using the MediaBuffer data so that its state
+    // can be set to FREE for dequeuing
+    virtual void signalBufferReturned(MediaBuffer* buffer);
+    // end of MediaSource interface
+
+    uint32_t getBufferCount( ) const { return mBufferCount;}
+
+
+    // setBufferCount updates the number of available buffer slots.  After
+    // calling this all buffer slots are both unallocated and owned by the
+    // SurfaceMediaSource object (i.e. they are not owned by the client).
+    virtual status_t setBufferCount(int bufferCount);
+
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+
+    // dequeueBuffer gets the next buffer slot index for the client to use. If a
+    // buffer slot is available then that slot index is written to the location
+    // pointed to by the buf argument and a status of OK is returned.  If no
+    // slot is available then a status of -EBUSY is returned and buf is
+    // unmodified.
+    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage);
+
+    // queueBuffer returns a filled buffer to the SurfaceMediaSource. In addition, a
+    // timestamp must be provided for the buffer. The timestamp is in
+    // nanoseconds, and must be monotonically increasing. Its other semantics
+    // (zero point, etc) are client-dependent and should be documented by the
+    // client.
+    virtual status_t queueBuffer(int buf, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+    virtual void cancelBuffer(int buf);
+
+    // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+    // or listeners that a frame has been received
+    // The buffer is not made available for dequeueing immediately. We need to
+    // wait to hear from StageFrightRecorder to set the buffer FREE
+    // Make sure this is called when the mutex is locked
+    virtual status_t onFrameReceivedLocked();
+
+    virtual status_t setScalingMode(int mode) { } // no op for encoding
+    virtual int query(int what, int* value);
+
+    // Just confirming to the ISurfaceTexture interface as of now
+    virtual status_t setCrop(const Rect& reg) { return OK; }
+    virtual status_t setTransform(uint32_t transform) {return OK;}
+
+    // setSynchronousMode set whether dequeueBuffer is synchronous or
+    // asynchronous. In synchronous mode, dequeueBuffer blocks until
+    // a buffer is available, the currently bound buffer can be dequeued and
+    // queued buffers will be retired in order.
+    // The default mode is synchronous.
+    // TODO: Clarify the minute differences bet sycn /async
+    // modes (S.Encoder vis-a-vis SurfaceTexture)
+    virtual status_t setSynchronousMode(bool enabled);
+
+    // connect attempts to connect a client API to the SurfaceMediaSource.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceMediaSource and no corresponding disconnect call was made.
+    virtual status_t connect(int api);
+
+    // disconnect attempts to disconnect a client API from the SurfaceMediaSource.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceMediaSource is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api);
+
+    // 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.
+    status_t setBufferCountServer(int bufferCount);
+
+    // getTimestamp retrieves the timestamp associated with the image
+    // set by the most recent call to read()
+    //
+    // The timestamp is in nanoseconds, and is monotonically increasing. Its
+    // other semantics (zero point, etc) are source-dependent and should be
+    // documented by the source.
+    int64_t getTimestamp();
+
+    // setFrameAvailableListener sets the listener object that will be notified
+    // when a new frame becomes available.
+    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
+
+    // getCurrentBuffer returns the buffer associated with the current image.
+    sp<GraphicBuffer> getCurrentBuffer() const;
+
+    // dump our state in a String
+    void dump(String8& result) const;
+    void dump(String8& result, const char* prefix, char* buffer,
+                                                    size_t SIZE) const;
+
+    // isMetaDataStoredInVideoBuffers tells the encoder whether we will
+    // pass metadata through the buffers. Currently, it is force set to true
+    bool isMetaDataStoredInVideoBuffers() const;
+
+protected:
+
+    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
+    // all slots.
+    void freeAllBuffers();
+    static bool isExternalFormat(uint32_t format);
+
+private:
+
+    status_t setBufferCountServerLocked(int bufferCount);
+
+    enum { INVALID_BUFFER_SLOT = -1 };
+
+    struct BufferSlot {
+
+        BufferSlot()
+            : mBufferState(BufferSlot::FREE),
+              mRequestBufferCalled(false),
+              mTimestamp(0) {
+        }
+
+        // mGraphicBuffer points to the buffer allocated for this slot or is
+        // NULL if no buffer has been allocated.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // BufferState represents the different states in which a buffer slot
+        // can be.
+        enum BufferState {
+            // FREE indicates that the buffer is not currently being used and
+            // will not be used in the future until it gets dequeued and
+            // subseqently queued by the client.
+            FREE = 0,
+
+            // DEQUEUED indicates that the buffer has been dequeued by the
+            // client, but has not yet been queued or canceled. The buffer is
+            // considered 'owned' by the client, and the server should not use
+            // it for anything.
+            //
+            // Note that when in synchronous-mode (mSynchronousMode == true),
+            // the buffer that's currently attached to the texture may be
+            // dequeued by the client.  That means that the current buffer can
+            // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
+            // however, the current buffer is always in the QUEUED state.
+            DEQUEUED = 1,
+
+            // QUEUED indicates that the buffer has been queued by the client,
+            // and has not since been made available for the client to dequeue.
+            // Attaching the buffer to the texture does NOT transition the
+            // buffer away from the QUEUED state. However, in Synchronous mode
+            // the current buffer may be dequeued by the client under some
+            // circumstances. See the note about the current buffer in the
+            // documentation for DEQUEUED.
+            QUEUED = 2,
+        };
+
+        // mBufferState is the current state of this buffer slot.
+        BufferState mBufferState;
+
+        // mRequestBufferCalled is used for validating that the client did
+        // call requestBuffer() when told to do so. Technically this is not
+        // needed but useful for debugging and catching client bugs.
+        bool mRequestBufferCalled;
+
+        // mTimestamp is the current timestamp for this buffer slot. This gets
+        // to set by queueBuffer each time this slot is queued.
+        int64_t mTimestamp;
+    };
+
+    // mSlots is the array of buffer slots that must be mirrored on the client
+    // side. This allows buffer ownership to be transferred between the client
+    // and server without sending a GraphicBuffer over binder. The entire array
+    // is initialized to NULL at construction time, and buffers are allocated
+    // for a slot when requestBuffer is called with that slot's index.
+    BufferSlot mSlots[NUM_BUFFER_SLOTS];
+
+    // mDefaultWidth holds the default width of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultWidth;
+
+    // mDefaultHeight holds the default height of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultHeight;
+
+    // mPixelFormat holds the pixel format of allocated buffers. It is used
+    // in requestBuffers() if a format of zero is specified.
+    uint32_t mPixelFormat;
+
+    // mBufferCount is the number of buffer slots that the client and server
+    // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
+    // by calling setBufferCount or setBufferCountServer
+    int mBufferCount;
+
+    // mClientBufferCount is the number of buffer slots requested by the
+    // client. The default is zero, which means the client doesn't care how
+    // many buffers there are
+    int mClientBufferCount;
+
+    // mServerBufferCount buffer count requested by the server-side
+    int mServerBufferCount;
+
+    // mCurrentSlot is the buffer slot index of the buffer that is currently
+    // being used by buffer consumer
+    // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture
+    // in the case of SurfaceTexture).
+    // It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+    int mCurrentSlot;
+
+
+    // mCurrentBuf is the graphic buffer of the current slot to be used by
+    // buffer consumer. It's possible that this buffer is not associated
+    // with any buffer slot, so we must track it separately in order to
+    // properly use IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+    sp<GraphicBuffer> mCurrentBuf;
+
+
+    // mCurrentTimestamp is the timestamp for the current texture. It
+    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+    int64_t mCurrentTimestamp;
+
+    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+    // allocate new GraphicBuffer objects.
+    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+    // mFrameAvailableListener is the listener object that will be called when a
+    // new frame becomes available. If it is not NULL it will be called from
+    // queueBuffer.
+    sp<FrameAvailableListener> mFrameAvailableListener;
+
+    // mSynchronousMode whether we're in synchronous mode or not
+    bool mSynchronousMode;
+
+    // mConnectedApi indicates the API that is currently connected to this
+    // SurfaceTexture.  It defaults to NO_CONNECTED_API (= 0), and gets updated
+    // by the connect and disconnect methods.
+    int mConnectedApi;
+
+    // mDequeueCondition condition used for dequeueBuffer in synchronous mode
+    mutable Condition mDequeueCondition;
+
+
+    // mQueue is a FIFO of queued buffers used in synchronous mode
+    typedef Vector<int> Fifo;
+    Fifo mQueue;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceMediaSource objects. It must be locked whenever the
+    // member variables are accessed.
+    mutable Mutex mMutex;
+
+    ////////////////////////// For MediaSource
+    // Set to a default of 30 fps if not specified by the client side
+    int32_t mFrameRate;
+
+    // mStarted is a flag to check if the recording has started
+    bool mStarted;
+
+    // mFrameAvailableCondition condition used to indicate whether there
+    // is a frame available for dequeuing
+    Condition mFrameAvailableCondition;
+    Condition mFrameCompleteCondition;
+
+    // Avoid copying and equating and default constructor
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceMediaSource);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SURFACEMEDIASOURCE_H
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 7ed072b..97170d7 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -16,29 +16,29 @@
  * -------------------------------------------------------------------
  */
 /**
- * Copyright (c) 2008 The Khronos Group Inc. 
- * 
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions: 
+ * to the following conditions:
  * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
- * 
+ * in all copies or substantial portions of the Software.
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
-/** 
+/**
  * @file OMX_IVCommon.h - OpenMax IL version 1.1.2
  *  The structures needed by Video and Image components to exchange
  *  parameters and configuration data with the components.
@@ -53,7 +53,7 @@
 /**
  * Each OMX header must include all required header files to allow the header
  * to compile without errors.  The includes below are required for this header
- * file to compile successfully 
+ * file to compile successfully
  */
 
 #include <OMX_Core.h>
@@ -64,8 +64,8 @@
  */
 
 
-/** 
- * Enumeration defining possible uncompressed image/video formats. 
+/**
+ * Enumeration defining possible uncompressed image/video formats.
  *
  * ENUMS:
  *  Unused                 : Placeholder value when format is N/A
@@ -113,7 +113,7 @@
     OMX_COLOR_Format16bitBGR565,
     OMX_COLOR_Format18bitRGB666,
     OMX_COLOR_Format18bitARGB1665,
-    OMX_COLOR_Format19bitARGB1666, 
+    OMX_COLOR_Format19bitARGB1666,
     OMX_COLOR_Format24bitRGB888,
     OMX_COLOR_Format24bitBGR888,
     OMX_COLOR_Format24bitARGB1887,
@@ -136,55 +136,62 @@
     OMX_COLOR_FormatRawBayer8bit,
     OMX_COLOR_FormatRawBayer10bit,
     OMX_COLOR_FormatRawBayer8bitcompressed,
-    OMX_COLOR_FormatL2, 
-    OMX_COLOR_FormatL4, 
-    OMX_COLOR_FormatL8, 
-    OMX_COLOR_FormatL16, 
-    OMX_COLOR_FormatL24, 
+    OMX_COLOR_FormatL2,
+    OMX_COLOR_FormatL4,
+    OMX_COLOR_FormatL8,
+    OMX_COLOR_FormatL16,
+    OMX_COLOR_FormatL24,
     OMX_COLOR_FormatL32,
     OMX_COLOR_FormatYUV420PackedSemiPlanar,
     OMX_COLOR_FormatYUV422PackedSemiPlanar,
     OMX_COLOR_Format18BitBGR666,
     OMX_COLOR_Format24BitARGB6666,
     OMX_COLOR_Format24BitABGR6666,
-    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+    /**<Reserved android opaque colorformat. Tells the encoder that
+     * the actual colorformat will be  relayed by the
+     * Gralloc Buffers.
+     * FIXME: In the process of reserving some enum values for
+     * Android-specific OMX IL colorformats. Change this enum to
+     * an acceptable range once that is done.*/
+    OMX_COLOR_FormatAndroidOpaque = 0x7F000001,
     OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
 
-/** 
+/**
  * Defines the matrix for conversion from RGB to YUV or vice versa.
- * iColorMatrix should be initialized with the fixed point values 
+ * iColorMatrix should be initialized with the fixed point values
  * used in converting between formats.
  */
 typedef struct OMX_CONFIG_COLORCONVERSIONTYPE {
     OMX_U32 nSize;              /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */
     OMX_U32 nPortIndex;         /**< Port that this struct applies to */
     OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */
     OMX_S32 xColorOffset[4];    /**< Stored in signed Q16 format */
 }OMX_CONFIG_COLORCONVERSIONTYPE;
 
 
-/** 
- * Structure defining percent to scale each frame dimension.  For example:  
+/**
+ * Structure defining percent to scale each frame dimension.  For example:
  * To make the width 50% larger, use fWidth = 1.5 and to make the width
  * 1/2 the original size, use fWidth = 0.5
  */
 typedef struct OMX_CONFIG_SCALEFACTORTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
     OMX_U32 nPortIndex;       /**< Port that this struct applies to */
     OMX_S32 xWidth;           /**< Fixed point value stored as Q16 */
     OMX_S32 xHeight;          /**< Fixed point value stored as Q16 */
 }OMX_CONFIG_SCALEFACTORTYPE;
 
 
-/** 
- * Enumeration of possible image filter types 
+/**
+ * Enumeration of possible image filter types
  */
 typedef enum OMX_IMAGEFILTERTYPE {
     OMX_ImageFilterNone,
@@ -195,23 +202,23 @@
     OMX_ImageFilterOilPaint,
     OMX_ImageFilterHatch,
     OMX_ImageFilterGpen,
-    OMX_ImageFilterAntialias, 
-    OMX_ImageFilterDeRing,       
+    OMX_ImageFilterAntialias,
+    OMX_ImageFilterDeRing,
     OMX_ImageFilterSolarize,
-    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ImageFilterMax = 0x7FFFFFFF
 } OMX_IMAGEFILTERTYPE;
 
 
-/** 
- * Image filter configuration 
+/**
+ * Image filter configuration
  *
  * STRUCT MEMBERS:
- *  nSize        : Size of the structure in bytes       
+ *  nSize        : Size of the structure in bytes
  *  nVersion     : OMX specification version information
- *  nPortIndex   : Port that this structure applies to 
- *  eImageFilter : Image filter type enumeration      
+ *  nPortIndex   : Port that this structure applies to
+ *  eImageFilter : Image filter type enumeration
  */
 typedef struct OMX_CONFIG_IMAGEFILTERTYPE {
     OMX_U32 nSize;
@@ -221,22 +228,22 @@
 } OMX_CONFIG_IMAGEFILTERTYPE;
 
 
-/** 
- * Customized U and V for color enhancement 
+/**
+ * Customized U and V for color enhancement
  *
  * STRUCT MEMBERS:
  *  nSize             : Size of the structure in bytes
- *  nVersion          : OMX specification version information 
+ *  nVersion          : OMX specification version information
  *  nPortIndex        : Port that this structure applies to
  *  bColorEnhancement : Enable/disable color enhancement
- *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for
  *                      U component
- *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for
  *                      V component
  */
 typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_BOOL bColorEnhancement;
     OMX_U8 nCustomizedU;
@@ -244,12 +251,12 @@
 } OMX_CONFIG_COLORENHANCEMENTTYPE;
 
 
-/** 
- * Define color key and color key mask 
+/**
+ * Define color key and color key mask
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nARGBColor : 32bit Alpha, Red, Green, Blue Color
  *  nARGBMask  : 32bit Mask for Alpha, Red, Green, Blue channels
@@ -263,12 +270,12 @@
 } OMX_CONFIG_COLORKEYTYPE;
 
 
-/** 
- * List of color blend types for pre/post processing 
+/**
+ * List of color blend types for pre/post processing
  *
  * ENUMS:
  *  None          : No color blending present
- *  AlphaConstant : Function is (alpha_constant * src) + 
+ *  AlphaConstant : Function is (alpha_constant * src) +
  *                  (1 - alpha_constant) * dst)
  *  AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst)
  *  Alternate     : Function is alternating pixels from src and dst
@@ -284,21 +291,21 @@
     OMX_ColorBlendAnd,
     OMX_ColorBlendOr,
     OMX_ColorBlendInvert,
-    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ColorBlendMax = 0x7FFFFFFF
 } OMX_COLORBLENDTYPE;
 
 
-/** 
- * Color blend configuration 
+/**
+ * Color blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize             : Size of the structure in bytes                        
- *  nVersion          : OMX specification version information                
- *  nPortIndex        : Port that this structure applies to                   
+ *  nSize             : Size of the structure in bytes
+ *  nVersion          : OMX specification version information
+ *  nPortIndex        : Port that this structure applies to
  *  nRGBAlphaConstant : Constant global alpha values when global alpha is used
- *  eColorBlend       : Color blend type enumeration                         
+ *  eColorBlend       : Color blend type enumeration
  */
 typedef struct OMX_CONFIG_COLORBLENDTYPE {
     OMX_U32 nSize;
@@ -309,15 +316,15 @@
 } OMX_CONFIG_COLORBLENDTYPE;
 
 
-/** 
+/**
  * Hold frame dimension
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to     
- *  nWidth     : Frame width in pixels                 
- *  nHeight    : Frame height in pixels                
+ *  nPortIndex : Port that this structure applies to
+ *  nWidth     : Frame width in pixels
+ *  nHeight    : Frame height in pixels
  */
 typedef struct OMX_FRAMESIZETYPE {
     OMX_U32 nSize;
@@ -329,69 +336,69 @@
 
 
 /**
- * Rotation configuration 
+ * Rotation configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes             
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nRotation  : +/- integer rotation value               
+ *  nRotation  : +/- integer rotation value
  */
 typedef struct OMX_CONFIG_ROTATIONTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
-    OMX_S32 nRotation; 
+    OMX_S32 nRotation;
 } OMX_CONFIG_ROTATIONTYPE;
 
 
-/** 
- * Possible mirroring directions for pre/post processing 
+/**
+ * Possible mirroring directions for pre/post processing
  *
  * ENUMS:
- *  None       : No mirroring                         
- *  Vertical   : Vertical mirroring, flip on X axis   
- *  Horizontal : Horizontal mirroring, flip on Y axis  
+ *  None       : No mirroring
+ *  Vertical   : Vertical mirroring, flip on X axis
+ *  Horizontal : Horizontal mirroring, flip on Y axis
  *  Both       : Both vertical and horizontal mirroring
  */
 typedef enum OMX_MIRRORTYPE {
     OMX_MirrorNone = 0,
     OMX_MirrorVertical,
     OMX_MirrorHorizontal,
-    OMX_MirrorBoth, 
-    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_MirrorBoth,
+    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
-    OMX_MirrorMax = 0x7FFFFFFF   
+    OMX_MirrorMax = 0x7FFFFFFF
 } OMX_MIRRORTYPE;
 
 
-/** 
- * Mirroring configuration 
+/**
+ * Mirroring configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to  
- *  eMirror    : Mirror type enumeration              
+ *  nPortIndex : Port that this structure applies to
+ *  eMirror    : Mirror type enumeration
  */
 typedef struct OMX_CONFIG_MIRRORTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_MIRRORTYPE  eMirror;
 } OMX_CONFIG_MIRRORTYPE;
 
 
-/** 
- * Position information only 
+/**
+ * Position information only
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes               
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nX         : X coordinate for the point                     
- *  nY         : Y coordinate for the point 
- */                      
+ *  nX         : X coordinate for the point
+ *  nY         : Y coordinate for the point
+ */
 typedef struct OMX_CONFIG_POINTTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -401,37 +408,37 @@
 } OMX_CONFIG_POINTTYPE;
 
 
-/** 
- * Frame size plus position 
+/**
+ * Frame size plus position
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                    
- *  nVersion   : OMX specification version information      
- *  nPortIndex : Port that this structure applies to    
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nLeft      : X Coordinate of the top left corner of the rectangle
  *  nTop       : Y Coordinate of the top left corner of the rectangle
- *  nWidth     : Width of the rectangle                              
- *  nHeight    : Height of the rectangle                             
+ *  nWidth     : Width of the rectangle
+ *  nHeight    : Height of the rectangle
  */
 typedef struct OMX_CONFIG_RECTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion;  
-    OMX_U32 nPortIndex; 
-    OMX_S32 nLeft; 
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_S32 nLeft;
     OMX_S32 nTop;
     OMX_U32 nWidth;
     OMX_U32 nHeight;
 } OMX_CONFIG_RECTTYPE;
 
 
-/** 
- * Deblocking state; it is required to be set up before starting the codec 
+/**
+ * Deblocking state; it is required to be set up before starting the codec
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes      
- *  nVersion    : OMX specification version information 
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  bDeblocking : Enable/disable deblocking mode    
+ *  bDeblocking : Enable/disable deblocking mode
  */
 typedef struct OMX_PARAM_DEBLOCKINGTYPE {
     OMX_U32 nSize;
@@ -441,13 +448,13 @@
 } OMX_PARAM_DEBLOCKINGTYPE;
 
 
-/** 
- * Stabilization state 
+/**
+ * Stabilization state
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes          
- *  nVersion   : OMX specification version information    
- *  nPortIndex : Port that this structure applies to   
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  bStab      : Enable/disable frame stabilization state
  */
 typedef struct OMX_CONFIG_FRAMESTABTYPE {
@@ -458,8 +465,8 @@
 } OMX_CONFIG_FRAMESTABTYPE;
 
 
-/** 
- * White Balance control type 
+/**
+ * White Balance control type
  *
  * STRUCT MEMBERS:
  *  SunLight : Referenced in JSR-234
@@ -476,20 +483,20 @@
     OMX_WhiteBalControlIncandescent,
     OMX_WhiteBalControlFlash,
     OMX_WhiteBalControlHorizon,
-    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_WhiteBalControlMax = 0x7FFFFFFF
 } OMX_WHITEBALCONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes       
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                 
- *  eWhiteBalControl : White balance enumeration            
+ *  nPortIndex       : Port that this structure applies to
+ *  eWhiteBalControl : White balance enumeration
  */
 typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE {
     OMX_U32 nSize;
@@ -499,8 +506,8 @@
 } OMX_CONFIG_WHITEBALCONTROLTYPE;
 
 
-/** 
- * Exposure control type 
+/**
+ * Exposure control type
  */
 typedef enum OMX_EXPOSURECONTROLTYPE {
     OMX_ExposureControlOff = 0,
@@ -513,20 +520,20 @@
     OMX_ExposureControlBeach,
     OMX_ExposureControlLargeAperture,
     OMX_ExposureControlSmallApperture,
-    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ExposureControlMax = 0x7FFFFFFF
 } OMX_EXPOSURECONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes      
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                
- *  eExposureControl : Exposure control enumeration         
+ *  nPortIndex       : Port that this structure applies to
+ *  eExposureControl : Exposure control enumeration
  */
 typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE {
     OMX_U32 nSize;
@@ -536,16 +543,16 @@
 } OMX_CONFIG_EXPOSURECONTROLTYPE;
 
 
-/** 
- * Defines sensor supported mode. 
+/**
+ * Defines sensor supported mode.
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes           
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to 
- *  nFrameRate : Single shot mode is indicated by a 0     
+ *  nPortIndex : Port that this structure applies to
+ *  nFrameRate : Single shot mode is indicated by a 0
  *  bOneShot   : Enable for single shot, disable for streaming
- *  sFrameSize : Framesize                                          
+ *  sFrameSize : Framesize
  */
 typedef struct OMX_PARAM_SENSORMODETYPE {
     OMX_U32 nSize;
@@ -557,13 +564,13 @@
 } OMX_PARAM_SENSORMODETYPE;
 
 
-/** 
- * Defines contrast level 
+/**
+ * Defines contrast level
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                              
- *  nVersion   : OMX specification version information                
- *  nPortIndex : Port that this structure applies to                 
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nContrast  : Values allowed for contrast -100 to 100, zero means no change
  */
 typedef struct OMX_CONFIG_CONTRASTTYPE {
@@ -574,14 +581,14 @@
 } OMX_CONFIG_CONTRASTTYPE;
 
 
-/** 
- * Defines brightness level 
+/**
+ * Defines brightness level
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes          
- *  nVersion    : OMX specification version information 
- *  nPortIndex  : Port that this structure applies to 
- *  nBrightness : 0-100%        
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
+ *  nPortIndex  : Port that this structure applies to
+ *  nBrightness : 0-100%
  */
 typedef struct OMX_CONFIG_BRIGHTNESSTYPE {
     OMX_U32 nSize;
@@ -591,16 +598,16 @@
 } OMX_CONFIG_BRIGHTNESSTYPE;
 
 
-/** 
- * Defines backlight level configuration for a video sink, e.g. LCD panel 
+/**
+ * Defines backlight level configuration for a video sink, e.g. LCD panel
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nBacklight : Values allowed for backlight 0-100%
- *  nTimeout   : Number of milliseconds before backlight automatically turns 
- *               off.  A value of 0x0 disables backight timeout 
+ *  nTimeout   : Number of milliseconds before backlight automatically turns
+ *               off.  A value of 0x0 disables backight timeout
  */
 typedef struct OMX_CONFIG_BACKLIGHTTYPE {
     OMX_U32 nSize;
@@ -611,12 +618,12 @@
 } OMX_CONFIG_BACKLIGHTTYPE;
 
 
-/** 
- * Defines setting for Gamma 
+/**
+ * Defines setting for Gamma
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nGamma     : Values allowed for gamma -100 to 100, zero means no change
  */
@@ -628,14 +635,14 @@
 } OMX_CONFIG_GAMMATYPE;
 
 
-/** 
- * Define for setting saturation 
- * 
+/**
+ * Define for setting saturation
+ *
  * STRUCT MEMBERS:
  *  nSize       : Size of the structure in bytes
  *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  nSaturation : Values allowed for saturation -100 to 100, zero means 
+ *  nSaturation : Values allowed for saturation -100 to 100, zero means
  *                no change
  */
 typedef struct OMX_CONFIG_SATURATIONTYPE {
@@ -646,14 +653,14 @@
 } OMX_CONFIG_SATURATIONTYPE;
 
 
-/** 
- * Define for setting Lightness 
+/**
+ * Define for setting Lightness
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nLightness : Values allowed for lightness -100 to 100, zero means no 
+ *  nLightness : Values allowed for lightness -100 to 100, zero means no
  *               change
  */
 typedef struct OMX_CONFIG_LIGHTNESSTYPE {
@@ -664,17 +671,17 @@
 } OMX_CONFIG_LIGHTNESSTYPE;
 
 
-/** 
- * Plane blend configuration 
+/**
+ * Plane blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes 
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Index of input port associated with the plane.
- *  nDepth     : Depth of the plane in relation to the screen. Higher 
- *               numbered depths are "behind" lower number depths.  
+ *  nDepth     : Depth of the plane in relation to the screen. Higher
+ *               numbered depths are "behind" lower number depths.
  *               This number defaults to the Port Index number.
- *  nAlpha     : Transparency blending component for the entire plane.  
+ *  nAlpha     : Transparency blending component for the entire plane.
  *               See blending modes for more detail.
  */
 typedef struct OMX_CONFIG_PLANEBLENDTYPE {
@@ -686,17 +693,17 @@
 } OMX_CONFIG_PLANEBLENDTYPE;
 
 
-/** 
+/**
  * Define interlace type
  *
  * STRUCT MEMBERS:
- *  nSize                 : Size of the structure in bytes 
- *  nVersion              : OMX specification version information 
+ *  nSize                 : Size of the structure in bytes
+ *  nVersion              : OMX specification version information
  *  nPortIndex            : Port that this structure applies to
- *  bEnable               : Enable control variable for this functionality 
+ *  bEnable               : Enable control variable for this functionality
  *                          (see below)
- *  nInterleavePortIndex  : Index of input or output port associated with  
- *                          the interleaved plane. 
+ *  nInterleavePortIndex  : Index of input or output port associated with
+ *                          the interleaved plane.
  *  pPlanarPortIndexes[4] : Index of input or output planar ports.
  */
 typedef struct OMX_PARAM_INTERLEAVETYPE {
@@ -708,8 +715,8 @@
 } OMX_PARAM_INTERLEAVETYPE;
 
 
-/** 
- * Defines the picture effect used for an input picture 
+/**
+ * Defines the picture effect used for an input picture
  */
 typedef enum OMX_TRANSITIONEFFECTTYPE {
     OMX_EffectNone,
@@ -719,18 +726,18 @@
     OMX_EffectDissolve,
     OMX_EffectWipe,
     OMX_EffectUnspecifiedMixOfTwoScenes,
-    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EffectMax = 0x7FFFFFFF
 } OMX_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Structure used to configure current transition effect 
+/**
+ * Structure used to configure current transition effect
  *
  * STRUCT MEMBERS:
  * nSize      : Size of the structure in bytes
- * nVersion   : OMX specification version information 
+ * nVersion   : OMX specification version information
  * nPortIndex : Port that this structure applies to
  * eEffect    : Effect to enable
  */
@@ -742,43 +749,43 @@
 } OMX_CONFIG_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Defines possible data unit types for encoded video data. The data unit 
+/**
+ * Defines possible data unit types for encoded video data. The data unit
  * types are used both for encoded video input for playback as well as
- * encoded video output from recording. 
+ * encoded video output from recording.
  */
 typedef enum OMX_DATAUNITTYPE {
     OMX_DataUnitCodedPicture,
     OMX_DataUnitVideoSegment,
     OMX_DataUnitSeveralSegments,
     OMX_DataUnitArbitraryStreamSection,
-    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataUnitMax = 0x7FFFFFFF
 } OMX_DATAUNITTYPE;
 
 
-/** 
- * Defines possible encapsulation types for coded video data unit. The 
- * encapsulation information is used both for encoded video input for 
- * playback as well as encoded video output from recording. 
+/**
+ * Defines possible encapsulation types for coded video data unit. The
+ * encapsulation information is used both for encoded video input for
+ * playback as well as encoded video output from recording.
  */
 typedef enum OMX_DATAUNITENCAPSULATIONTYPE {
     OMX_DataEncapsulationElementaryStream,
     OMX_DataEncapsulationGenericPayload,
     OMX_DataEncapsulationRtpPayload,
-    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataEncapsulationMax = 0x7FFFFFFF
 } OMX_DATAUNITENCAPSULATIONTYPE;
 
 
-/** 
- * Structure used to configure the type of being decoded/encoded 
+/**
+ * Structure used to configure the type of being decoded/encoded
  */
 typedef struct OMX_PARAM_DATAUNITTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DATAUNITTYPE eUnitType;
     OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType;
@@ -786,25 +793,25 @@
 
 
 /**
- * Defines dither types 
+ * Defines dither types
  */
 typedef enum OMX_DITHERTYPE {
     OMX_DitherNone,
     OMX_DitherOrdered,
     OMX_DitherErrorDiffusion,
     OMX_DitherOther,
-    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DitherMax = 0x7FFFFFFF
 } OMX_DITHERTYPE;
 
 
-/** 
- * Structure used to configure current type of dithering 
+/**
+ * Structure used to configure current type of dithering
  */
 typedef struct OMX_CONFIG_DITHERTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DITHERTYPE eDither;   /**< Type of dithering to use */
 } OMX_CONFIG_DITHERTYPE;
@@ -813,28 +820,28 @@
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;     /**< Port that this structure applies to */
-    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture 
+    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture
                              *   data as fast as possible (otherwise obey port's frame rate). */
-    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the 
-                             *   specified number of frames (otherwise the port does not 
-                             *   terminate the capture until instructed to do so by the client). 
-                             *   Even if set, the client may manually terminate the capture prior 
+    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the
+                             *   specified number of frames (otherwise the port does not
+                             *   terminate the capture until instructed to do so by the client).
+                             *   Even if set, the client may manually terminate the capture prior
                              *   to reaching the limit. */
     OMX_U32 nFrameLimit;      /**< Limit on number of frames emitted during a capture (only
                                *   valid if bFrameLimited is set). */
 } OMX_CONFIG_CAPTUREMODETYPE;
 
 typedef enum OMX_METERINGTYPE {
- 
+
     OMX_MeteringModeAverage,     /**< Center-weighted average metering. */
     OMX_MeteringModeSpot,  	      /**< Spot (partial) metering. */
     OMX_MeteringModeMatrix,      /**< Matrix or evaluative metering. */
- 
-    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+
+    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EVModeMax = 0x7fffffff
 } OMX_METERINGTYPE;
- 
+
 typedef struct OMX_CONFIG_EXPOSUREVALUETYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -843,14 +850,14 @@
     OMX_S32 xEVCompensation;      /**< Fixed point value stored as Q16 */
     OMX_U32 nApertureFNumber;     /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */
     OMX_BOOL bAutoAperture;		/**< Whether aperture number is defined automatically */
-    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */ 
-    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */ 
+    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */
+    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */
     OMX_U32 nSensitivity;         /**< e.g. nSensitivity = 100 implies "ISO 100" */
     OMX_BOOL bAutoSensitivity;	/**< Whether sensitivity is defined automatically */
 } OMX_CONFIG_EXPOSUREVALUETYPE;
 
-/** 
- * Focus region configuration 
+/**
+ * Focus region configuration
  *
  * STRUCT MEMBERS:
  *  nSize           : Size of the structure in bytes
@@ -881,8 +888,8 @@
     OMX_BOOL bBottomRight;
 } OMX_CONFIG_FOCUSREGIONTYPE;
 
-/** 
- * Focus Status type 
+/**
+ * Focus Status type
  */
 typedef enum OMX_FOCUSSTATUSTYPE {
     OMX_FocusStatusOff = 0,
@@ -890,13 +897,13 @@
     OMX_FocusStatusReached,
     OMX_FocusStatusUnableToReach,
     OMX_FocusStatusLost,
-    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_FocusStatusMax = 0x7FFFFFFF
 } OMX_FOCUSSTATUSTYPE;
 
-/** 
- * Focus status configuration 
+/**
+ * Focus status configuration
  *
  * STRUCT MEMBERS:
  *  nSize               : Size of the structure in bytes
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
new file mode 100644
index 0000000..1723f04
--- /dev/null
+++ b/include/powermanager/IPowerManager.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IPOWERMANAGER_H
+#define ANDROID_IPOWERMANAGER_H
+
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// must be kept in sync with interface defined in IPowerManager.aidl
+class IPowerManager : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(PowerManager);
+
+    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag) = 0;
+    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IPOWERMANAGER_H
diff --git a/services/jni/com_android_server_InputWindow.h b/include/powermanager/PowerManager.h
similarity index 65%
rename from services/jni/com_android_server_InputWindow.h
rename to include/powermanager/PowerManager.h
index eaf7bde..4590174 100644
--- a/services/jni/com_android_server_InputWindow.h
+++ b/include/powermanager/PowerManager.h
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
-
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
+#ifndef ANDROID_POWERMANAGER_H
+#define ANDROID_POWERMANAGER_H
 
 namespace android {
 
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
+// must be kept in sync with definitions in PowerManager.java
+enum {
+    POWERMANAGER_PARTIAL_WAKE_LOCK = 1, // equals PowerManager.PARTIAL_WAKE_LOCK constant
+};
 
-} // namespace android
+}; // namespace android
 
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
+#endif // ANDROID_POWERMANAGER_H
diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h
index fdf327e..a8dd64f 100644
--- a/include/private/binder/binder_module.h
+++ b/include/private/binder/binder_module.h
@@ -21,126 +21,11 @@
 namespace android {
 #endif
 
-#if defined(HAVE_ANDROID_OS)
-
 /* obtain structures and constants from the kernel header */
 
 #include <sys/ioctl.h>
 #include <linux/binder.h>
 
-#else
-
-/* Some parts of the simulator need fake versions of this 
- * stuff in order to compile.  Really this should go away
- * entirely...
- */
-
-#define BINDER_CURRENT_PROTOCOL_VERSION 7
-
-#define BINDER_TYPE_BINDER 1
-#define BINDER_TYPE_WEAK_BINDER 2
-#define BINDER_TYPE_HANDLE 3
-#define BINDER_TYPE_WEAK_HANDLE 4
-#define BINDER_TYPE_FD 5
-
-struct flat_binder_object {
-    unsigned long type;
-    unsigned long flags;
-    union {
-        void *binder;
-        signed long handle;
-    };
-    void *cookie;
-};
-
-struct binder_write_read {
-    signed long write_size;
-    signed long write_consumed;
-    unsigned long write_buffer;
-    signed long read_size;
-    signed long read_consumed;
-    unsigned long read_buffer;
-};
-
-struct binder_transaction_data {
-    union {
-        size_t handle;
-        void *ptr;
-    } target;
-    void *cookie;
-    unsigned int code;
-    
-    unsigned int flags;
-    pid_t sender_pid;
-    uid_t sender_euid;
-    size_t data_size;
-    size_t offsets_size;
-    
-    union {
-        struct {
-            const void *buffer;
-            const void *offsets;
-        } ptr;
-        uint8_t buf[8];
-    } data;
-};
-
-enum transaction_flags {
-    TF_ONE_WAY = 0x01,
-    TF_ROOT_OBJECT = 0x04,
-    TF_STATUS_CODE = 0x08,
-    TF_ACCEPT_FDS = 0x10,
-};
-
-
-enum {
-    FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
-    FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
-};
-
-enum BinderDriverReturnProtocol {
-    BR_ERROR,
-    BR_OK,
-    BR_TRANSACTION,
-    BR_REPLY,
-    BR_ACQUIRE_RESULT,
-    BR_DEAD_REPLY,
-    BR_TRANSACTION_COMPLETE,
-    BR_INCREFS,
-    BR_ACQUIRE,
-    BR_RELEASE,
-    BR_DECREFS,
-    BR_ATTEMPT_ACQUIRE,
-    BR_NOOP,
-    BR_SPAWN_LOOPER,
-    BR_FINISHED,
-    BR_DEAD_BINDER,
-    BR_CLEAR_DEATH_NOTIFICATION_DONE,
-    BR_FAILED_REPLY,
-};
-
-enum BinderDriverCommandProtocol {
-    BC_TRANSACTION,
-    BC_REPLY,
-    BC_ACQUIRE_RESULT,
-    BC_FREE_BUFFER,
-    BC_INCREFS,
-    BC_ACQUIRE,
-    BC_RELEASE,
-    BC_DECREFS,
-    BC_INCREFS_DONE,
-    BC_ACQUIRE_DONE,
-    BC_ATTEMPT_ACQUIRE,
-    BC_REGISTER_LOOPER,
-    BC_ENTER_LOOPER,
-    BC_EXIT_LOOPER,
-    BC_REQUEST_DEATH_NOTIFICATION,
-    BC_CLEAR_DEATH_NOTIFICATION,
-    BC_DEAD_BINDER_DONE,
-};
-
-#endif
-
 #ifdef __cplusplus
 }   // namespace android
 #endif
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 6e9a654..02cabc1 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -45,9 +45,6 @@
     struct surface_data_t {
         int32_t             token;
         int32_t             identity;
-        uint32_t            width;
-        uint32_t            height;
-        uint32_t            format;
         status_t readFromParcel(const Parcel& parcel);
         status_t writeToParcel(Parcel* parcel) const;
     };
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index dc2a845..0460bbd 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -28,6 +28,8 @@
 #include <ui/Region.h>
 #include <ui/egl/android_natives.h>
 
+#include <gui/SurfaceTextureClient.h>
+
 #include <surfaceflinger/ISurface.h>
 #include <surfaceflinger/ISurfaceComposerClient.h>
 
@@ -37,14 +39,9 @@
 
 // ---------------------------------------------------------------------------
 
-class GraphicBuffer;
-class GraphicBufferMapper;
-class IOMX;
 class ISurfaceTexture;
-class Rect;
 class Surface;
 class SurfaceComposerClient;
-class SurfaceTextureClient;
 
 // ---------------------------------------------------------------------------
 
@@ -60,7 +57,6 @@
     static bool isSameSurface(
             const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
         
-    uint32_t    getFlags() const { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
 
     // release surface data from java
@@ -89,25 +85,13 @@
     SurfaceControl& operator = (SurfaceControl& rhs);
     SurfaceControl(const SurfaceControl& rhs);
 
-    
     friend class SurfaceComposerClient;
-
-    // camera and camcorder need access to the ISurface binder interface for preview
-    friend class CameraService;
-    friend class MediaRecorder;
-    // mediaplayer needs access to ISurface for display
-    friend class MediaPlayer;
-    // for testing
-    friend class Test;
-    // videoEditor preview classes
-    friend class VideoEditorPreviewController;
     friend class Surface;
 
     SurfaceControl(
             const sp<SurfaceComposerClient>& client,
             const sp<ISurface>& surface,
-            const ISurfaceComposerClient::surface_data_t& data,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+            const ISurfaceComposerClient::surface_data_t& data);
 
     ~SurfaceControl();
 
@@ -118,10 +102,6 @@
     sp<ISurface>                mSurface;
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
-    uint32_t                    mWidth;
-    uint32_t                    mHeight;
-    PixelFormat                 mFormat;
-    uint32_t                    mFlags;
     mutable Mutex               mLock;
     
     mutable sp<Surface>         mSurfaceData;
@@ -129,8 +109,7 @@
     
 // ---------------------------------------------------------------------------
 
-class Surface 
-    : public EGLNativeBase<ANativeWindow, Surface, RefBase>
+class Surface : public SurfaceTextureClient
 {
 public:
     struct SurfaceInfo {
@@ -143,112 +122,50 @@
         uint32_t    reserved[2];
     };
 
-    static status_t writeToParcel(
-            const sp<Surface>& control, Parcel* parcel);
+    explicit Surface(const sp<ISurfaceTexture>& st);
+
+    static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
 
     static sp<Surface> readFromParcel(const Parcel& data);
-
     static bool isValid(const sp<Surface>& surface) {
         return (surface != 0) && surface->isValid();
     }
 
     bool        isValid();
-    uint32_t    getFlags() const    { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
     sp<ISurfaceTexture> getSurfaceTexture();
 
     // the lock/unlock APIs must be used from the same thread
-    status_t    lock(SurfaceInfo* info, bool blocking = true);
-    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
+    status_t    lock(SurfaceInfo* info, Region* dirty = NULL);
     status_t    unlockAndPost();
 
     sp<IBinder> asBinder() const;
 
 private:
-    /*
-     * Android frameworks friends
-     * (eventually this should go away and be replaced by proper APIs)
-     */
-    // camera and camcorder need access to the ISurface binder interface for preview
-    friend class CameraService;
-    friend class MediaRecorder;
-    // MediaPlayer needs access to ISurface for display
-    friend class MediaPlayer;
-    friend class IOMX;
-    friend class SoftwareRenderer;
     // this is just to be able to write some unit tests
     friend class Test;
-    // videoEditor preview classes
-    friend class VideoEditorPreviewController;
-    friend class PreviewRenderer;
-
-private:
-    friend class SurfaceComposerClient;
     friend class SurfaceControl;
 
     // can't be copied
     Surface& operator = (Surface& rhs);
     Surface(const Surface& rhs);
 
-    Surface(const sp<SurfaceControl>& control);
+    explicit Surface(const sp<SurfaceControl>& control);
     Surface(const Parcel& data, const sp<IBinder>& ref);
     ~Surface();
 
-
-    /*
-     *  ANativeWindow hooks
-     */
-    static int setSwapInterval(ANativeWindow* window, int interval);
-    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
-    static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int query(const ANativeWindow* window, int what, int* value);
-    static int perform(ANativeWindow* window, int operation, ...);
-
-    int setSwapInterval(int interval);
-    int dequeueBuffer(ANativeWindowBuffer** buffer);
-    int lockBuffer(ANativeWindowBuffer* buffer);
-    int queueBuffer(ANativeWindowBuffer* buffer);
-    int cancelBuffer(ANativeWindowBuffer* buffer);
-    int query(int what, int* value) const;
-    int perform(int operation, va_list args);
-
     /*
      *  private stuff...
      */
-    void init();
-    status_t validate(bool inCancelBuffer = false) const;
+    void init(const sp<ISurfaceTexture>& surfaceTexture);
 
-    int getConnectedApi() const;
-    
     static void cleanCachedSurfacesLocked();
 
+    virtual int query(int what, int* value) const;
+
     // constants
-    status_t                    mInitCheck;
     sp<ISurface>                mSurface;
-    sp<SurfaceTextureClient>    mSurfaceTextureClient;
     uint32_t                    mIdentity;
-    PixelFormat                 mFormat;
-    uint32_t                    mFlags;
-    
-    // protected by mSurfaceLock. These are also used from lock/unlock
-    // but in that case, they must be called form the same thread.
-    mutable Region              mDirtyRegion;
-
-    // must be used from the lock/unlock thread
-    sp<GraphicBuffer>           mLockedBuffer;
-    sp<GraphicBuffer>           mPostedBuffer;
-    mutable Region              mOldDirtyRegion;
-    bool                        mReserved;
-
-    // query() must be called from dequeueBuffer() thread
-    uint32_t                    mWidth;
-    uint32_t                    mHeight;
-
-    // Inherently thread-safe
-    mutable Mutex               mSurfaceLock;
-    mutable Mutex               mApiLock;
 
     // A cache of Surface objects that have been deserialized into this process.
     static Mutex sCachedSurfacesLock;
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index f46f25c..848c5a1 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -55,7 +55,7 @@
 
     PIXEL_FORMAT_OPAQUE         = -1,
         // System chooses an opaque format (no alpha bits required)
-    
+
     // real pixel formats supported for rendering -----------------------------
 
     PIXEL_FORMAT_RGBA_8888   = HAL_PIXEL_FORMAT_RGBA_8888,  // 4x8-bit RGBA
@@ -84,7 +84,7 @@
         INDEX_GREEN   = 2,
         INDEX_BLUE    = 3
     };
-    
+
     enum { // components
         ALPHA               = 1,
         RGB                 = 2,
@@ -98,10 +98,10 @@
         uint8_t h;
         uint8_t l;
     };
-    
+
     inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }
     size_t getScanlineSize(unsigned int width) const;
-    size_t getSize(size_t ci) const { 
+    size_t getSize(size_t ci) const {
         return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;
     }
     size_t      version;
@@ -112,7 +112,7 @@
         szinfo      cinfo[4];
         struct {
             uint8_t     h_alpha;
-            uint8_t     l_alpha;    
+            uint8_t     l_alpha;
             uint8_t     h_red;
             uint8_t     l_red;
             uint8_t     h_green;
diff --git a/include/utils/Pool.h b/include/utils/Pool.h
deleted file mode 100644
index 2ee768e..0000000
--- a/include/utils/Pool.h
+++ /dev/null
@@ -1,71 +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 UTILS_POOL_H
-#define UTILS_POOL_H
-
-#include <utils/TypeHelpers.h>
-
-namespace android {
-
-class PoolImpl {
-public:
-    PoolImpl(size_t objSize);
-    ~PoolImpl();
-
-    void* allocImpl();
-    void freeImpl(void* obj);
-
-private:
-    size_t mObjSize;
-};
-
-/*
- * A homogeneous typed memory pool for fixed size objects.
- * Not intended to be thread-safe.
- */
-template<typename T>
-class Pool : private PoolImpl {
-public:
-    /* Creates an initially empty pool. */
-    Pool() : PoolImpl(sizeof(T)) { }
-
-    /* Destroys the pool.
-     * Assumes that the pool is empty. */
-    ~Pool() { }
-
-    /* Allocates an object from the pool, growing the pool if needed. */
-    inline T* alloc() {
-        void* mem = allocImpl();
-        if (! traits<T>::has_trivial_ctor) {
-            return new (mem) T();
-        } else {
-            return static_cast<T*>(mem);
-        }
-    }
-
-    /* Frees an object from the pool. */
-    inline void free(T* obj) {
-        if (! traits<T>::has_trivial_dtor) {
-            obj->~T();
-        }
-        freeImpl(obj);
-    }
-};
-
-} // namespace android
-
-#endif // UTILS_POOL_H
diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h
index 3a99979..547e36a 100644
--- a/include/utils/ZipFileRO.h
+++ b/include/utils/ZipFileRO.h
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <time.h>
 
 namespace android {
 
@@ -174,6 +175,20 @@
         size_t uncompLen, size_t compLen);
 
     /*
+     * Utility function to convert ZIP's time format to a timespec struct.
+     */
+    static inline void zipTimeToTimespec(long when, struct tm* timespec) {
+        const long date = when >> 16;
+        timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980
+        timespec->tm_mon = (date >> 5) & 0x0F;
+        timespec->tm_mday = date & 0x1F;
+
+        timespec->tm_hour = (when >> 11) & 0x1F;
+        timespec->tm_min = (when >> 5) & 0x3F;
+        timespec->tm_sec = (when & 0x1F) << 1;
+    }
+
+    /*
      * Some basic functions for raw data manipulation.  "LE" means
      * Little Endian.
      */
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 23ffd59..f38f6ce 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -23,8 +23,8 @@
  */
 interface IKeyChainService {
     // APIs used by KeyChain
-    byte[] getPrivateKey(String alias, String authToken);
-    byte[] getCertificate(String alias, String authToken);
+    byte[] getPrivateKey(String alias);
+    byte[] getCertificate(String alias);
 
     // APIs used by CertInstaller
     void installCaCertificate(in byte[] caCertificate);
@@ -32,4 +32,8 @@
     // APIs used by Settings
     boolean deleteCaCertificate(String alias);
     boolean reset();
+
+    // APIs used by KeyChainActivity
+    void setGrant(int uid, String alias, boolean value);
+    boolean hasGrant(int uid, String alias);
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 6229331..db6388a 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -15,36 +15,25 @@
  */
 package android.security;
 
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-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;
 import android.content.ServiceConnection;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.IOException;
-import java.security.KeyFactory;
 import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 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;
@@ -266,7 +255,7 @@
             throw new NullPointerException("response == null");
         }
         Intent intent = new Intent(ACTION_CHOOSER);
-        intent.putExtra(EXTRA_RESPONSE, new AliasResponse(activity, response));
+        intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
         intent.putExtra(EXTRA_HOST, host);
         intent.putExtra(EXTRA_PORT, port);
         intent.putExtra(EXTRA_ALIAS, alias);
@@ -276,56 +265,12 @@
     }
 
     private static class AliasResponse extends IKeyChainAliasCallback.Stub {
-        private final Activity activity;
         private final KeyChainAliasCallback keyChainAliasResponse;
-        private AliasResponse(Activity activity, KeyChainAliasCallback keyChainAliasResponse) {
-            this.activity = activity;
+        private AliasResponse(KeyChainAliasCallback keyChainAliasResponse) {
             this.keyChainAliasResponse = keyChainAliasResponse;
         }
         @Override public void alias(String alias) {
-            if (alias == null) {
-                keyChainAliasResponse.alias(null);
-                return;
-            }
-            AccountManager accountManager = AccountManager.get(activity);
-            accountManager.getAuthToken(getAccount(activity),
-                                        alias,
-                                        null,
-                                        activity,
-                                        new AliasAccountManagerCallback(keyChainAliasResponse,
-                                                                        alias),
-                                        null);
-        }
-    }
-
-    private static class AliasAccountManagerCallback implements AccountManagerCallback<Bundle> {
-        private final KeyChainAliasCallback keyChainAliasResponse;
-        private final String alias;
-        private AliasAccountManagerCallback(KeyChainAliasCallback keyChainAliasResponse,
-                                            String alias) {
-            this.keyChainAliasResponse = keyChainAliasResponse;
-            this.alias = alias;
-        }
-        @Override public void run(AccountManagerFuture<Bundle> future) {
-            Bundle bundle;
-            try {
-                bundle = future.getResult();
-            } catch (OperationCanceledException e) {
-                keyChainAliasResponse.alias(null);
-                return;
-            } catch (IOException e) {
-                keyChainAliasResponse.alias(null);
-                return;
-            } catch (AuthenticatorException e) {
-                keyChainAliasResponse.alias(null);
-                return;
-            }
-            String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
-            if (authToken != null) {
-                keyChainAliasResponse.alias(alias);
-            } else {
-                keyChainAliasResponse.alias(null);
-            }
+            keyChainAliasResponse.alias(alias);
         }
     }
 
@@ -347,12 +292,8 @@
         }
         KeyChainConnection keyChainConnection = bind(context);
         try {
-            String authToken = authToken(context, alias);
-            if (authToken == null) {
-                return null;
-            }
             IKeyChainService keyChainService = keyChainConnection.getService();
-            byte[] privateKeyBytes = keyChainService.getPrivateKey(alias, authToken);
+            byte[] privateKeyBytes = keyChainService.getPrivateKey(alias);
             return toPrivateKey(privateKeyBytes);
         } catch (RemoteException e) {
             throw new KeyChainException(e);
@@ -382,12 +323,8 @@
         }
         KeyChainConnection keyChainConnection = bind(context);
         try {
-            String authToken = authToken(context, alias);
-            if (authToken == null) {
-                return null;
-            }
             IKeyChainService keyChainService = keyChainConnection.getService();
-            byte[] certificateBytes = keyChainService.getCertificate(alias, authToken);
+            byte[] certificateBytes = keyChainService.getCertificate(alias);
             List<X509Certificate> chain = new ArrayList<X509Certificate>();
             chain.add(toCertificate(certificateBytes));
             TrustedCertificateStore store = new TrustedCertificateStore();
@@ -438,50 +375,6 @@
         }
     }
 
-    private static String authToken(Context context, String alias) {
-        AccountManager accountManager = AccountManager.get(context);
-        AccountManagerFuture<Bundle> future = accountManager.getAuthToken(getAccount(context),
-                                                                          alias,
-                                                                          false,
-                                                                          null,
-                                                                          null);
-        Bundle bundle;
-        try {
-            bundle = future.getResult();
-        } catch (OperationCanceledException e) {
-            throw new AssertionError(e);
-        } catch (IOException e) {
-            // KeyChainAccountAuthenticator doesn't do I/O
-            throw new AssertionError(e);
-        } catch (AuthenticatorException e) {
-            throw new AssertionError(e);
-        }
-        Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
-        if (intent != null) {
-            return null;
-        }
-        String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
-        if (authToken == null) {
-            throw new AssertionError("Invalid authtoken");
-        }
-        return authToken;
-    }
-
-    private static Account getAccount(Context context) {
-        AccountManager accountManager = AccountManager.get(context);
-        Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);
-        if (accounts.length == 0) {
-            try {
-                // Account is created if necessary during binding of the IKeyChainService
-                bind(context).close();
-            } catch (InterruptedException e) {
-                throw new AssertionError(e);
-            }
-            accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);
-        }
-        return accounts[0];
-    }
-
     /**
      * @hide for reuse by CertInstaller and Settings.
      * @see KeyChain#bind
@@ -517,11 +410,15 @@
         ensureNotOnMainThread(context);
         final BlockingQueue<IKeyChainService> q = new LinkedBlockingQueue<IKeyChainService>(1);
         ServiceConnection keyChainServiceConnection = new ServiceConnection() {
+            volatile boolean mConnectedAtLeastOnce = false;
             @Override public void onServiceConnected(ComponentName name, IBinder service) {
-                try {
-                    q.put(IKeyChainService.Stub.asInterface(service));
-                } catch (InterruptedException e) {
-                    throw new AssertionError(e);
+                if (!mConnectedAtLeastOnce) {
+                    mConnectedAtLeastOnce = true;
+                    try {
+                        q.put(IKeyChainService.Stub.asInterface(service));
+                    } catch (InterruptedException e) {
+                        // will never happen, since the queue starts with one available slot
+                    }
                 }
             }
             @Override public void onServiceDisconnected(ComponentName name) {}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 7264ac4..f5288c8c 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -154,11 +154,7 @@
         mBinderContextUserData = userData;
 
         int dummy = 0;
-#if defined(HAVE_ANDROID_OS)
         status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
-#else
-        status_t result = INVALID_OPERATION;
-#endif
         if (result == 0) {
             mManagesContexts = true;
         } else if (result == -1) {
@@ -304,12 +300,7 @@
     if (fd >= 0) {
         fcntl(fd, F_SETFD, FD_CLOEXEC);
         int vers;
-#if defined(HAVE_ANDROID_OS)
         status_t result = ioctl(fd, BINDER_VERSION, &vers);
-#else
-        status_t result = -1;
-        errno = EPERM;
-#endif
         if (result == -1) {
             LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
             close(fd);
@@ -320,14 +311,11 @@
             close(fd);
             fd = -1;
         }
-#if defined(HAVE_ANDROID_OS)
         size_t maxThreads = 15;
         result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
         if (result == -1) {
             LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
         }
-#endif
-        
     } else {
         LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
     }
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 9392cf2..d8fef09 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -84,6 +84,8 @@
 const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
 const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
 const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
 
 const char CameraParameters::TRUE[] = "true";
 const char CameraParameters::FALSE[] = "false";
diff --git a/libs/cpustats/Android.mk b/libs/cpustats/Android.mk
new file mode 100644
index 0000000..21bacbb
--- /dev/null
+++ b/libs/cpustats/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES :=     \
+        CentralTendencyStatistics.cpp \
+        ThreadCpuUsage.cpp
+
+LOCAL_MODULE := libcpustats
+
+include $(BUILD_STATIC_LIBRARY)
+
+#include $(CLEAR_VARS)
+#
+#LOCAL_SRC_FILES :=     \
+#       CentralTendencyStatistics.cpp \
+#       ThreadCpuUsage.cpp
+#
+#LOCAL_MODULE := libcpustats
+#
+#include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libs/cpustats/CentralTendencyStatistics.cpp b/libs/cpustats/CentralTendencyStatistics.cpp
new file mode 100644
index 0000000..42ab62b
--- /dev/null
+++ b/libs/cpustats/CentralTendencyStatistics.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 <stdlib.h>
+
+#include <cpustats/CentralTendencyStatistics.h>
+
+void CentralTendencyStatistics::sample(double x)
+{
+    // update min and max
+    if (x < mMinimum)
+        mMinimum = x;
+    if (x > mMaximum)
+        mMaximum = x;
+    // Knuth
+    if (mN == 0) {
+        mMean = 0;
+    }
+    ++mN;
+    double delta = x - mMean;
+    mMean += delta / mN;
+    mM2 += delta * (x - mMean);
+}
+
+void CentralTendencyStatistics::reset()
+{
+    mMean = NAN;
+    mMedian = NAN;
+    mMinimum = INFINITY;
+    mMaximum = -INFINITY;
+    mN = 0;
+    mM2 = 0;
+    mVariance = NAN;
+    mVarianceKnownForN = 0;
+    mStddev = NAN;
+    mStddevKnownForN = 0;
+}
+
+double CentralTendencyStatistics::variance() const
+{
+    double variance;
+    if (mVarianceKnownForN != mN) {
+        if (mN > 1) {
+            // double variance_n = M2/n;
+            variance = mM2 / (mN - 1);
+        } else {
+            variance = NAN;
+        }
+        mVariance = variance;
+        mVarianceKnownForN = mN;
+    } else {
+        variance = mVariance;
+    }
+    return variance;
+}
+
+double CentralTendencyStatistics::stddev() const
+{
+    double stddev;
+    if (mStddevKnownForN != mN) {
+        stddev = sqrt(variance());
+        mStddev = stddev;
+        mStddevKnownForN = mN;
+    } else {
+        stddev = mStddev;
+    }
+    return stddev;
+}
diff --git a/libs/cpustats/ThreadCpuUsage.cpp b/libs/cpustats/ThreadCpuUsage.cpp
new file mode 100644
index 0000000..4bfbdf3
--- /dev/null
+++ b/libs/cpustats/ThreadCpuUsage.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 <errno.h>
+#include <time.h>
+
+#include <utils/Log.h>
+
+#include <cpustats/ThreadCpuUsage.h>
+
+bool ThreadCpuUsage::setEnabled(bool isEnabled)
+{
+    bool wasEnabled = mIsEnabled;
+    // only do something if there is a change
+    if (isEnabled != wasEnabled) {
+        int rc;
+        // enabling
+        if (isEnabled) {
+            rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mPreviousTs);
+            if (rc) {
+                LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
+                isEnabled = false;
+            } else {
+                mWasEverEnabled = true;
+                // record wall clock time at first enable
+                if (!mMonotonicKnown) {
+                    rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs);
+                    if (rc) {
+                        LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
+                    } else {
+                        mMonotonicKnown = true;
+                    }
+                }
+            }
+        // disabling
+        } else {
+            struct timespec ts;
+            rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
+            if (rc) {
+                LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
+            } else {
+                long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL +
+                        (ts.tv_nsec - mPreviousTs.tv_nsec);
+                mAccumulator += delta;
+#if 0
+                mPreviousTs = ts;
+#endif
+            }
+        }
+        mIsEnabled = isEnabled;
+    }
+    return wasEnabled;
+}
+
+void ThreadCpuUsage::sampleAndEnable()
+{
+    bool wasEverEnabled = mWasEverEnabled;
+    if (enable()) {
+        // already enabled, so add a new sample relative to previous
+        sample();
+    } else if (wasEverEnabled) {
+        // was disabled, but add sample for accumulated time while enabled
+        mStatistics.sample((double) mAccumulator);
+        mAccumulator = 0;
+    }
+}
+
+void ThreadCpuUsage::sample()
+{
+    if (mWasEverEnabled) {
+        if (mIsEnabled) {
+            struct timespec ts;
+            int rc;
+            rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
+            if (rc) {
+                LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
+            } else {
+                long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL +
+                        (ts.tv_nsec - mPreviousTs.tv_nsec);
+                mAccumulator += delta;
+                mPreviousTs = ts;
+            }
+        } else {
+            mWasEverEnabled = false;
+        }
+        mStatistics.sample((double) mAccumulator);
+        mAccumulator = 0;
+    } else {
+        LOGW("Can't add sample because measurements have never been enabled");
+    }
+}
+
+long long ThreadCpuUsage::elapsed() const
+{
+    long long elapsed;
+    if (mMonotonicKnown) {
+        struct timespec ts;
+        int rc;
+        rc = clock_gettime(CLOCK_MONOTONIC, &ts);
+        if (rc) {
+            LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
+            elapsed = 0;
+        } else {
+            // mMonotonicTs is updated only at first enable and resetStatistics
+            elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL +
+                    (ts.tv_nsec - mMonotonicTs.tv_nsec);
+        }
+    } else {
+        LOGW("Can't compute elapsed time because measurements have never been enabled");
+        elapsed = 0;
+    }
+    return elapsed;
+}
+
+void ThreadCpuUsage::resetStatistics()
+{
+    mStatistics.reset();
+    if (mMonotonicKnown) {
+        int rc;
+        rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs);
+        if (rc) {
+            LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
+            mMonotonicKnown = false;
+        }
+    }
+}
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index bc97cac..ace16aa 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -132,9 +132,6 @@
 {
     token    = parcel.readInt32();
     identity = parcel.readInt32();
-    width    = parcel.readInt32();
-    height   = parcel.readInt32();
-    format   = parcel.readInt32();
     return NO_ERROR;
 }
 
@@ -142,9 +139,6 @@
 {
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
-    parcel->writeInt32(width);
-    parcel->writeInt32(height);
-    parcel->writeInt32(format);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 16e3780..55246dc 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -38,9 +38,11 @@
     CANCEL_BUFFER,
     SET_CROP,
     SET_TRANSFORM,
-    GET_ALLOCATOR,
     QUERY,
     SET_SYNCHRONOUS_MODE,
+    CONNECT,
+    DISCONNECT,
+    SET_SCALING_MODE,
 };
 
 
@@ -52,18 +54,18 @@
     {
     }
 
-    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
+    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
         data.writeInt32(bufferIdx);
         remote()->transact(REQUEST_BUFFER, data, &reply);
-        sp<GraphicBuffer> buffer;
         bool nonNull = reply.readInt32();
         if (nonNull) {
-            buffer = new GraphicBuffer();
-            reply.read(*buffer);
+            *buf = new GraphicBuffer();
+            reply.read(**buf);
         }
-        return buffer;
+        status_t result = reply.readInt32();
+        return result;
     }
 
     virtual status_t setBufferCount(int bufferCount)
@@ -90,12 +92,16 @@
         return result;
     }
 
-    virtual status_t queueBuffer(int buf, int64_t timestamp) {
+    virtual status_t queueBuffer(int buf, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
         data.writeInt32(buf);
         data.writeInt64(timestamp);
         remote()->transact(QUEUE_BUFFER, data, &reply);
+        *outWidth = reply.readInt32();
+        *outHeight = reply.readInt32();
+        *outTransform = reply.readInt32();
         status_t result = reply.readInt32();
         return result;
     }
@@ -128,11 +134,13 @@
         return result;
     }
 
-    virtual sp<IBinder> getAllocator() {
+    virtual status_t setScalingMode(int mode) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
-        remote()->transact(GET_ALLOCATOR, data, &reply);
-        return reply.readStrongBinder();
+        data.writeInt32(mode);
+        remote()->transact(SET_SCALING_MODE, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
     }
 
     virtual int query(int what, int* value) {
@@ -154,7 +162,23 @@
         return result;
     }
 
+    virtual status_t connect(int api) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(api);
+        remote()->transact(CONNECT, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
 
+    virtual status_t disconnect(int api) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(api);
+        remote()->transact(DISCONNECT, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -168,11 +192,13 @@
         case REQUEST_BUFFER: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             int bufferIdx   = data.readInt32();
-            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
+            sp<GraphicBuffer> buffer;
+            int result = requestBuffer(bufferIdx, &buffer);
             reply->writeInt32(buffer != 0);
             if (buffer != 0) {
                 reply->write(*buffer);
             }
+            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         case SET_BUFFER_COUNT: {
@@ -198,7 +224,12 @@
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             int buf = data.readInt32();
             int64_t timestamp = data.readInt64();
-            status_t result = queueBuffer(buf, timestamp);
+            uint32_t outWidth, outHeight, outTransform;
+            status_t result = queueBuffer(buf, timestamp,
+                    &outWidth, &outHeight, &outTransform);
+            reply->writeInt32(outWidth);
+            reply->writeInt32(outHeight);
+            reply->writeInt32(outTransform);
             reply->writeInt32(result);
             return NO_ERROR;
         } break;
@@ -226,10 +257,11 @@
             reply->writeInt32(result);
             return NO_ERROR;
         } break;
-        case GET_ALLOCATOR: {
+        case SET_SCALING_MODE: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
-            sp<IBinder> result = getAllocator();
-            reply->writeStrongBinder(result);
+            int mode = data.readInt32();
+            status_t result = setScalingMode(mode);
+            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         case QUERY: {
@@ -248,6 +280,20 @@
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
+        case CONNECT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int api = data.readInt32();
+            status_t res = connect(api);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case DISCONNECT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int api = data.readInt32();
+            status_t res = disconnect(api);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9185e1e..ccf98e5 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -26,15 +26,12 @@
 #include <utils/Log.h>
 #include <utils/threads.h>
 
-#include <binder/IMemory.h>
 #include <binder/IPCThreadState.h>
 
 #include <gui/SurfaceTextureClient.h>
 
 #include <ui/DisplayInfo.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <ui/GraphicLog.h>
 #include <ui/Rect.h>
 
 #include <surfaceflinger/ISurface.h>
@@ -42,63 +39,8 @@
 #include <surfaceflinger/Surface.h>
 #include <surfaceflinger/SurfaceComposerClient.h>
 
-#include <private/surfaceflinger/LayerState.h>
-
 namespace android {
 
-// ----------------------------------------------------------------------
-
-static status_t copyBlt(
-        const sp<GraphicBuffer>& dst, 
-        const sp<GraphicBuffer>& src, 
-        const Region& reg)
-{
-    // src and dst with, height and format must be identical. no verification
-    // is done here.
-    status_t err;
-    uint8_t const * src_bits = NULL;
-    err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
-    LOGE_IF(err, "error locking src buffer %s", strerror(-err));
-
-    uint8_t* dst_bits = NULL;
-    err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
-    LOGE_IF(err, "error locking dst buffer %s", strerror(-err));
-
-    Region::const_iterator head(reg.begin());
-    Region::const_iterator tail(reg.end());
-    if (head != tail && src_bits && dst_bits) {
-        const size_t bpp = bytesPerPixel(src->format);
-        const size_t dbpr = dst->stride * bpp;
-        const size_t sbpr = src->stride * bpp;
-
-        while (head != tail) {
-            const Rect& r(*head++);
-            ssize_t h = r.height();
-            if (h <= 0) continue;
-            size_t size = r.width() * bpp;
-            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
-            uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
-            if (dbpr==sbpr && size==sbpr) {
-                size *= h;
-                h = 1;
-            }
-            do {
-                memcpy(d, s, size);
-                d += dbpr;
-                s += sbpr;
-            } while (--h > 0);
-        }
-    }
-    
-    if (src_bits)
-        src->unlock();
-    
-    if (dst_bits)
-        dst->unlock();
-    
-    return err;
-}
-
 // ============================================================================
 //  SurfaceControl
 // ============================================================================
@@ -106,12 +48,9 @@
 SurfaceControl::SurfaceControl(
         const sp<SurfaceComposerClient>& client, 
         const sp<ISurface>& surface,
-        const ISurfaceComposerClient::surface_data_t& data,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+        const ISurfaceComposerClient::surface_data_t& data)
     : mClient(client), mSurface(surface),
-      mToken(data.token), mIdentity(data.identity),
-      mWidth(data.width), mHeight(data.height), mFormat(data.format),
-      mFlags(flags)
+      mToken(data.token), mIdentity(data.identity)
 {
 }
         
@@ -240,24 +179,13 @@
 {
     sp<ISurface> sur;
     uint32_t identity = 0;
-    uint32_t width = 0;
-    uint32_t height = 0;
-    uint32_t format = 0;
-    uint32_t flags = 0;
     if (SurfaceControl::isValid(control)) {
         sur      = control->mSurface;
         identity = control->mIdentity;
-        width    = control->mWidth;
-        height   = control->mHeight;
-        format   = control->mFormat;
-        flags    = control->mFlags;
     }
     parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+    parcel->writeStrongBinder(NULL);  // NULL ISurfaceTexture in this case.
     parcel->writeInt32(identity);
-    parcel->writeInt32(width);
-    parcel->writeInt32(height);
-    parcel->writeInt32(format);
-    parcel->writeInt32(flags);
     return NO_ERROR;
 }
 
@@ -265,7 +193,8 @@
 {
     Mutex::Autolock _l(mLock);
     if (mSurfaceData == 0) {
-        mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
+        sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));
+        mSurfaceData = new Surface(surface_control);
     }
     return mSurfaceData;
 }
@@ -277,57 +206,63 @@
 // ---------------------------------------------------------------------------
 
 Surface::Surface(const sp<SurfaceControl>& surface)
-    : mInitCheck(NO_INIT),
+    : SurfaceTextureClient(),
       mSurface(surface->mSurface),
-      mIdentity(surface->mIdentity),
-      mFormat(surface->mFormat), mFlags(surface->mFlags),
-      mWidth(surface->mWidth), mHeight(surface->mHeight)
+      mIdentity(surface->mIdentity)
 {
-    init();
+    sp<ISurfaceTexture> st;
+    if (mSurface != NULL) {
+        st = mSurface->getSurfaceTexture();
+    }
+    init(st);
 }
 
 Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
-    : mInitCheck(NO_INIT)
+    : SurfaceTextureClient()
 {
-    mSurface    = interface_cast<ISurface>(ref);
+    mSurface = interface_cast<ISurface>(ref);
+    sp<IBinder> st_binder(parcel.readStrongBinder());
+    sp<ISurfaceTexture> st;
+    if (st_binder != NULL) {
+        st = interface_cast<ISurfaceTexture>(st_binder);
+    } else if (mSurface != NULL) {
+        st = mSurface->getSurfaceTexture();
+    }
+
     mIdentity   = parcel.readInt32();
-    mWidth      = parcel.readInt32();
-    mHeight     = parcel.readInt32();
-    mFormat     = parcel.readInt32();
-    mFlags      = parcel.readInt32();
-    init();
+    init(st);
+}
+
+Surface::Surface(const sp<ISurfaceTexture>& st)
+    : SurfaceTextureClient(),
+      mSurface(NULL),
+      mIdentity(0)
+{
+    init(st);
 }
 
 status_t Surface::writeToParcel(
         const sp<Surface>& surface, Parcel* parcel)
 {
     sp<ISurface> sur;
+    sp<ISurfaceTexture> st;
     uint32_t identity = 0;
-    uint32_t width = 0;
-    uint32_t height = 0;
-    uint32_t format = 0;
-    uint32_t flags = 0;
     if (Surface::isValid(surface)) {
         sur      = surface->mSurface;
+        st       = surface->getISurfaceTexture();
         identity = surface->mIdentity;
-        width    = surface->mWidth;
-        height   = surface->mHeight;
-        format   = surface->mFormat;
-        flags    = surface->mFlags;
-    } else if (surface != 0 && surface->mSurface != 0) {
-        LOGW("Parceling invalid surface with non-NULL ISurface as NULL: "
-             "mSurface = %p, mIdentity = %d, mWidth = %d, mHeight = %d, "
-             "mFormat = %d, mFlags = 0x%08x, mInitCheck = %d",
-             surface->mSurface.get(), surface->mIdentity, surface->mWidth,
-             surface->mHeight, surface->mFormat, surface->mFlags,
-             surface->mInitCheck);
+    } else if (surface != 0 &&
+            (surface->mSurface != NULL ||
+             surface->getISurfaceTexture() != NULL)) {
+        LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: "
+             "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ",
+             surface->mSurface.get(), surface->getISurfaceTexture().get(),
+             surface->mIdentity);
     }
-    parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+
+    parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL);
+    parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL);
     parcel->writeInt32(identity);
-    parcel->writeInt32(width);
-    parcel->writeInt32(height);
-    parcel->writeInt32(format);
-    parcel->writeInt32(flags);
     return NO_ERROR;
 
 }
@@ -343,8 +278,8 @@
        surface = new Surface(data, binder);
        sCachedSurfaces.add(binder, surface);
     }
-    if (surface->mSurface == 0) {
-      surface = 0;
+    if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
+        surface = 0;
     }
     cleanCachedSurfacesLocked();
     return surface;
@@ -361,40 +296,20 @@
     }
 }
 
-void Surface::init()
+void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
 {
-    ANativeWindow::setSwapInterval  = setSwapInterval;
-    ANativeWindow::dequeueBuffer    = dequeueBuffer;
-    ANativeWindow::cancelBuffer     = cancelBuffer;
-    ANativeWindow::lockBuffer       = lockBuffer;
-    ANativeWindow::queueBuffer      = queueBuffer;
-    ANativeWindow::query            = query;
-    ANativeWindow::perform          = perform;
-
-    if (mSurface != NULL) {
-        sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
+    if (mSurface != NULL || surfaceTexture != NULL) {
         LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
         if (surfaceTexture != NULL) {
-            mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
-            mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER);
+            setISurfaceTexture(surfaceTexture);
+            setUsage(GraphicBuffer::USAGE_HW_RENDER);
         }
 
         DisplayInfo dinfo;
         SurfaceComposerClient::getDisplayInfo(0, &dinfo);
         const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
         const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
-
-        const_cast<int&>(ANativeWindow::minSwapInterval) =
-                mSurfaceTextureClient->minSwapInterval;
-
-        const_cast<int&>(ANativeWindow::maxSwapInterval) =
-                mSurfaceTextureClient->maxSwapInterval;
-
         const_cast<uint32_t&>(ANativeWindow::flags) = 0;
-
-        if (mSurfaceTextureClient != 0) {
-            mInitCheck = NO_ERROR;
-        }
     }
 }
 
@@ -402,27 +317,16 @@
 {
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
-    mSurfaceTextureClient.clear();
     mSurface.clear();
     IPCThreadState::self()->flushCommands();
 }
 
 bool Surface::isValid() {
-    return mInitCheck == NO_ERROR;
-}
-
-status_t Surface::validate(bool inCancelBuffer) const
-{
-    // check that we initialized ourself properly
-    if (mInitCheck != NO_ERROR) {
-        LOGE("invalid token (identity=%u)", mIdentity);
-        return mInitCheck;
-    }
-    return NO_ERROR;
+    return getISurfaceTexture() != NULL;
 }
 
 sp<ISurfaceTexture> Surface::getSurfaceTexture() {
-    return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL;
+    return getISurfaceTexture();
 }
 
 sp<IBinder> Surface::asBinder() const {
@@ -431,219 +335,45 @@
 
 // ----------------------------------------------------------------------------
 
-int Surface::setSwapInterval(ANativeWindow* window, int interval) {
-    Surface* self = getSelf(window);
-    return self->setSwapInterval(interval);
-}
-
-int Surface::dequeueBuffer(ANativeWindow* window, 
-        ANativeWindowBuffer** buffer) {
-    Surface* self = getSelf(window);
-    return self->dequeueBuffer(buffer);
-}
-
-int Surface::cancelBuffer(ANativeWindow* window,
-        ANativeWindowBuffer* buffer) {
-    Surface* self = getSelf(window);
-    return self->cancelBuffer(buffer);
-}
-
-int Surface::lockBuffer(ANativeWindow* window, 
-        ANativeWindowBuffer* buffer) {
-    Surface* self = getSelf(window);
-    return self->lockBuffer(buffer);
-}
-
-int Surface::queueBuffer(ANativeWindow* window, 
-        ANativeWindowBuffer* buffer) {
-    Surface* self = getSelf(window);
-    return self->queueBuffer(buffer);
-}
-
-int Surface::query(const ANativeWindow* window,
-        int what, int* value) {
-    const Surface* self = getSelf(window);
-    return self->query(what, value);
-}
-
-int Surface::perform(ANativeWindow* window, 
-        int operation, ...) {
-    va_list args;
-    va_start(args, operation);
-    Surface* self = getSelf(window);
-    int res = self->perform(operation, args);
-    va_end(args);
-    return res;
-}
-
-// ----------------------------------------------------------------------------
-
-int Surface::setSwapInterval(int interval) {
-    return mSurfaceTextureClient->setSwapInterval(interval);
-}
-
-int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) {
-    status_t err = mSurfaceTextureClient->dequeueBuffer(buffer);
-    if (err == NO_ERROR) {
-        mDirtyRegion.set(buffer[0]->width, buffer[0]->height);
-    }
-    return err;
-}
-
-int Surface::cancelBuffer(ANativeWindowBuffer* buffer) {
-    return mSurfaceTextureClient->cancelBuffer(buffer);
-}
-
-int Surface::lockBuffer(ANativeWindowBuffer* buffer) {
-    return mSurfaceTextureClient->lockBuffer(buffer);
-}
-
-int Surface::queueBuffer(ANativeWindowBuffer* buffer) {
-    return mSurfaceTextureClient->queueBuffer(buffer);
-}
-
 int Surface::query(int what, int* value) const {
     switch (what) {
     case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-        // TODO: this is not needed anymore
         *value = 1;
         return NO_ERROR;
     case NATIVE_WINDOW_CONCRETE_TYPE:
-        // TODO: this is not needed anymore
         *value = NATIVE_WINDOW_SURFACE;
         return NO_ERROR;
     }
-    return mSurfaceTextureClient->query(what, value);
-}
-
-int Surface::perform(int operation, va_list args) {
-    return mSurfaceTextureClient->perform(operation, args);
+    return SurfaceTextureClient::query(what, value);
 }
 
 // ----------------------------------------------------------------------------
 
-int Surface::getConnectedApi() const {
-    return mSurfaceTextureClient->getConnectedApi();
-}
+status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn) {
+    ANativeWindow_Buffer outBuffer;
 
-// ----------------------------------------------------------------------------
-
-status_t Surface::lock(SurfaceInfo* info, bool blocking) {
-    return Surface::lock(info, NULL, blocking);
-}
-
-status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
-{
-    if (getConnectedApi()) {
-        LOGE("Surface::lock(%p) failed. Already connected to another API",
-                (ANativeWindow*)this);
-        CallStack stack;
-        stack.update();
-        stack.dump("");
-        return INVALID_OPERATION;
+    ARect temp;
+    ARect* inOutDirtyBounds = NULL;
+    if (dirtyIn) {
+        temp = dirtyIn->getBounds();
+        inOutDirtyBounds = &temp;
     }
 
-    if (mApiLock.tryLock() != NO_ERROR) {
-        LOGE("calling Surface::lock from different threads!");
-        CallStack stack;
-        stack.update();
-        stack.dump("");
-        return WOULD_BLOCK;
-    }
+    status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);
 
-    /* Here we're holding mApiLock */
-    
-    if (mLockedBuffer != 0) {
-        LOGE("Surface::lock failed, already locked");
-        mApiLock.unlock();
-        return INVALID_OPERATION;
-    }
-
-    // we're intending to do software rendering from this point
-    mSurfaceTextureClient->setUsage(
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-
-    ANativeWindowBuffer* out;
-    status_t err = mSurfaceTextureClient->dequeueBuffer(&out);
-    LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
     if (err == NO_ERROR) {
-        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
-        err = mSurfaceTextureClient->lockBuffer(backBuffer.get());
-        LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
-                backBuffer->handle, strerror(-err));
-        if (err == NO_ERROR) {
-            const Rect bounds(backBuffer->width, backBuffer->height);
-            const Region boundsRegion(bounds);
-            Region scratch(boundsRegion);
-            Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
-            newDirtyRegion &= boundsRegion;
-
-            // figure out if we can copy the frontbuffer back
-            const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
-            const bool canCopyBack = (frontBuffer != 0 &&
-                    backBuffer->width  == frontBuffer->width &&
-                    backBuffer->height == frontBuffer->height &&
-                    backBuffer->format == frontBuffer->format &&
-                    !(mFlags & ISurfaceComposer::eDestroyBackbuffer));
-
-            // the dirty region we report to surfaceflinger is the one
-            // given by the user (as opposed to the one *we* return to the
-            // user).
-            mDirtyRegion = newDirtyRegion;
-
-            if (canCopyBack) {
-                // copy the area that is invalid and not repainted this round
-                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
-                if (!copyback.isEmpty())
-                    copyBlt(backBuffer, frontBuffer, copyback);
-            } else {
-                // if we can't copy-back anything, modify the user's dirty
-                // region to make sure they redraw the whole buffer
-                newDirtyRegion = boundsRegion;
-            }
-
-            // keep track of the are of the buffer that is "clean"
-            // (ie: that will be redrawn)
-            mOldDirtyRegion = newDirtyRegion;
-
-            void* vaddr;
-            status_t res = backBuffer->lock(
-                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-                    newDirtyRegion.bounds(), &vaddr);
-            
-            LOGW_IF(res, "failed locking buffer (handle = %p)", 
-                    backBuffer->handle);
-
-            mLockedBuffer = backBuffer;
-            other->w      = backBuffer->width;
-            other->h      = backBuffer->height;
-            other->s      = backBuffer->stride;
-            other->usage  = backBuffer->usage;
-            other->format = backBuffer->format;
-            other->bits   = vaddr;
-        }
+        other->w = uint32_t(outBuffer.width);
+        other->h = uint32_t(outBuffer.height);
+        other->s = uint32_t(outBuffer.stride);
+        other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+        other->format = uint32_t(outBuffer.format);
+        other->bits = outBuffer.bits;
     }
-    mApiLock.unlock();
     return err;
 }
-    
-status_t Surface::unlockAndPost() 
-{
-    if (mLockedBuffer == 0) {
-        LOGE("Surface::unlockAndPost failed, no locked buffer");
-        return INVALID_OPERATION;
-    }
 
-    status_t err = mLockedBuffer->unlock();
-    LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
-    
-    err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get());
-    LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
-            mLockedBuffer->handle, strerror(-err));
-
-    mPostedBuffer = mLockedBuffer;
-    mLockedBuffer = 0;
-    return err;
+status_t Surface::unlockAndPost() {
+    return SurfaceTextureClient::unlockAndPost();
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8cead80..3b0ffea 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -339,7 +339,7 @@
         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);
+            result = new SurfaceControl(this, surface, data);
         }
     }
     return result;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 886a3fb..16755ad 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -86,13 +86,15 @@
     mClientBufferCount(0),
     mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
     mCurrentTexture(INVALID_BUFFER_SLOT),
-    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
     mCurrentTransform(0),
     mCurrentTimestamp(0),
     mNextTransform(0),
+    mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mTexName(tex),
     mSynchronousMode(false),
-    mAllowSynchronousMode(allowSynchronousMode) {
+    mAllowSynchronousMode(allowSynchronousMode),
+    mConnectedApi(NO_CONNECTED_API),
+    mAbandoned(false) {
     LOGV("SurfaceTexture::SurfaceTexture");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -148,6 +150,11 @@
     LOGV("SurfaceTexture::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
+    if (mAbandoned) {
+        LOGE("setBufferCount: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
     if (bufferCount > NUM_BUFFER_SLOTS) {
         LOGE("setBufferCount: bufferCount larger than slots available");
         return BAD_VALUE;
@@ -189,30 +196,43 @@
 
 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
 {
-    Mutex::Autolock lock(mMutex);
-    if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
-        mDefaultWidth = w;
-        mDefaultHeight = h;
+    if (!w || !h) {
+        LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", w, h);
+        return BAD_VALUE;
     }
+
+    Mutex::Autolock lock(mMutex);
+    mDefaultWidth = w;
+    mDefaultHeight = h;
     return OK;
 }
 
-sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
+status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
     LOGV("SurfaceTexture::requestBuffer");
     Mutex::Autolock lock(mMutex);
-    if (buf < 0 || mBufferCount <= buf) {
-        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
-                mBufferCount, buf);
-        return 0;
+    if (mAbandoned) {
+        LOGE("requestBuffer: SurfaceTexture has been abandoned!");
+        return NO_INIT;
     }
-    mSlots[buf].mRequestBufferCalled = true;
-    return mSlots[buf].mGraphicBuffer;
+    if (slot < 0 || mBufferCount <= slot) {
+        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, slot);
+        return BAD_VALUE;
+    }
+    mSlots[slot].mRequestBufferCalled = true;
+    *buf = mSlots[slot].mGraphicBuffer;
+    return NO_ERROR;
 }
 
 status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
         uint32_t format, uint32_t usage) {
     LOGV("SurfaceTexture::dequeueBuffer");
 
+    if (mAbandoned) {
+        LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
     if ((w && !h) || (!w && h)) {
         LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
         return BAD_VALUE;
@@ -250,6 +270,11 @@
             // wait for the FIFO to drain
             while (!mQueue.isEmpty()) {
                 mDequeueCondition.wait(mMutex);
+                if (mAbandoned) {
+                    LOGE("dequeueBuffer: SurfaceTexture was abandoned while "
+                            "blocked!");
+                    return NO_INIT;
+                }
             }
             minBufferCountNeeded = mSynchronousMode ?
                     MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
@@ -378,6 +403,11 @@
 status_t SurfaceTexture::setSynchronousMode(bool enabled) {
     Mutex::Autolock lock(mMutex);
 
+    if (mAbandoned) {
+        LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
     status_t err = OK;
     if (!mAllowSynchronousMode && enabled)
         return err;
@@ -400,13 +430,18 @@
     return err;
 }
 
-status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
+status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
+        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
     LOGV("SurfaceTexture::queueBuffer");
 
     sp<FrameAvailableListener> listener;
 
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
+        if (mAbandoned) {
+            LOGE("queueBuffer: SurfaceTexture has been abandoned!");
+            return NO_INIT;
+        }
         if (buf < 0 || buf >= mBufferCount) {
             LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                     mBufferCount, buf);
@@ -452,6 +487,7 @@
         mSlots[buf].mBufferState = BufferSlot::QUEUED;
         mSlots[buf].mCrop = mNextCrop;
         mSlots[buf].mTransform = mNextTransform;
+        mSlots[buf].mScalingMode = mNextScalingMode;
         mSlots[buf].mTimestamp = timestamp;
         mDequeueCondition.signal();
     } // scope for the lock
@@ -460,12 +496,23 @@
     if (listener != 0) {
         listener->onFrameAvailable();
     }
+
+    *outWidth = mDefaultWidth;
+    *outHeight = mDefaultHeight;
+    *outTransform = 0;
+
     return OK;
 }
 
 void SurfaceTexture::cancelBuffer(int buf) {
     LOGV("SurfaceTexture::cancelBuffer");
     Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
+        return;
+    }
+
     if (buf < 0 || buf >= mBufferCount) {
         LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                 mBufferCount, buf);
@@ -482,6 +529,10 @@
 status_t SurfaceTexture::setCrop(const Rect& crop) {
     LOGV("SurfaceTexture::setCrop");
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        LOGE("setCrop: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
     mNextCrop = crop;
     return OK;
 }
@@ -489,10 +540,90 @@
 status_t SurfaceTexture::setTransform(uint32_t transform) {
     LOGV("SurfaceTexture::setTransform");
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        LOGE("setTransform: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
     mNextTransform = transform;
     return OK;
 }
 
+status_t SurfaceTexture::connect(int api) {
+    LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        LOGE("connect: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi != NO_CONNECTED_API) {
+                LOGE("connect: already connected (cur=%d, req=%d)",
+                        mConnectedApi, api);
+                err = -EINVAL;
+            } else {
+                mConnectedApi = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceTexture::disconnect(int api) {
+    LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        LOGE("connect: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi == api) {
+                mConnectedApi = NO_CONNECTED_API;
+            } else {
+                LOGE("disconnect: connected to another api (cur=%d, req=%d)",
+                        mConnectedApi, api);
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceTexture::setScalingMode(int mode) {
+    LOGV("SurfaceTexture::setScalingMode(%d)", mode);
+
+    switch (mode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    mNextScalingMode = mode;
+    return OK;
+}
+
 status_t SurfaceTexture::updateTexImage() {
     LOGV("SurfaceTexture::updateTexImage");
     Mutex::Autolock lock(mMutex);
@@ -522,12 +653,8 @@
             LOGW("updateTexImage: clearing GL error: %#04x", error);
         }
 
-        GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format);
-        if (target != mCurrentTextureTarget) {
-            glDeleteTextures(1, &mTexName);
-        }
-        glBindTexture(target, mTexName);
-        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
 
         bool failed = false;
         while ((error = glGetError()) != GL_NO_ERROR) {
@@ -549,10 +676,10 @@
 
         // Update the SurfaceTexture state.
         mCurrentTexture = buf;
-        mCurrentTextureTarget = target;
         mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
         mCurrentCrop = mSlots[buf].mCrop;
         mCurrentTransform = mSlots[buf].mTransform;
+        mCurrentScalingMode = mSlots[buf].mScalingMode;
         mCurrentTimestamp = mSlots[buf].mTimestamp;
         computeCurrentTransformMatrix();
 
@@ -562,7 +689,7 @@
         mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
-        glBindTexture(mCurrentTextureTarget, mTexName);
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
     }
 
     return OK;
@@ -587,20 +714,8 @@
     return false;
 }
 
-GLenum SurfaceTexture::getTextureTarget(uint32_t format)
-{
-    GLenum target = GL_TEXTURE_2D;
-#if defined(GL_OES_EGL_image_external)
-    if (isExternalFormat(format)) {
-        target = GL_TEXTURE_EXTERNAL_OES;
-    }
-#endif
-    return target;
-}
-
 GLenum SurfaceTexture::getCurrentTextureTarget() const {
-    Mutex::Autolock lock(mMutex);
-    return mCurrentTextureTarget;
+    return GL_TEXTURE_EXTERNAL_OES;
 }
 
 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
@@ -712,11 +827,6 @@
     mFrameAvailableListener = listener;
 }
 
-sp<IBinder> SurfaceTexture::getAllocator() {
-    LOGV("SurfaceTexture::getAllocator");
-    return mGraphicBufferAlloc->asBinder();
-}
-
 void SurfaceTexture::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].mGraphicBuffer = 0;
@@ -760,20 +870,27 @@
     return mCurrentTransform;
 }
 
+uint32_t SurfaceTexture::getCurrentScalingMode() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentScalingMode;
+}
+
 int SurfaceTexture::query(int what, int* outValue)
 {
     Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        LOGE("query: SurfaceTexture has been abandoned!");
+        return NO_INIT;
+    }
+
     int value;
     switch (what) {
     case NATIVE_WINDOW_WIDTH:
         value = mDefaultWidth;
-        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
-            value = mCurrentTextureBuf->width;
         break;
     case NATIVE_WINDOW_HEIGHT:
         value = mDefaultHeight;
-        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
-            value = mCurrentTextureBuf->height;
         break;
     case NATIVE_WINDOW_FORMAT:
         value = mPixelFormat;
@@ -789,6 +906,13 @@
     return NO_ERROR;
 }
 
+void SurfaceTexture::abandon() {
+    Mutex::Autolock lock(mMutex);
+    freeAllBuffers();
+    mAbandoned = true;
+    mDequeueCondition.signal();
+}
+
 void SurfaceTexture::dump(String8& result) const
 {
     char buffer[1024];
@@ -816,12 +940,12 @@
     }
 
     snprintf(buffer, SIZE,
-            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n"
+            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
             "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
             ,
             prefix, mCurrentCrop.left,
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
-            mCurrentTransform, mCurrentTexture, mCurrentTextureTarget,
+            mCurrentTransform, mCurrentTexture,
             prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
             mCurrentTransform, fifoSize, fifo.string()
     );
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index e203035..e6837ea 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -24,68 +24,86 @@
 namespace android {
 
 SurfaceTextureClient::SurfaceTextureClient(
-        const sp<ISurfaceTexture>& surfaceTexture):
-        mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
-        mReqHeight(0), mReqFormat(0), mReqUsage(0),
-        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
-        mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
-        mMutex() {
+        const sp<ISurfaceTexture>& surfaceTexture)
+{
+    SurfaceTextureClient::init();
+    SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
+}
+
+SurfaceTextureClient::SurfaceTextureClient() {
+    SurfaceTextureClient::init();
+}
+
+void SurfaceTextureClient::init() {
     // Initialize the ANativeWindow function pointers.
-    ANativeWindow::setSwapInterval  = setSwapInterval;
-    ANativeWindow::dequeueBuffer    = dequeueBuffer;
-    ANativeWindow::cancelBuffer     = cancelBuffer;
-    ANativeWindow::lockBuffer       = lockBuffer;
-    ANativeWindow::queueBuffer      = queueBuffer;
-    ANativeWindow::query            = query;
-    ANativeWindow::perform          = perform;
+    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
+    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
+    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
+    ANativeWindow::lockBuffer       = hook_lockBuffer;
+    ANativeWindow::queueBuffer      = hook_queueBuffer;
+    ANativeWindow::query            = hook_query;
+    ANativeWindow::perform          = hook_perform;
 
     const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
 
-    // Get a reference to the allocator.
-    mAllocator = mSurfaceTexture->getAllocator();
+    mReqWidth = 0;
+    mReqHeight = 0;
+    mReqFormat = 0;
+    mReqUsage = 0;
+    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
+    mDefaultWidth = 0;
+    mDefaultHeight = 0;
+    mTransformHint = 0;
+    mConnectedToCpu = false;
+}
+
+void SurfaceTextureClient::setISurfaceTexture(
+        const sp<ISurfaceTexture>& surfaceTexture)
+{
+    mSurfaceTexture = surfaceTexture;
 }
 
 sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const {
     return mSurfaceTexture;
 }
 
-int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
+int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interval) {
     SurfaceTextureClient* c = getSelf(window);
     return c->setSwapInterval(interval);
 }
 
-int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
+int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window,
         ANativeWindowBuffer** buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->dequeueBuffer(buffer);
 }
 
-int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
+int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window,
         ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->cancelBuffer(buffer);
 }
 
-int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
+int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window,
         ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->lockBuffer(buffer);
 }
 
-int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
+int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window,
         ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->queueBuffer(buffer);
 }
 
-int SurfaceTextureClient::query(const ANativeWindow* window,
+int SurfaceTextureClient::hook_query(const ANativeWindow* window,
                                 int what, int* value) {
     const SurfaceTextureClient* c = getSelf(window);
     return c->query(what, value);
 }
 
-int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
+int SurfaceTextureClient::hook_perform(ANativeWindow* window, int operation, ...) {
     va_list args;
     va_start(args, operation);
     SurfaceTextureClient* c = getSelf(window);
@@ -127,14 +145,12 @@
     }
 
     if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
-        gbuf = mSurfaceTexture->requestBuffer(buf);
-        if (gbuf == 0) {
-            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
-            return NO_MEMORY;
+        result = mSurfaceTexture->requestBuffer(buf, &gbuf);
+        if (result != NO_ERROR) {
+            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
+                    result);
+            return result;
         }
-        mQueryWidth  = gbuf->width;
-        mQueryHeight = gbuf->height;
-        mQueryFormat = gbuf->format;
     }
     *buffer = gbuf.get();
     return OK;
@@ -201,27 +217,38 @@
     if (i < 0) {
         return i;
     }
-    mSurfaceTexture->queueBuffer(i, timestamp);
+    mSurfaceTexture->queueBuffer(i, timestamp,
+            &mDefaultWidth, &mDefaultHeight, &mTransformHint);
     return OK;
 }
 
 int SurfaceTextureClient::query(int what, int* value) const {
     LOGV("SurfaceTextureClient::query");
-    switch (what) {
-    case NATIVE_WINDOW_FORMAT:
-        if (mReqFormat) {
-            *value = mReqFormat;
-            return NO_ERROR;
+    { // scope for the lock
+        Mutex::Autolock lock(mMutex);
+        switch (what) {
+            case NATIVE_WINDOW_FORMAT:
+                if (mReqFormat) {
+                    *value = mReqFormat;
+                    return NO_ERROR;
+                }
+                break;
+            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+                *value = 0;
+                return NO_ERROR;
+            case NATIVE_WINDOW_CONCRETE_TYPE:
+                *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
+                return NO_ERROR;
+            case NATIVE_WINDOW_DEFAULT_WIDTH:
+                *value = mDefaultWidth;
+                return NO_ERROR;
+            case NATIVE_WINDOW_DEFAULT_HEIGHT:
+                *value = mDefaultHeight;
+                return NO_ERROR;
+            case NATIVE_WINDOW_TRANSFORM_HINT:
+                *value = mTransformHint;
+                return NO_ERROR;
         }
-        break;
-    case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-        // TODO: this is not needed anymore
-        *value = 0;
-        return NO_ERROR;
-    case NATIVE_WINDOW_CONCRETE_TYPE:
-        // TODO: this is not needed anymore
-        *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
-        return NO_ERROR;
     }
     return mSurfaceTexture->query(what, value);
 }
@@ -260,6 +287,15 @@
     case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
         res = dispatchSetBuffersFormat(args);
         break;
+    case NATIVE_WINDOW_LOCK:
+        res = dispatchLock(args);
+        break;
+    case NATIVE_WINDOW_UNLOCK_AND_POST:
+        res = dispatchUnlockAndPost(args);
+        break;
+    case NATIVE_WINDOW_SET_SCALING_MODE:
+        res = dispatchSetScalingMode(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -314,6 +350,11 @@
     return setBuffersFormat(f);
 }
 
+int SurfaceTextureClient::dispatchSetScalingMode(va_list args) {
+    int m = va_arg(args, int);
+    return setScalingMode(m);
+}
+
 int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
     int transform = va_arg(args, int);
     return setBuffersTransform(transform);
@@ -324,21 +365,23 @@
     return setBuffersTimestamp(timestamp);
 }
 
+int SurfaceTextureClient::dispatchLock(va_list args) {
+    ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
+    ARect* inOutDirtyBounds = va_arg(args, ARect*);
+    return lock(outBuffer, inOutDirtyBounds);
+}
+
+int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) {
+    return unlockAndPost();
+}
+
+
 int SurfaceTextureClient::connect(int api) {
     LOGV("SurfaceTextureClient::connect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
-    switch (api) {
-        case NATIVE_WINDOW_API_EGL:
-            if (mConnectedApi) {
-                err = -EINVAL;
-            } else {
-                mConnectedApi = api;
-            }
-            break;
-        default:
-            err = -EINVAL;
-            break;
+    int err = mSurfaceTexture->connect(api);
+    if (!err && api == NATIVE_WINDOW_API_CPU) {
+        mConnectedToCpu = true;
     }
     return err;
 }
@@ -346,29 +389,13 @@
 int SurfaceTextureClient::disconnect(int api) {
     LOGV("SurfaceTextureClient::disconnect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
-    switch (api) {
-        case NATIVE_WINDOW_API_EGL:
-            if (mConnectedApi == api) {
-                mConnectedApi = 0;
-            } else {
-                err = -EINVAL;
-            }
-            break;
-        default:
-            err = -EINVAL;
-            break;
+    int err = mSurfaceTexture->disconnect(api);
+    if (!err && api == NATIVE_WINDOW_API_CPU) {
+        mConnectedToCpu = false;
     }
     return err;
 }
 
-int SurfaceTextureClient::getConnectedApi() const
-{
-    Mutex::Autolock lock(mMutex);
-    return mConnectedApi;
-}
-
-
 int SurfaceTextureClient::setUsage(uint32_t reqUsage)
 {
     LOGV("SurfaceTextureClient::setUsage");
@@ -444,6 +471,18 @@
     return NO_ERROR;
 }
 
+int SurfaceTextureClient::setScalingMode(int mode)
+{
+    LOGV("SurfaceTextureClient::setScalingMode(%d)", mode);
+    Mutex::Autolock lock(mMutex);
+    // mode is validated on the server
+    status_t err = mSurfaceTexture->setScalingMode(mode);
+    LOGE_IF(err, "ISurfaceTexture::setScalingMode(%d) returned %s",
+            mode, strerror(-err));
+
+    return err;
+}
+
 int SurfaceTextureClient::setBuffersTransform(int transform)
 {
     LOGV("SurfaceTextureClient::setBuffersTransform");
@@ -466,4 +505,160 @@
     }
 }
 
+// ----------------------------------------------------------------------
+// the lock/unlock APIs must be used from the same thread
+
+static status_t copyBlt(
+        const sp<GraphicBuffer>& dst,
+        const sp<GraphicBuffer>& src,
+        const Region& reg)
+{
+    // src and dst with, height and format must be identical. no verification
+    // is done here.
+    status_t err;
+    uint8_t const * src_bits = NULL;
+    err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
+    LOGE_IF(err, "error locking src buffer %s", strerror(-err));
+
+    uint8_t* dst_bits = NULL;
+    err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
+    LOGE_IF(err, "error locking dst buffer %s", strerror(-err));
+
+    Region::const_iterator head(reg.begin());
+    Region::const_iterator tail(reg.end());
+    if (head != tail && src_bits && dst_bits) {
+        const size_t bpp = bytesPerPixel(src->format);
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+
+        while (head != tail) {
+            const Rect& r(*head++);
+            ssize_t h = r.height();
+            if (h <= 0) continue;
+            size_t size = r.width() * bpp;
+            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+            uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+            if (dbpr==sbpr && size==sbpr) {
+                size *= h;
+                h = 1;
+            }
+            do {
+                memcpy(d, s, size);
+                d += dbpr;
+                s += sbpr;
+            } while (--h > 0);
+        }
+    }
+
+    if (src_bits)
+        src->unlock();
+
+    if (dst_bits)
+        dst->unlock();
+
+    return err;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t SurfaceTextureClient::lock(
+        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
+{
+    if (mLockedBuffer != 0) {
+        LOGE("Surface::lock failed, already locked");
+        return INVALID_OPERATION;
+    }
+
+    if (!mConnectedToCpu) {
+        int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU);
+        if (err) {
+            return err;
+        }
+        // we're intending to do software rendering from this point
+        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+    }
+
+    ANativeWindowBuffer* out;
+    status_t err = dequeueBuffer(&out);
+    LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
+    if (err == NO_ERROR) {
+        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
+        err = lockBuffer(backBuffer.get());
+        LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
+                backBuffer->handle, strerror(-err));
+        if (err == NO_ERROR) {
+            const Rect bounds(backBuffer->width, backBuffer->height);
+
+            Region newDirtyRegion;
+            if (inOutDirtyBounds) {
+                newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
+                newDirtyRegion.andSelf(bounds);
+            } else {
+                newDirtyRegion.set(bounds);
+            }
+
+            // figure out if we can copy the frontbuffer back
+            const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
+            const bool canCopyBack = (frontBuffer != 0 &&
+                    backBuffer->width  == frontBuffer->width &&
+                    backBuffer->height == frontBuffer->height &&
+                    backBuffer->format == frontBuffer->format);
+
+            if (canCopyBack) {
+                // copy the area that is invalid and not repainted this round
+                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+                if (!copyback.isEmpty())
+                    copyBlt(backBuffer, frontBuffer, copyback);
+            } else {
+                // if we can't copy-back anything, modify the user's dirty
+                // region to make sure they redraw the whole buffer
+                newDirtyRegion.set(bounds);
+            }
+
+            // keep track of the are of the buffer that is "clean"
+            // (ie: that will be redrawn)
+            mOldDirtyRegion = newDirtyRegion;
+
+            if (inOutDirtyBounds) {
+                *inOutDirtyBounds = newDirtyRegion.getBounds();
+            }
+
+            void* vaddr;
+            status_t res = backBuffer->lock(
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                    newDirtyRegion.bounds(), &vaddr);
+
+            LOGW_IF(res, "failed locking buffer (handle = %p)",
+                    backBuffer->handle);
+
+            mLockedBuffer = backBuffer;
+            outBuffer->width  = backBuffer->width;
+            outBuffer->height = backBuffer->height;
+            outBuffer->stride = backBuffer->stride;
+            outBuffer->format = backBuffer->format;
+            outBuffer->bits   = vaddr;
+        }
+    }
+    return err;
+}
+
+status_t SurfaceTextureClient::unlockAndPost()
+{
+    if (mLockedBuffer == 0) {
+        LOGE("Surface::unlockAndPost failed, no locked buffer");
+        return INVALID_OPERATION;
+    }
+
+    status_t err = mLockedBuffer->unlock();
+    LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
+
+    err = queueBuffer(mLockedBuffer.get());
+    LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
+            mLockedBuffer->handle, strerror(-err));
+
+    mPostedBuffer = mLockedBuffer;
+    mLockedBuffer = 0;
+    return err;
+}
+
 }; // namespace android
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 519b40e..c1a3c98 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -116,11 +116,6 @@
     EXPECT_EQ(NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, result);
 }
 
-TEST_F(SurfaceTextureClientTest, ANativeWindowLockFails) {
-    ANativeWindow_Buffer buf;
-    ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(mANW.get(), &buf, NULL));
-}
-
 TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     ASSERT_EQ(EGL_SUCCESS, eglGetError());
@@ -613,4 +608,90 @@
     }
 }
 
+class MultiSurfaceTextureClientTest : public ::testing::Test {
+
+public:
+    MultiSurfaceTextureClientTest() :
+            mEglDisplay(EGL_NO_DISPLAY),
+            mEglContext(EGL_NO_CONTEXT) {
+        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
+            mEglSurfaces[i] = EGL_NO_CONTEXT;
+        }
+    }
+
+protected:
+
+    enum { NUM_SURFACE_TEXTURES = 32 };
+
+    virtual void SetUp() {
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+        EGLint majorVersion, minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLConfig myConfig;
+        EGLint numConfigs = 0;
+        EGLint configAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_NONE
+        };
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, configAttribs, &myConfig, 1,
+                &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT,
+                0);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
+            sp<SurfaceTexture> st(new SurfaceTexture(i));
+            sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st));
+            mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig,
+                    static_cast<ANativeWindow*>(stc.get()), NULL);
+            ASSERT_EQ(EGL_SUCCESS, eglGetError());
+            ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]);
+        }
+    }
+
+    virtual void TearDown() {
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                EGL_NO_CONTEXT);
+
+        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
+            if (mEglSurfaces[i] != EGL_NO_SURFACE) {
+                eglDestroySurface(mEglDisplay, mEglSurfaces[i]);
+            }
+        }
+
+        if (mEglContext != EGL_NO_CONTEXT) {
+            eglDestroyContext(mEglDisplay, mEglContext);
+        }
+
+        if (mEglDisplay != EGL_NO_DISPLAY) {
+            eglTerminate(mEglDisplay);
+        }
+    }
+
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurfaces[NUM_SURFACE_TEXTURES];
+    EGLContext mEglContext;
+};
+
+// XXX: This test is disabled because it causes a hang on some devices.  See bug
+// 5015672.
+TEST_F(MultiSurfaceTextureClientTest, DISABLED_MakeCurrentBetweenSurfacesWorks) {
+    for (int iter = 0; iter < 8; iter++) {
+        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
+            eglMakeCurrent(mEglDisplay, mEglSurfaces[i], mEglSurfaces[i],
+                    mEglContext);
+            glClear(GL_COLOR_BUFFER_BIT);
+            eglSwapBuffers(mEglDisplay, mEglSurfaces[i]);
+        }
+    }
+}
+
 } // namespace android
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 88433fb..44babcf 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "SurfaceTexture_test"
 //#define LOG_NDEBUG 0
 
 #include <gtest/gtest.h>
@@ -379,6 +380,13 @@
         ASSERT_NE(-1, mTexMatrixHandle);
     }
 
+    virtual void TearDown() {
+        mANW.clear();
+        mSTC.clear();
+        mST.clear();
+        GLTest::TearDown();
+    }
+
     // drawTexture draws the SurfaceTexture over the entire GL viewport.
     void drawTexture() {
         const GLfloat triangleVertices[] = {
@@ -824,9 +832,7 @@
     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) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) {
     const int texWidth = 64;
     const int texHeight = 66;
 
@@ -863,26 +869,24 @@
     EXPECT_TRUE(checkPixel( 0, 65,  35,  35,  35,  35));
 
     EXPECT_TRUE(checkPixel(15, 10,  35, 231, 231, 231));
-    EXPECT_TRUE(checkPixel(24, 63,  38, 228, 231,  35));
+    EXPECT_TRUE(checkPixel(23, 65, 231,  35, 231,  35));
     EXPECT_TRUE(checkPixel(19, 40,  35, 231,  35,  35));
     EXPECT_TRUE(checkPixel(38, 30, 231,  35,  35,  35));
     EXPECT_TRUE(checkPixel(42, 54,  35,  35,  35, 231));
-    EXPECT_TRUE(checkPixel(37, 33, 228,  38,  38,  38));
+    EXPECT_TRUE(checkPixel(37, 34,  35, 231, 231, 231));
     EXPECT_TRUE(checkPixel(31,  8, 231,  35,  35, 231));
-    EXPECT_TRUE(checkPixel(36, 47, 228,  35, 231, 231));
-    EXPECT_TRUE(checkPixel(24, 63,  38, 228, 231,  35));
-    EXPECT_TRUE(checkPixel(48,  3, 228, 228,  38,  35));
+    EXPECT_TRUE(checkPixel(37, 47, 231,  35, 231, 231));
+    EXPECT_TRUE(checkPixel(25, 38,  35,  35,  35,  35));
+    EXPECT_TRUE(checkPixel(49,  6,  35, 231,  35,  35));
     EXPECT_TRUE(checkPixel(54, 50,  35, 231, 231, 231));
-    EXPECT_TRUE(checkPixel(24, 25,  41,  41, 231, 231));
-    EXPECT_TRUE(checkPixel(10,  9,  38,  38, 231, 231));
+    EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231));
+    EXPECT_TRUE(checkPixel(10,  6,  35,  35, 231, 231));
     EXPECT_TRUE(checkPixel(29,  4,  35,  35,  35, 231));
-    EXPECT_TRUE(checkPixel(56, 31,  38, 228, 231,  35));
+    EXPECT_TRUE(checkPixel(55, 28,  35,  35, 231,  35));
     EXPECT_TRUE(checkPixel(58, 55,  35,  35, 231, 231));
 }
 
-// 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_TexturingFromCpuFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) {
     const int texWidth = 64;
     const int texHeight = 64;
 
@@ -936,9 +940,7 @@
     EXPECT_TRUE(checkPixel( 3, 52,  35, 231,  35,  35));
 }
 
-// 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_TexturingFromGLFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) {
     const int texWidth = 64;
     const int texHeight = 64;
 
@@ -948,7 +950,7 @@
     EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
             mANW.get(), NULL);
     ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+    ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
 
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
             mEglContext));
@@ -972,6 +974,8 @@
 
     eglSwapBuffers(mEglDisplay, stcEglSurface);
 
+    eglDestroySurface(mEglDisplay, stcEglSurface);
+
     // Do the consumer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
             mEglContext));
@@ -1010,6 +1014,83 @@
     EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
 }
 
+TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
+    class ProducerThread : public Thread {
+    public:
+        ProducerThread(const sp<ANativeWindow>& anw):
+                mANW(anw),
+                mDequeueError(NO_ERROR) {
+        }
+
+        virtual ~ProducerThread() {
+        }
+
+        virtual bool threadLoop() {
+            Mutex::Autolock lock(mMutex);
+            ANativeWindowBuffer* anb;
+
+            // Frame 1
+            if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                return false;
+            }
+            if (anb == NULL) {
+                return false;
+            }
+            if (mANW->queueBuffer(mANW.get(), anb)
+                    != NO_ERROR) {
+                return false;
+            }
+
+            // Frame 2
+            if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                return false;
+            }
+            if (anb == NULL) {
+                return false;
+            }
+            if (mANW->queueBuffer(mANW.get(), anb)
+                    != NO_ERROR) {
+                return false;
+            }
+
+            // Frame 3 - error expected
+            mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb);
+            return false;
+        }
+
+        status_t getDequeueError() {
+            Mutex::Autolock lock(mMutex);
+            return mDequeueError;
+        }
+
+    private:
+        sp<ANativeWindow> mANW;
+        status_t mDequeueError;
+        Mutex mMutex;
+    };
+
+    sp<FrameWaiter> fw(new FrameWaiter);
+    mST->setFrameAvailableListener(fw);
+    ASSERT_EQ(OK, mST->setSynchronousMode(true));
+    ASSERT_EQ(OK, mST->setBufferCountServer(2));
+
+    sp<Thread> pt(new ProducerThread(mANW));
+    pt->run();
+
+    fw->waitForFrame();
+    fw->waitForFrame();
+
+    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
+    // block waiting for a buffer to become available.
+    usleep(100000);
+
+    mST->abandon();
+
+    pt->requestExitAndWait();
+    ASSERT_EQ(NO_INIT,
+            reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
+}
+
 /*
  * This test is for testing GL -> GL texture streaming via SurfaceTexture.  It
  * contains functionality to create a producer thread that will perform GL
@@ -1089,13 +1170,21 @@
     // synchronously from SurfaceTexture::queueBuffer.
     class FrameCondition : public SurfaceTexture::FrameAvailableListener {
     public:
+        FrameCondition():
+                mFrameAvailable(false),
+                mFrameFinished(false) {
+        }
+
         // waitForFrame waits for the next frame to arrive.  This should be
         // called from the consumer thread once for every frame expected by the
         // test.
         void waitForFrame() {
-            LOGV("+waitForFrame");
             Mutex::Autolock lock(mMutex);
-            status_t result = mFrameAvailableCondition.wait(mMutex);
+            LOGV("+waitForFrame");
+            while (!mFrameAvailable) {
+                mFrameAvailableCondition.wait(mMutex);
+            }
+            mFrameAvailable = false;
             LOGV("-waitForFrame");
         }
 
@@ -1103,22 +1192,30 @@
         // on to produce the next frame.  This should be called by the consumer
         // thread once for every frame expected by the test.
         void finishFrame() {
-            LOGV("+finishFrame");
             Mutex::Autolock lock(mMutex);
+            LOGV("+finishFrame");
+            mFrameFinished = true;
             mFrameFinishCondition.signal();
             LOGV("-finishFrame");
         }
 
         // This should be called by SurfaceTexture on the producer thread.
         virtual void onFrameAvailable() {
-            LOGV("+onFrameAvailable");
             Mutex::Autolock lock(mMutex);
+            LOGV("+onFrameAvailable");
+            mFrameAvailable = true;
             mFrameAvailableCondition.signal();
-            mFrameFinishCondition.wait(mMutex);
+            while (!mFrameFinished) {
+                mFrameFinishCondition.wait(mMutex);
+            }
+            mFrameFinished = false;
             LOGV("-onFrameAvailable");
         }
 
     protected:
+        bool mFrameAvailable;
+        bool mFrameFinished;
+
         Mutex mMutex;
         Condition mFrameAvailableCondition;
         Condition mFrameFinishCondition;
@@ -1164,6 +1261,7 @@
         }
         mProducerThread.clear();
         mFC.clear();
+        SurfaceTextureGLTest::TearDown();
     }
 
     void runProducerThread(const sp<ProducerThread> producerThread) {
@@ -1180,7 +1278,7 @@
     sp<FrameCondition> mFC;
 };
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1198,7 +1296,7 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1216,7 +1314,7 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1244,7 +1342,7 @@
     }
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1272,4 +1370,70 @@
     }
 }
 
+// XXX: This test is disabled because it is currently hanging on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
+    enum { NUM_ITERATIONS = 64 };
+
+    class PT : public ProducerThread {
+        virtual void render() {
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+                glClear(GL_COLOR_BUFFER_BIT);
+                LOGV("+swapBuffers");
+                swapBuffers();
+                LOGV("-swapBuffers");
+            }
+        }
+    };
+
+    ASSERT_EQ(OK, mST->setSynchronousMode(true));
+    ASSERT_EQ(OK, mST->setBufferCountServer(2));
+
+    runProducerThread(new PT());
+
+    // Allow three frames to be rendered and queued before starting the
+    // rendering in this thread.  For the latter two frames we don't call
+    // updateTexImage so the next dequeue from the producer thread will block
+    // waiting for a frame to become available.
+    mFC->waitForFrame();
+    mFC->finishFrame();
+
+    // We must call updateTexImage to consume the first frame so that the
+    // SurfaceTexture is able to reduce the buffer count to 2.  This is because
+    // the GL driver may dequeue a buffer when the EGLSurface is created, and
+    // that happens before we call setBufferCountServer.  It's possible that the
+    // driver does not dequeue a buffer at EGLSurface creation time, so we
+    // cannot rely on this to cause the second dequeueBuffer call to block.
+    mST->updateTexImage();
+
+    mFC->waitForFrame();
+    mFC->finishFrame();
+    mFC->waitForFrame();
+    mFC->finishFrame();
+
+    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
+    // block waiting for a buffer to become available.
+    usleep(100000);
+
+    // Render and present a number of images.  This thread should not be blocked
+    // by the fact that the producer thread is blocking in dequeue.
+    for (int i = 0; i < NUM_ITERATIONS; i++) {
+        glClear(GL_COLOR_BUFFER_BIT);
+        eglSwapBuffers(mEglDisplay, mEglSurface);
+    }
+
+    // Consume the two pending buffers to unblock the producer thread.
+    mST->updateTexImage();
+    mST->updateTexImage();
+
+    // Consume the remaining buffers from the producer thread.
+    for (int i = 0; i < NUM_ITERATIONS-3; i++) {
+        mFC->waitForFrame();
+        mFC->finishFrame();
+        LOGV("+updateTexImage");
+        mST->updateTexImage();
+        LOGV("-updateTexImage");
+    }
+}
+
 } // namespace android
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 563d7e4..c5858e9 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -33,6 +33,16 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
+// Macros
+///////////////////////////////////////////////////////////////////////////////
+
+#if DEBUG_CACHE_FLUSH
+    #define FLUSH_LOGD(...) LOGD(__VA_ARGS__)
+#else
+    #define FLUSH_LOGD(...)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -73,7 +83,6 @@
     String8 stringLog;
     dumpMemoryUsage(stringLog);
     LOGD("%s", stringLog.string());
-    delete stringLog;
 }
 
 void Caches::dumpMemoryUsage(String8 &log) {
@@ -151,6 +160,32 @@
     mLayerGarbage.push(layer);
 }
 
+void Caches::flush(FlushMode mode) {
+    FLUSH_LOGD("Flushing caches (mode %d)", mode);
+
+    clearGarbage();
+
+    switch (mode) {
+        case kFlushMode_Full:
+            textureCache.clear();
+            patchCache.clear();
+            dropShadowCache.clear();
+            gradientCache.clear();
+            // fall through
+        case kFlushMode_Moderate:
+            pathCache.clear();
+            roundRectShapeCache.clear();
+            circleShapeCache.clear();
+            ovalShapeCache.clear();
+            rectShapeCache.clear();
+            arcShapeCache.clear();
+            // fall through
+        case kFlushMode_Layers:
+            layerCache.clear();
+            break;
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // VBO
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index e64d8ac..cdcbf21 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -100,6 +100,19 @@
     Vector<Layer*> mLayerGarbage;
 
 public:
+    enum FlushMode {
+        kFlushMode_Layers = 0,
+        kFlushMode_Moderate,
+        kFlushMode_Full
+    };
+
+    /**
+     * Flush the cache.
+     *
+     * @param mode Indicates how much of the cache should be flushed
+     */
+    void flush(FlushMode mode);
+
     /**
      * Indicates whether the renderer is in debug mode.
      * This debug mode provides limited information to app developers.
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 2cdc8c3..5db73db 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -26,6 +26,9 @@
 // Turn on to enable memory usage summary on each frame
 #define DEBUG_MEMORY_USAGE 0
 
+// Turn on to enable debugging of cache flushes
+#define DEBUG_CACHE_FLUSH 1
+
 // Turn on to enable layers debugging when rendered as regions
 #define DEBUG_LAYERS_AS_REGIONS 0
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 8b1caeee..88cfc5a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -74,12 +74,17 @@
     if (logBuffer.isEmpty()) {
         return;
     }
-    String8 cachesLog;
-    Caches::getInstance().dumpMemoryUsage(cachesLog);
+
     FILE *file = fdopen(fd, "a");
-    fprintf(file, "\nCaches:\n%s", cachesLog.string());
+
     fprintf(file, "\nRecent DisplayList operations\n");
     logBuffer.outputCommands(file, OP_NAMES);
+
+    String8 cachesLog;
+    Caches::getInstance().dumpMemoryUsage(cachesLog);
+    fprintf(file, "\nCaches:\n%s", cachesLog.string());
+    fprintf(file, "\n");
+
     fflush(file);
 }
 
@@ -143,10 +148,10 @@
         clearResources();
     }
 
-    size_t size = writer.size();
-    void* buffer = sk_malloc_throw(size);
+    mSize = writer.size();
+    void* buffer = sk_malloc_throw(mSize);
     writer.flatten(buffer);
-    mReader.setMemory(buffer, size);
+    mReader.setMemory(buffer, mSize);
 
     Caches& caches = Caches::getInstance();
 
@@ -188,6 +193,11 @@
 }
 
 void DisplayList::init() {
+    mSize = 0;
+}
+
+size_t DisplayList::getSize() {
+    return mSize;
 }
 
 /**
@@ -883,7 +893,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
-    mDisplayList = NULL;
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -923,13 +932,13 @@
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayList* DisplayListRenderer::getDisplayList() {
-    if (mDisplayList == NULL) {
-        mDisplayList = new DisplayList(*this);
+DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
+    if (!displayList) {
+        displayList = new DisplayList(*this);
     } else {
-        mDisplayList->initFromDisplayListRenderer(*this, true);
+        displayList->initFromDisplayListRenderer(*this, true);
     }
-    return mDisplayList;
+    return displayList;
 }
 
 void DisplayListRenderer::setViewport(int width, int height) {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b83259f..69e72a4 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -37,7 +37,7 @@
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
 
-#define MIN_WRITER_SIZE 16384
+#define MIN_WRITER_SIZE 4096
 
 // Debug
 #if DEBUG_DISPLAY_LIST
@@ -105,6 +105,8 @@
 
     void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
 
+    size_t getSize();
+
     bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
 
     void output(OpenGLRenderer& renderer, uint32_t level = 0);
@@ -203,6 +205,8 @@
     Vector<SkiaShader*> mShaders;
 
     mutable SkFlattenableReadBuffer mReader;
+
+    size_t mSize;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -217,7 +221,7 @@
     DisplayListRenderer();
     ~DisplayListRenderer();
 
-    DisplayList* getDisplayList();
+    DisplayList* getDisplayList(DisplayList* displayList);
 
     void setViewport(int width, int height);
     void prepareDirty(float left, float top, float right, float bottom, bool opaque);
@@ -474,8 +478,6 @@
 
     SkWriter32 mWriter;
 
-    DisplayList *mDisplayList;
-
     int mRestoreSaveCount;
 
     friend class DisplayList;
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 4a40a63..996acd5 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -181,11 +181,8 @@
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
 
-    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);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3c2d80d..dd75497 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -51,8 +51,6 @@
         texture.width = layerWidth;
         texture.height = layerHeight;
         colorFilter = NULL;
-        firstFilter = true;
-        firstWrap = true;
     }
 
     ~Layer() {
@@ -150,27 +148,11 @@
     }
 
     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);
-        }
+        texture.setWrap(wrapS, wrapT, bindTexture, force, renderTarget);
     }
 
     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);
-        }
+        texture.setFilter(min, mag,bindTexture, force, renderTarget);
     }
 
     inline bool isCacheable() {
@@ -209,6 +191,10 @@
         if (texture.id) glDeleteTextures(1, &texture.id);
     }
 
+    inline void deleteFbo() {
+        if (fbo) glDeleteFramebuffers(1, &fbo);
+    }
+
     inline void allocateTexture(GLenum format, GLenum storage) {
         glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
     }
@@ -296,8 +282,6 @@
      */
     mat4 texTransform;
 
-    bool firstFilter;
-    bool firstWrap;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 1a15e87..0af0177 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -68,7 +68,9 @@
 
 void LayerCache::deleteLayer(Layer* layer) {
     if (layer) {
+        LAYER_LOGD("Destroying layer %dx%d", layer->getWidth(), layer->getHeight());
         mSize -= layer->getWidth() * layer->getHeight() * 4;
+        layer->deleteFbo();
         layer->deleteTexture();
         delete layer;
     }
@@ -107,21 +109,25 @@
         layer->generateTexture();
         layer->bindTexture();
         layer->setFilter(GL_NEAREST, GL_NEAREST);
-        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
 #if DEBUG_LAYERS
-        size_t size = mCache.size();
-        for (size_t i = 0; i < size; i++) {
-            const LayerEntry& entry = mCache.itemAt(i);
-            LAYER_LOGD("  Layer size %dx%d", entry.mWidth, entry.mHeight);
-        }
+        dump();
 #endif
     }
 
     return layer;
 }
 
+void LayerCache::dump() {
+    size_t size = mCache.size();
+    for (size_t i = 0; i < size; i++) {
+        const LayerEntry& entry = mCache.itemAt(i);
+        LAYER_LOGD("  Layer size %dx%d", entry.mWidth, entry.mHeight);
+    }
+}
+
 bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
     // TODO: We should be smarter and see if we have a texture of the appropriate
     //       size already in the cache, and reuse it instead of creating a new one
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 81b8bf3..a0eae59 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -101,6 +101,11 @@
      */
     uint32_t getSize();
 
+    /**
+     * Prints out the content of the cache.
+     */
+    void dump();
+
 private:
     void deleteLayer(Layer* layer);
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 1fa343b..7e8c7fd 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -167,7 +167,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
-    LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
+    LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
 
     GLuint fbo = Caches::getInstance().fboCache.get();
     if (!fbo) {
@@ -288,16 +288,22 @@
 
 void LayerRenderer::destroyLayer(Layer* layer) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->getFbo());
+        LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
+                layer->getWidth(), layer->getHeight(), layer->getFbo());
 
         if (layer->getFbo()) {
             Caches::getInstance().fboCache.put(layer->getFbo());
         }
 
         if (!Caches::getInstance().layerCache.put(layer)) {
+            LAYER_RENDERER_LOGD("  Destroyed!");
             layer->deleteTexture();
             delete layer;
         } else {
+            LAYER_RENDERER_LOGD("  Cached!");
+#if DEBUG_LAYER_RENDERER
+            Caches::getInstance().layerCache.dump();
+#endif
             layer->region.clear();
         }
     }
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a349121..e67abbd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -125,6 +125,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void OpenGLRenderer::setViewport(int width, int height) {
+    glDisable(GL_DITHER);
     glViewport(0, 0, width, height);
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
@@ -151,7 +152,6 @@
     mSaveCount = 1;
 
     glViewport(0, 0, mWidth, mHeight);
-    glDisable(GL_DITHER);
 
     glEnable(GL_SCISSOR_TEST);
     glScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
@@ -1293,16 +1293,16 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
-
     float x = left;
     float y = top;
 
+    GLenum filter = GL_LINEAR;
     bool ignoreTransform = false;
     if (mSnapshot->transform->isPureTranslate()) {
         x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
         y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
         ignoreTransform = true;
+        filter = GL_NEAREST;
     }
 
     setupDraw();
@@ -1315,7 +1315,11 @@
     setupDrawBlending(true, mode);
     setupDrawProgram();
     setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform);
+
     setupDrawTexture(texture->id);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setFilter(filter, filter);
+
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms();
@@ -1379,7 +1383,9 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+    texture->setFilter(GL_LINEAR, GL_LINEAR, true);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -1462,7 +1468,7 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
 
     const float width = texture->width;
     const float height = texture->height;
@@ -1483,11 +1489,13 @@
         const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
         const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
 
+        texture->setFilter(GL_NEAREST, GL_NEAREST, true);
         drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop),
                 texture->id, alpha / 255.0f, mode, texture->blend,
                 &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                 GL_TRIANGLE_STRIP, gMeshCount, false, true);
     } else {
+        texture->setFilter(GL_LINEAR, GL_LINEAR, true);
         drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
                 mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                 GL_TRIANGLE_STRIP, gMeshCount);
@@ -1507,7 +1515,8 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+    texture->setFilter(GL_LINEAR, GL_LINEAR, true);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -2411,16 +2420,18 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
 
     if (mSnapshot->transform->isPureTranslate()) {
         const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
         const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
 
+        texture->setFilter(GL_NEAREST, GL_NEAREST, true);
         drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
                 alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL,
                 (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true);
     } else {
+        texture->setFilter(GL_LINEAR, GL_LINEAR, true);
         drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
                 texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
                 GL_TRIANGLE_STRIP, gMeshCount);
@@ -2550,22 +2561,5 @@
     return resultMode;
 }
 
-void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
-    bool bound = false;
-    if (wrapS != texture->wrapS) {
-        glBindTexture(GL_TEXTURE_2D, texture->id);
-        bound = true;
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
-        texture->wrapS = wrapS;
-    }
-    if (wrapT != texture->wrapT) {
-        if (!bound) {
-            glBindTexture(GL_TEXTURE_2D, texture->id);
-        }
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
-        texture->wrapT = wrapT;
-    }
-}
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0a3d5090..fa893f0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -464,12 +464,6 @@
     }
 
     /**
-     * Sets the wrap modes for the specified texture. The wrap modes are modified
-     * only when needed.
-     */
-    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT);
-
-    /**
      * Enable or disable blending as necessary. This function sets the appropriate
      * blend function based on the specified xfermode.
      */
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7c10518..923978f 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -43,7 +43,7 @@
     kDebugDisabled = 0,
     kDebugMemory = 1,
     kDebugCaches = 2,
-    kDebugMoreCaches = 3
+    kDebugMoreCaches = kDebugMemory | kDebugCaches
 };
 
 // These properties are defined in mega-bytes
@@ -68,7 +68,7 @@
 #define MB(s) s * 1024 * 1024
 
 #define DEFAULT_TEXTURE_CACHE_SIZE 24.0f
-#define DEFAULT_LAYER_CACHE_SIZE 24.0f
+#define DEFAULT_LAYER_CACHE_SIZE 16.0f
 #define DEFAULT_PATH_CACHE_SIZE 4.0f
 #define DEFAULT_SHAPE_CACHE_SIZE 1.0f
 #define DEFAULT_PATCH_CACHE_SIZE 512
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index f4d9686..33953be 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -624,11 +624,8 @@
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
             GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels());
 
-    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);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8878c70..1a60dca 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -77,14 +77,7 @@
 
 void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    if (wrapS != texture->wrapS) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
-        texture->wrapS = wrapS;
-    }
-    if (wrapT != texture->wrapT) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
-        texture->wrapT = wrapT;
-    }
+    texture->setWrap(wrapS, wrapT);
 }
 
 void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
@@ -151,6 +144,9 @@
 
     // Uniforms
     bindTexture(texture, mWrapS, mWrapT);
+    GLenum filter = textureTransform.isPureTranslate() ? GL_NEAREST : GL_LINEAR;
+    texture->setFilter(filter, filter);
+
     glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
     glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
             GL_FALSE, &textureTransform.data[0]);
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 8f6f860..a3ee63b 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -137,11 +137,8 @@
         glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
                 GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
 
-        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);
+        texture->setFilter(GL_LINEAR, GL_LINEAR);
+        texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 
         if (size < mMaxSize) {
             if (mDebugEnabled) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index c6ae326..48229b6 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -35,16 +35,45 @@
 
         minFilter = GL_NEAREST;
         magFilter = GL_NEAREST;
+
+        firstFilter = true;
+        firstWrap = true;
     }
 
-    void setWrap(GLenum wrapS, GLenum wrapT) {
-        this->wrapS = wrapS;
-        this->wrapT = wrapT;
+    void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false,
+            GLenum renderTarget = GL_TEXTURE_2D) {
+
+        if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) {
+            firstWrap = true;
+
+            this->wrapS = wrapS;
+            this->wrapT = wrapT;
+
+            if (bindTexture) {
+                glBindTexture(renderTarget, id);
+            }
+
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+        }
     }
 
-    void setFilter(GLenum min, GLenum mag) {
-        minFilter = min;
-        magFilter = mag;
+    void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false,
+            GLenum renderTarget = GL_TEXTURE_2D) {
+
+        if (firstFilter || force || min != minFilter || mag != magFilter) {
+            firstFilter = false;
+
+            minFilter = min;
+            magFilter = mag;
+
+            if (bindTexture) {
+                glBindTexture(renderTarget, id);
+            }
+
+            glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+            glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+        }
     }
 
     /**
@@ -87,6 +116,10 @@
      */
     GLenum minFilter;
     GLenum magFilter;
+
+private:
+    bool firstFilter;
+    bool firstWrap;
 }; // struct Texture
 
 class AutoTexture {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 3752874..fbdbf92 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -165,7 +165,7 @@
 
 void TextureCache::clear() {
     mCache.clear();
-    TEXTURE_LOGD("TextureCache:clear(), miSize = %d", mSize);
+    TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize);
 }
 
 void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
@@ -219,11 +219,8 @@
         break;
     }
 
-    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);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index a8aa0c7..58d3e5c 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -128,7 +128,7 @@
 	driver/rsdShaderCache.cpp \
 	driver/rsdVertexArray.cpp
 
-LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
+LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc libbcinfo
 
 LOCAL_STATIC_LIBRARIES := libdex libft2
 
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index bbf2836..0c0aa10 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -19,6 +19,8 @@
 #include "rsdBcc.h"
 #include "rsdRuntime.h"
 
+#include <bcinfo/bcinfo.h>
+
 #include "rsContext.h"
 #include "rsScriptC.h"
 
@@ -38,22 +40,14 @@
 
     BCCScriptRef mBccScript;
 
-    uint32_t mInvokeFunctionCount;
+    struct BCScriptMetadata *mScriptMetadata;
+
     InvokeFunc_t *mInvokeFunctions;
-    uint32_t mFieldCount;
     void ** mFieldAddress;
     bool * mFieldIsObject;
 
     const uint8_t * mScriptText;
     uint32_t mScriptTextLength;
-
-    //uint32_t * mObjectSlots;
-    //uint32_t mObjectSlotCount;
-
-    uint32_t mPragmaCount;
-    const char ** mPragmaKeys;
-    const char ** mPragmaValues;
-
 };
 
 
@@ -77,7 +71,7 @@
 
     pthread_mutex_lock(&rsdgInitMutex);
     char *cachePath = NULL;
-    uint32_t objectSlotCount = 0;
+    struct BCScriptMetadata *md = NULL;
 
     DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
     if (drv == NULL) {
@@ -90,6 +84,14 @@
     drv->mScriptText = bitcode;
     drv->mScriptTextLength = bitcodeSize;
 
+    md = bcinfoGetScriptMetadata((const char*)drv->mScriptText,
+                                 drv->mScriptTextLength, 0);
+    if (!md) {
+      LOGE("bcinfo: failed to read script metadata");
+      goto error;
+    }
+    drv->mScriptMetadata = md;
+
     //LOGE("mBccScript %p", script->mBccScript);
 
     if (bccRegisterSymbolCallback(drv->mBccScript, &rsdLookupRuntimeStub, script) != 0) {
@@ -120,59 +122,42 @@
     drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root"));
     drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init"));
 
-    drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript);
-    if (drv->mInvokeFunctionCount <= 0)
+    if (md->exportFuncCount > 0) {
+        drv->mInvokeFunctions = (InvokeFunc_t*) calloc(md->exportFuncCount,
+                                                       sizeof(InvokeFunc_t));
+        bccGetExportFuncList(drv->mBccScript,
+                             md->exportFuncCount,
+                             (void **) drv->mInvokeFunctions);
+    } else {
         drv->mInvokeFunctions = NULL;
-    else {
-        drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t));
-        bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions);
     }
 
-    drv->mFieldCount = bccGetExportVarCount(drv->mBccScript);
-    if (drv->mFieldCount <= 0) {
+    if (md->exportVarCount > 0) {
+        drv->mFieldAddress = (void **) calloc(md->exportVarCount,
+                                              sizeof(void*));
+        drv->mFieldIsObject = (bool *) calloc(md->exportVarCount, sizeof(bool));
+        bccGetExportVarList(drv->mBccScript,
+                            md->exportVarCount,
+                            (void **) drv->mFieldAddress);
+    } else {
         drv->mFieldAddress = NULL;
         drv->mFieldIsObject = NULL;
-    } else {
-        drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *));
-        drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool));
-        bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress);
     }
 
-    objectSlotCount = bccGetObjectSlotCount(drv->mBccScript);
-    if (objectSlotCount) {
-        uint32_t * slots = new uint32_t[objectSlotCount];
-        bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots);
-        for (uint32_t ct=0; ct < objectSlotCount; ct++) {
-            drv->mFieldIsObject[slots[ct]] = true;
+    if (md->objectSlotCount) {
+        for (uint32_t ct=0; ct < md->objectSlotCount; ct++) {
+            drv->mFieldIsObject[md->objectSlotList[ct]] = true;
         }
-        delete [] slots;
     }
 
-    uint32_t mPragmaCount;
-    const char ** mPragmaKeys;
-    const char ** mPragmaValues;
-
-    drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
-    if (drv->mPragmaCount <= 0) {
-        drv->mPragmaKeys = NULL;
-        drv->mPragmaValues = NULL;
-    } else {
-        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);
-    }
-
-
-
     // Copy info over to runtime
-    script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount;
-    script->mHal.info.exportedVariableCount = drv->mFieldCount;
-    script->mHal.info.exportedPragmaCount = drv->mPragmaCount;
-    script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys;
-    script->mHal.info.exportedPragmaValueList = drv->mPragmaValues;
+    script->mHal.info.exportedFunctionCount = md->exportFuncCount;
+    script->mHal.info.exportedVariableCount = md->exportVarCount;
+    script->mHal.info.exportedPragmaCount = md->pragmaCount;
+    script->mHal.info.exportedPragmaKeyList = md->pragmaKeyList;
+    script->mHal.info.exportedPragmaValueList = md->pragmaValueList;
     script->mHal.info.root = drv->mRoot;
 
-
     pthread_mutex_unlock(&rsdgInitMutex);
     return true;
 
@@ -460,9 +445,10 @@
 
 void rsdScriptDestroy(const Context *dc, Script *script) {
     DrvScript *drv = (DrvScript *)script->mHal.drv;
+    struct BCScriptMetadata *md = drv->mScriptMetadata;
 
     if (drv->mFieldAddress) {
-        for (size_t ct=0; ct < drv->mFieldCount; ct++) {
+        for (size_t ct = 0; ct < md->exportVarCount; ct++) {
             if (drv->mFieldIsObject[ct]) {
                 // The field address can be NULL if the script-side has
                 // optimized the corresponding global variable away.
@@ -471,18 +457,18 @@
                 }
             }
         }
-        delete [] drv->mFieldAddress;
-        delete [] drv->mFieldIsObject;
+        free(drv->mFieldAddress);
         drv->mFieldAddress = NULL;
-        drv->mFieldIsObject = NULL;
-        drv->mFieldCount = 0;
-    }
+        free(drv->mFieldIsObject);
+        drv->mFieldIsObject = NULL;    }
 
     if (drv->mInvokeFunctions) {
-        delete [] drv->mInvokeFunctions;
+        free(drv->mInvokeFunctions);
         drv->mInvokeFunctions = NULL;
-        drv->mInvokeFunctionCount = 0;
     }
+
+    bcinfoReleaseScriptMetadata(&drv->mScriptMetadata);
+
     free(drv);
     script->mHal.drv = NULL;
 
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 2f9f410..d8050ac 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -365,24 +365,49 @@
     return rsrGetAllocation(rsc, sc, ptr);
 }
 
-static void SC_ForEach(Script *target,
-                Allocation *in,
-                Allocation *out,
-                const void *usr,
-                const RsScriptCall *call) {
+static void SC_ForEach_SAA(Script *target,
+                            Allocation *in,
+                            Allocation *out) {
+    GET_TLS();
+    rsrForEach(rsc, sc, target, in, out, NULL, 0, NULL);
+}
+
+static void SC_ForEach_SAAU(Script *target,
+                            Allocation *in,
+                            Allocation *out,
+                            const void *usr) {
     GET_TLS();
     rsrForEach(rsc, sc, target, in, out, usr, 0, NULL);
 }
 
-static void SC_ForEach2(Script *target,
-                 Allocation *in,
-                 Allocation *out,
-                 const void *usr,
-                 const RsScriptCall *call) {
+static void SC_ForEach_SAAUS(Script *target,
+                             Allocation *in,
+                             Allocation *out,
+                             const void *usr,
+                             const RsScriptCall *call) {
     GET_TLS();
     rsrForEach(rsc, sc, target, in, out, usr, 0, call);
 }
 
+static void SC_ForEach_SAAUL(Script *target,
+                             Allocation *in,
+                             Allocation *out,
+                             const void *usr,
+                             uint32_t usrLen) {
+    GET_TLS();
+    rsrForEach(rsc, sc, target, in, out, usr, usrLen, NULL);
+}
+
+static void SC_ForEach_SAAULS(Script *target,
+                              Allocation *in,
+                              Allocation *out,
+                              const void *usr,
+                              uint32_t usrLen,
+                              const RsScriptCall *call) {
+    GET_TLS();
+    rsrForEach(rsc, sc, target, in, out, usr, usrLen, call);
+}
+
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -648,8 +673,11 @@
     { "_Z19rsgClearDepthTargetv", (void *)&SC_ClearFrameBufferObjectDepthTarget, false },
     { "_Z24rsgClearAllRenderTargetsv", (void *)&SC_ClearFrameBufferObjectTargets, false },
 
-    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
-    { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach2, false },
+    { "_Z9rsForEach9rs_script13rs_allocationS0_", (void *)&SC_ForEach_SAA, false },
+    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach_SAAU, false },
+    { "_Z9rsForEach9rs_script13rs_allocationS0_PKvPK16rs_script_call_t", (void *)&SC_ForEach_SAAUS, false },
+    { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach_SAAUL, false },
+    { "_Z9rsForEach9rs_script13rs_allocationS0_PKvjPK16rs_script_call_t", (void *)&SC_ForEach_SAAULS, false },
 
     // time
     { "_Z6rsTimePi", (void *)&SC_Time, true },
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 44e9d89..decd9f1 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -340,10 +340,6 @@
 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) {
     Context * rsc = new Context();
 
-    // Temporary to avoid breaking the tools
-    if (!dev) {
-        return rsc;
-    }
     if (!rsc->initContext(dev, sc)) {
         delete rsc;
         return NULL;
@@ -446,6 +442,7 @@
 
     if (mWidth && mHeight) {
         mStateVertex.updateSize(this);
+        mFBOCache.updateSize();
     }
 }
 
@@ -693,7 +690,9 @@
     LOGV("rsContextCreateGL %p", vdev);
     Device * dev = static_cast<Device *>(vdev);
     Context *rsc = Context::createContext(dev, &sc);
-    rsc->setDPI(dpi);
+    if (rsc) {
+        rsc->setDPI(dpi);
+    }
     LOGV("rsContextCreateGL ret %p ", rsc);
     return rsc;
 }
diff --git a/libs/rs/rsFBOCache.h b/libs/rs/rsFBOCache.h
index f42e1f3..5d58ba4 100644
--- a/libs/rs/rsFBOCache.h
+++ b/libs/rs/rsFBOCache.h
@@ -38,6 +38,7 @@
     void resetAll(Context *);
 
     void setup(Context *);
+    void updateSize() { mDirty = true; }
 
     struct Hal {
         mutable void *drv;
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 70b7278..7023a1f 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -21,14 +21,16 @@
 using namespace android;
 using namespace android::renderscript;
 
-LocklessCommandFifo::LocklessCommandFifo() {
+LocklessCommandFifo::LocklessCommandFifo() : mBuffer(0) {
 }
 
 LocklessCommandFifo::~LocklessCommandFifo() {
     if (!mInShutdown) {
         shutdown();
     }
-    free(mBuffer);
+    if (mBuffer) {
+        free(mBuffer);
+    }
 }
 
 void LocklessCommandFifo::shutdown() {
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index ab164c3..1c8b89c 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -21,8 +21,7 @@
 using namespace android;
 using namespace android::renderscript;
 
-ThreadIO::ThreadIO() {
-    mToCore.init(16 * 1024);
+ThreadIO::ThreadIO() : mUsingSocket(false) {
 }
 
 ThreadIO::~ThreadIO() {
@@ -30,6 +29,7 @@
 
 void ThreadIO::init(bool useSocket) {
     mUsingSocket = useSocket;
+    mToCore.init(16 * 1024);
 
     if (mUsingSocket) {
         mToClientSocket.init();
diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh
index 4768bbe..d939fb3 100644
--- a/libs/rs/scriptc/rs_core.rsh
+++ b/libs/rs/scriptc/rs_core.rsh
@@ -269,6 +269,7 @@
 extern void __attribute__((overloadable))
 rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far);
 
+#if !defined(RS_VERSION) || (RS_VERSION < 14)
 _RS_RUNTIME float4 __attribute__((overloadable))
 rsMatrixMultiply(rs_matrix4x4 *m, float4 in);
 
@@ -286,6 +287,25 @@
 
 _RS_RUNTIME float2 __attribute__((overloadable))
 rsMatrixMultiply(rs_matrix2x2 *m, float2 in);
+#else
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float4 in);
+
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float3 in);
+
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float2 in);
+
+_RS_RUNTIME float3 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix3x3 *m, float3 in);
+
+_RS_RUNTIME float3 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix3x3 *m, float2 in);
+
+_RS_RUNTIME float2 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix2x2 *m, float2 in);
+#endif
 
 // Returns true if the matrix was successfully inversed
 extern bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m);
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index f38f72c..1d36cc6 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -249,15 +249,27 @@
     uint32_t arrayEnd;
 } rs_script_call_t;
 
-extern void __attribute__((overloadable))
-    rsForEach(rs_script script, rs_allocation input,
-              rs_allocation output, const void * usrData);
-
+#if !defined(RS_VERSION) || (RS_VERSION < 14)
 extern void __attribute__((overloadable))
     rsForEach(rs_script script, rs_allocation input,
               rs_allocation output, const void * usrData,
               const rs_script_call_t *);
 
+extern void __attribute__((overloadable))
+    rsForEach(rs_script script, rs_allocation input,
+              rs_allocation output, const void * usrData);
+#else
+extern void __attribute__((overloadable))
+    rsForEach(rs_script script, rs_allocation input, rs_allocation output);
+
+extern void __attribute__((overloadable))
+    rsForEach(rs_script script, rs_allocation input, rs_allocation output,
+              const void * usrData, size_t usrDataLen);
+
+extern void __attribute__((overloadable))
+    rsForEach(rs_script script, rs_allocation input, rs_allocation output,
+              const void * usrData, size_t usrDataLen, const rs_script_call_t *);
+#endif
 
 
 /**
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index 536d1f04..121e013 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -19,6 +19,9 @@
 typedef uint32_t uint;
 typedef uint64_t ulong;
 
+typedef uint32_t size_t;
+typedef int32_t ssize_t;
+
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element;
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type;
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation;
@@ -88,6 +91,8 @@
 
 #define RS_PACKED __attribute__((packed, aligned(4)))
 
+#define NULL ((const void *)0)
+
 typedef enum {
     RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0,
     RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1,
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 9c10c75..0e8ae61 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -289,6 +289,18 @@
         case NATIVE_WINDOW_CONCRETE_TYPE:
             *value = NATIVE_WINDOW_FRAMEBUFFER;
             return NO_ERROR;
+        case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+            *value = 0;
+            return NO_ERROR;
+        case NATIVE_WINDOW_DEFAULT_WIDTH:
+            *value = fb->width;
+            return NO_ERROR;
+        case NATIVE_WINDOW_DEFAULT_HEIGHT:
+            *value = fb->height;
+            return NO_ERROR;
+        case NATIVE_WINDOW_TRANSFORM_HINT:
+            *value = 0;
+            return NO_ERROR;
     }
     *value = 0;
     return BAD_VALUE;
@@ -298,15 +310,25 @@
         int operation, ...)
 {
     switch (operation) {
-        case NATIVE_WINDOW_SET_USAGE:
-        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
         case NATIVE_WINDOW_CONNECT:
         case NATIVE_WINDOW_DISCONNECT:
-            break;
-        default:
-            return NAME_NOT_FOUND;
+        case NATIVE_WINDOW_SET_USAGE:
+        case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+        case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
+        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+        case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+            // TODO: we should implement these
+            return NO_ERROR;
+
+        case NATIVE_WINDOW_LOCK:
+        case NATIVE_WINDOW_UNLOCK_AND_POST:
+        case NATIVE_WINDOW_SET_CROP:
+        case NATIVE_WINDOW_SET_BUFFER_COUNT:
+        case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+        case NATIVE_WINDOW_SET_SCALING_MODE:
+            return INVALID_OPERATION;
     }
-    return NO_ERROR;
+    return NAME_NOT_FOUND;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index c46d6f4..1e602e9 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -83,7 +83,9 @@
         sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
     status_t result;
 
-    int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
+    String8 ashmemName("InputChannel ");
+    ashmemName.append(name);
+    int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
     if (serverAshmemFd < 0) {
         result = -errno;
         LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 693a32a..700b604 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -45,4 +45,4 @@
 )
 
 # Build the manual test programs.
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index f633357..e4eadbd 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -29,7 +29,6 @@
 	Flattenable.cpp \
 	LinearTransform.cpp \
 	ObbFile.cpp \
-	Pool.cpp \
 	PropertyMap.cpp \
 	RefBase.cpp \
 	ResourceTypes.cpp \
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 87549fe..7ef30f9 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -481,6 +481,14 @@
     return sprintf(buf, "%d %s=%s\n", len, key, value);
 }
 
+// Wire format to the backup manager service is chunked:  each chunk is prefixed by
+// a 4-byte count of its size.  A chunk size of zero (four zero bytes) indicates EOD.
+void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t size) {
+    uint32_t chunk_size_no = htonl(size);
+    writer->WriteEntityData(&chunk_size_no, 4);
+    if (size != 0) writer->WriteEntityData(buffer, size);
+}
+
 int write_tarfile(const String8& packageName, const String8& domain,
         const String8& rootpath, const String8& filepath, BackupDataWriter* writer)
 {
@@ -660,16 +668,16 @@
 
         // Checksum and write the pax block header
         calc_tar_checksum(paxHeader);
-        writer->WriteEntityData(paxHeader, 512);
+        send_tarfile_chunk(writer, paxHeader, 512);
 
         // Now write the pax data itself
         int paxblocks = (paxLen + 511) / 512;
-        writer->WriteEntityData(paxData, 512 * paxblocks);
+        send_tarfile_chunk(writer, paxData, 512 * paxblocks);
     }
 
     // Checksum and write the 512-byte ustar file header block to the output
     calc_tar_checksum(buf);
-    writer->WriteEntityData(buf, 512);
+    send_tarfile_chunk(writer, buf, 512);
 
     // Now write the file data itself, for real files.  We honor tar's convention that
     // only full 512-byte blocks are sent to write().
@@ -699,7 +707,7 @@
                 memset(buf + nRead, 0, remainder);
                 nRead += remainder;
             }
-            writer->WriteEntityData(buf, nRead);
+            send_tarfile_chunk(writer, buf, nRead);
             toWrite -= nRead;
         }
     }
diff --git a/libs/utils/Pool.cpp b/libs/utils/Pool.cpp
deleted file mode 100644
index 8f18cb9..0000000
--- a/libs/utils/Pool.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// A simple memory pool.
-//
-#define LOG_TAG "Pool"
-
-//#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-#include <utils/Pool.h>
-
-#include <stdlib.h>
-
-namespace android {
-
-// TODO Provide a real implementation of a pool.  This is just a stub for initial development.
-
-PoolImpl::PoolImpl(size_t objSize) :
-    mObjSize(objSize) {
-}
-
-PoolImpl::~PoolImpl() {
-}
-
-void* PoolImpl::allocImpl() {
-    void* ptr = malloc(mObjSize);
-    LOG_ALWAYS_FATAL_IF(ptr == NULL, "Cannot allocate new pool object.");
-    return ptr;
-}
-
-void PoolImpl::freeImpl(void* obj) {
-    LOG_ALWAYS_FATAL_IF(obj == NULL, "Caller attempted to free NULL pool object.");
-    return free(obj);
-}
-
-} // namespace android
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index cb6c246..6cf01c8 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4346,7 +4346,8 @@
                 | (0x0000ffff & (entryIndex));
             resource_name resName;
             if (!this->getResourceName(resID, &resName)) {
-                return UNKNOWN_ERROR;
+                LOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
+                continue;
             }
 
             const String16 overlayType(resName.type, resName.typeLen);
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 50312e7..d18c0a2 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -161,6 +161,7 @@
     pthread_t thread;
     int result = pthread_create(&thread, &attr,
                     (android_pthread_entry)entryFunction, userData);
+    pthread_attr_destroy(&attr);
     if (result != 0) {
         LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
              "(android threadPriority=%d)",
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 87ae3d5..bfb37a6 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -252,13 +252,15 @@
         "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
 
     void* item = editItemLocation(index);
-    if (item == 0)
-        return NO_MEMORY;
-    _do_destroy(item, 1);
-    if (prototype == 0) {
-        _do_construct(item, 1);
-    } else {
-        _do_copy(item, prototype, 1);
+    if (item != prototype) {
+        if (item == 0)
+            return NO_MEMORY;
+        _do_destroy(item, 1);
+        if (prototype == 0) {
+            _do_construct(item, 1);
+        } else {
+            _do_copy(item, prototype, 1);
+        }
     }
     return ssize_t(index);
 }
@@ -347,9 +349,10 @@
 //    LOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
-    if (where > mCount)
-        where = mCount;
-      
+    LOG_ASSERT(where <= mCount,
+            "[%p] _grow: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
     const size_t new_size = mCount + amount;
     if (capacity() < new_size) {
         const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
@@ -366,10 +369,10 @@
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
             if (sb) {
                 void* array = sb->data();
-                if (where>0) {
+                if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
-                if (mCount>where) {
+                if (where != mCount) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
                     _do_copy(dest, from, mCount-where);
@@ -379,15 +382,14 @@
             }
         }
     } else {
-        ssize_t s = mCount-where;
-        if (s>0) {
-            void* array = editArrayImpl();    
-            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+        if (where != mCount) {
+            void* array = editArrayImpl();
             const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
-            _do_move_forward(to, from, s);
+            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_forward(to, from, mCount - where);
         }
     }
-    mCount += amount;
+    mCount = new_size;
     void* free_space = const_cast<void*>(itemLocation(where));
     return free_space;
 }
@@ -400,14 +402,15 @@
 //    LOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
-    if (where >= mCount)
-        where = mCount - amount;
+    LOG_ASSERT(where + amount <= mCount,
+            "[%p] _shrink: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
 
     const size_t new_size = mCount - amount;
     if (new_size*3 < capacity()) {
         const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
 //        LOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
-        if ((where == mCount-amount) &&
+        if ((where == new_size) &&
             (mFlags & HAS_TRIVIAL_COPY) &&
             (mFlags & HAS_TRIVIAL_DTOR))
         {
@@ -418,31 +421,28 @@
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
             if (sb) {
                 void* array = sb->data();
-                if (where>0) {
+                if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
-                if (mCount > where+amount) {
+                if (where != new_size) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
-                    _do_copy(dest, from, mCount-(where+amount));
+                    _do_copy(dest, from, new_size - where);
                 }
                 release_storage();
                 mStorage = const_cast<void*>(array);
             }
         }
     } else {
-        void* array = editArrayImpl();    
+        void* array = editArrayImpl();
         void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
         _do_destroy(to, amount);
-        ssize_t s = mCount-(where+amount);
-        if (s>0) {
+        if (where != new_size) {
             const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
-            _do_move_backward(to, from, s);
+            _do_move_backward(to, from, new_size - where);
         }
     }
-
-    // adjust the number of items...
-    mCount -= amount;
+    mCount = new_size;
 }
 
 size_t VectorImpl::itemSize() const {
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 8726a53..b97f52f 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -8,7 +8,8 @@
 	ObbFile_test.cpp \
 	Looper_test.cpp \
 	String8_test.cpp \
-	Unicode_test.cpp
+	Unicode_test.cpp \
+	ZipFileRO_test.cpp \
 
 shared_libraries := \
 	libz \
diff --git a/libs/utils/tests/ZipFileRO_test.cpp b/libs/utils/tests/ZipFileRO_test.cpp
new file mode 100644
index 0000000..7a1d0bd
--- /dev/null
+++ b/libs/utils/tests/ZipFileRO_test.cpp
@@ -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.
+ */
+
+#define LOG_TAG "ZipFileRO_test"
+#include <utils/Log.h>
+#include <utils/ZipFileRO.h>
+
+#include <gtest/gtest.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+namespace android {
+
+class ZipFileROTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+};
+
+TEST_F(ZipFileROTest, ZipTimeConvertSuccess) {
+    struct tm t;
+
+    // 2011-06-29 14:40:40
+    long when = 0x3EDD7514;
+
+    ZipFileRO::zipTimeToTimespec(when, &t);
+
+    EXPECT_EQ(2011, t.tm_year + 1900)
+            << "Year was improperly converted.";
+
+    EXPECT_EQ(6, t.tm_mon)
+            << "Month was improperly converted.";
+
+    EXPECT_EQ(29, t.tm_mday)
+            << "Day was improperly converted.";
+
+    EXPECT_EQ(14, t.tm_hour)
+            << "Hour was improperly converted.";
+
+    EXPECT_EQ(40, t.tm_min)
+            << "Minute was improperly converted.";
+
+    EXPECT_EQ(40, t.tm_sec)
+            << "Second was improperly converted.";
+}
+
+}
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 29dec63..0adba06 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -325,7 +325,7 @@
         }
         catch (UnsupportedEncodingException e)
         {
-            Log.e(TAG, e.getMessage());
+            throw new AssertionError();
         }
         return decoded;
     }
@@ -338,7 +338,7 @@
         }
         catch (UnsupportedEncodingException e)
         {
-            Log.e(TAG, e.getMessage());
+            throw new AssertionError();
         }
         return decoded;
     }
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 31e46312..8990fe5 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -54,7 +54,8 @@
     /** Default audio channel mask */
     public static final int CHANNEL_OUT_DEFAULT = 1;
 
-    // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h
+    // Channel mask definitions below are translated to the native values defined in
+    //  in /system/core/include/system/audio.h in the JNI code of AudioTrack
     public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
     public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
     public static final int CHANNEL_OUT_FRONT_CENTER = 0x10;
@@ -64,6 +65,25 @@
     public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100;
     public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200;
     public static final int CHANNEL_OUT_BACK_CENTER = 0x400;
+    /** @hide */
+    public static final int CHANNEL_OUT_SIDE_LEFT =         0x800;
+    /** @hide */
+    public static final int CHANNEL_OUT_SIDE_RIGHT =       0x1000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_CENTER =       0x2000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_FRONT_LEFT =   0x4000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_FRONT_CENTER = 0x8000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_FRONT_RIGHT = 0x10000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_BACK_LEFT =   0x20000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_BACK_CENTER = 0x40000;
+    /** @hide */
+    public static final int CHANNEL_OUT_TOP_BACK_RIGHT =  0x80000;
+
     public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
     public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
     public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
@@ -75,6 +95,12 @@
     public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
             CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
+    /** @hide */
+    public static final int CHANNEL_OUT_7POINT1_SURROUND = (
+            CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
+            CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+            CHANNEL_OUT_LOW_FREQUENCY);
 
     public static final int CHANNEL_IN_DEFAULT = 1;
     public static final int CHANNEL_IN_LEFT = 0x4;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 253010c..7258e11 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -297,6 +297,9 @@
      */
     public static final int RINGER_MODE_NORMAL = 2;
 
+    // maximum valid ringer mode value. Values must start from 0 and be contiguous.
+    private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL;
+
     /**
      * Vibrate type that corresponds to the ringer.
      *
@@ -540,6 +543,21 @@
     }
 
     /**
+     * Checks valid ringer mode values.
+     *
+     * @return true if the ringer mode indicated is valid, false otherwise.
+     *
+     * @see #setRingerMode(int)
+     * @hide
+     */
+    public static boolean isValidRingerMode(int ringerMode) {
+        if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Returns the maximum volume index for a particular stream.
      *
      * @param streamType The stream type whose maximum volume index is returned.
@@ -601,6 +619,9 @@
      * @see #getRingerMode()
      */
     public void setRingerMode(int ringerMode) {
+        if (!isValidRingerMode(ringerMode)) {
+            return;
+        }
         IAudioService service = getService();
         try {
             service.setRingerMode(ringerMode);
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index c567a6e..855e831 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -185,7 +185,10 @@
      * Size of the native audio buffer.
      */
     private int mNativeBufferSizeInBytes = 0;
-
+    /**
+     * Audio session ID
+     */
+    private int mSessionId = 0;
 
     //---------------------------------------------------------
     // Constructor, Finalize
@@ -227,15 +230,20 @@
         audioBuffSizeCheck(bufferSizeInBytes);
 
         // native initialization
+        int[] session = new int[1];
+        session[0] = 0;
         //TODO: update native initialization when information about hardware init failure
         //      due to capture device already open is available.
         int initResult = native_setup( new WeakReference<AudioRecord>(this), 
-                mRecordSource, mSampleRate, mChannels, mAudioFormat, mNativeBufferSizeInBytes);
+                mRecordSource, mSampleRate, mChannels, mAudioFormat, mNativeBufferSizeInBytes,
+                session);
         if (initResult != SUCCESS) {
             loge("Error code "+initResult+" when initializing native AudioRecord object.");
             return; // with mState == STATE_UNINITIALIZED
         }
 
+        mSessionId = session[0];
+
         mState = STATE_INITIALIZED;
     }
 
@@ -485,6 +493,15 @@
         }
     }
 
+    /**
+     * Returns the audio session ID.
+     *
+     * @return the ID of the audio session this AudioRecord belongs to.
+     * @hide
+     */
+    public int getAudioSessionId() {
+        return mSessionId;
+    }
 
     //---------------------------------------------------------
     // Transport control methods
@@ -763,7 +780,8 @@
     //--------------------
 
     private native final int native_setup(Object audiorecord_this, 
-            int recordSource, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes);
+            int recordSource, int sampleRate, int nbChannels, int audioFormat,
+            int buffSizeInBytes, int[] sessionId);
 
     private native final void native_finalize();
     
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0876bbf..682560a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -332,10 +332,10 @@
                 SOUND_EFFECT_DEFAULT_VOLUME_DB);
 
         mVolumePanel = new VolumePanel(context, this);
-        mSettingsObserver = new SettingsObserver();
         mForcedUseForComm = AudioSystem.FORCE_NONE;
         createAudioSystemThread();
         readPersistedSettings();
+        mSettingsObserver = new SettingsObserver();
         createStreamStates();
         // Call setMode() to initialize mSetModeDeathHandlers
         mMode = AudioSystem.MODE_INVALID;
@@ -424,18 +424,29 @@
         final ContentResolver cr = mContentResolver;
 
         mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+        // sanity check in case the settings are restored from a device with incompatible
+        // ringer modes
+        if (!AudioManager.isValidRingerMode(mRingerMode)) {
+            mRingerMode = AudioManager.RINGER_MODE_NORMAL;
+            System.putInt(cr, System.MODE_RINGER, mRingerMode);
+        }
 
         mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0);
 
+        // make sure settings for ringer mode are consistent with device type: non voice capable
+        // devices (tablets) include media stream in silent mode whereas phones don't.
         mRingerModeAffectedStreams = Settings.System.getInt(cr,
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
-                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)|
-                 (1 << AudioSystem.STREAM_MUSIC)));
-
-        if (!mVoiceCapable) {
+                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
+        if (mVoiceCapable) {
+            mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
+        } else {
             mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
         }
+        Settings.System.putInt(cr,
+                Settings.System.MODE_RINGER_STREAMS_AFFECTED, mRingerModeAffectedStreams);
+
         mMuteAffectedStreams = System.getInt(cr,
                 System.MUTE_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
@@ -2166,12 +2177,14 @@
             super.onChange(selfChange);
             synchronized (mSettingsLock) {
                 int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
-                        Settings.System.MODE_RINGER_STREAMS_AFFECTED,
-                        0);
-                if (!mVoiceCapable) {
+                       Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+                       ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
+                       (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
+                if (mVoiceCapable) {
+                    ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
+                } else {
                     ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
                 }
-
                 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
                     /*
                      * Ensure all stream types that should be affected by ringer mode
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index b97c3c4..4f9eb2b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -32,24 +32,25 @@
  * It allows to stream PCM audio buffers to the audio hardware for playback. This is
  * achieved by "pushing" the data to the AudioTrack object using one of the
  *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
- *  
+ *
  * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
  * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
- * one of the write() methods. These are blocking and return when the data has been transferred
- * from the Java layer to the native layer and queued for playback. The streaming mode
- *  is most useful when playing blocks of audio data that for instance are:
+ * one of the {@code write()} methods. These are blocking and return when the data has been
+ * transferred from the Java layer to the native layer and queued for playback. The streaming
+ * mode is most useful when playing blocks of audio data that for instance are:
+ *
  * <ul>
  *   <li>too big to fit in memory because of the duration of the sound to play,</li>
  *   <li>too big to fit in memory because of the characteristics of the audio data
  *         (high sampling rate, bits per sample ...)</li>
  *   <li>received or generated while previously queued audio is playing.</li>
  * </ul>
+ *
  * The static mode is to be chosen when dealing with short sounds that fit in memory and
- * that need to be played with the smallest latency possible. AudioTrack instances in static mode
- * can play the sound without the need to transfer the audio data from Java to native layer
- * each time the sound is to be played. The static mode will therefore be preferred for UI and
- * game sounds that are played often, and with the smallest overhead possible.
- * 
+ * that need to be played with the smallest latency possible. The static mode will
+ * therefore be preferred for UI and game sounds that are played often, and with the
+ * smallest overhead possible.
+ *
  * <p>Upon creation, an AudioTrack object initializes its associated audio buffer.
  * The size of this buffer, specified during the construction, determines how long an AudioTrack
  * can play before running out of data.<br>
@@ -550,7 +551,9 @@
      * @see #PLAYSTATE_PLAYING
      */
     public int getPlayState() {
-        return mPlayState;
+        synchronized (mPlayStateLock) {
+            return mPlayState;
+        }
     }
 
     /**
@@ -816,6 +819,7 @@
     //--------------------
     /**
      * Starts playing an AudioTrack.
+     *
      * @throws IllegalStateException
      */
     public void play()
@@ -832,6 +836,7 @@
 
     /**
      * Stops playing the audio data.
+     *
      * @throws IllegalStateException
      */
     public void stop()
@@ -848,7 +853,10 @@
     }
 
     /**
-     * Pauses the playback of the audio data.
+     * Pauses the playback of the audio data. Data that has not been played
+     * back will not be discarded. Subsequent calls to {@link #play} will play
+     * this data back.
+     *
      * @throws IllegalStateException
      */
     public void pause()
@@ -871,9 +879,9 @@
     //--------------------
 
     /**
-     * Flushes the audio data currently queued for playback.
+     * Flushes the audio data currently queued for playback. Any data that has
+     * not been played back will be discarded.
      */
-
     public void flush() {
         if (mState == STATE_INITIALIZED) {
             // flush the data in native layer
@@ -883,9 +891,14 @@
     }
 
     /**
-     * Writes the audio data to the audio hardware for playback.
+     * Writes the audio data to the audio hardware for playback. Will block until
+     * all data has been written to the audio mixer.
+     * Note that the actual playback of this data might occur after this function
+     * returns. This function is thread safe with respect to {@link #stop} calls,
+     * in which case all of the specified data might not be written to the mixer.
+     *
      * @param audioData the array that holds the data to play.
-     * @param offsetInBytes the offset expressed in bytes in audioData where the data to play 
+     * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
      *    starts.
      * @param sizeInBytes the number of bytes to read in audioData after the offset.
      * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
@@ -914,7 +927,12 @@
 
 
     /**
-     * Writes the audio data to the audio hardware for playback.
+     * Writes the audio data to the audio hardware for playback. Will block until
+     * all data has been written to the audio mixer.
+     * Note that the actual playback of this data might occur after this function
+     * returns. This function is thread safe with respect to {@link #stop} calls,
+     * in which case all of the specified data might not be written to the mixer.
+     *
      * @param audioData the array that holds the data to play.
      * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
      *     starts.
@@ -988,7 +1006,7 @@
 
     /**
      * Sets the send level of the audio track to the attached auxiliary effect
-     * {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0.
+     * {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0.
      * <p>By default the send level is 0, so even if an effect is attached to the player
      * this method must be called for the effect to be applied.
      * <p>Note that the passed level value is a raw scalar. UI controls should be scaled
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 482b437..1bacdbb 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -611,7 +611,7 @@
      * needed.  Not calling this method when playing back a video will
      * result in only the audio track being played.
      *
-     * Either a surface or surface texture must be set if a display or video sink
+     * Either a surface holder or surface 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.
      *
@@ -630,6 +630,27 @@
     }
 
     /**
+     * Sets the {@link Surface} to be used as the sink for the video portion of
+     * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not
+     * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}.
+     * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set.
+     *
+     * @param surface The {@link Surface} to be used for the video portion of the media.
+     *
+     * @hide Pending review by API council.
+     */
+    public void setSurface(Surface surface) {
+        if (mScreenOnWhilePlaying && surface != null && mSurface != null) {
+            Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
+        }
+        mSurfaceHolder = null;
+        mSurface = surface;
+        mParcelSurfaceTexture = null;  // TODO(tedbo): Remove.
+        _setVideoSurfaceOrSurfaceTexture();
+        updateSurfaceScreenOn();
+    }
+
+    /**
      * Sets the {@link SurfaceTexture} to be used as the sink for the
      * video portion of the media. Either a surface or surface texture
      * must be set if a video sink is needed.  The same surface texture
@@ -665,7 +686,7 @@
      * @param pst The {@link ParcelSurfaceTexture} to be used as the sink for
      * the video portion of the media.
      *
-     * @hide Pending review by API council.
+     * @hide Pending removal when there are no more callers.
      */
     public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) {
         if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) {
@@ -1000,8 +1021,8 @@
      */
     public void setScreenOnWhilePlaying(boolean screenOn) {
         if (mScreenOnWhilePlaying != screenOn) {
-            if (screenOn && mParcelSurfaceTexture != null) {
-                Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
+            if (screenOn && mSurfaceHolder == null) {
+                Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
             }
             mScreenOnWhilePlaying = screenOn;
             updateSurfaceScreenOn();
@@ -1312,6 +1333,10 @@
      */
     private static final int KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001;
 
+    // There are currently no defined keys usable from Java with get*Parameter.
+    // But if any keys are defined, the order must be kept in sync with include/media/mediaplayer.h.
+    // private static final int KEY_PARAMETER_... = ...;
+
     /**
      * Sets the parameter indicated by key.
      * @param key key indicates the parameter to be set.
@@ -1331,7 +1356,9 @@
     public boolean setParameter(int key, String value) {
         Parcel p = Parcel.obtain();
         p.writeString(value);
-        return setParameter(key, p);
+        boolean ret = setParameter(key, p);
+        p.recycle();
+        return ret;
     }
 
     /**
@@ -1344,7 +1371,9 @@
     public boolean setParameter(int key, int value) {
         Parcel p = Parcel.obtain();
         p.writeInt(value);
-        return setParameter(key, p);
+        boolean ret = setParameter(key, p);
+        p.recycle();
+        return ret;
     }
 
     /**
@@ -1356,6 +1385,7 @@
 
     /**
      * Gets the value of the parameter indicated by key.
+     * The caller is responsible for recycling the returned parcel.
      * @param key key indicates the parameter to get.
      * @return value of the parameter.
      * {@hide}
@@ -1375,7 +1405,9 @@
     public String getStringParameter(int key) {
         Parcel p = Parcel.obtain();
         getParameter(key, p);
-        return p.readString();
+        String ret = p.readString();
+        p.recycle();
+        return ret;
     }
 
     /**
@@ -1387,7 +1419,9 @@
     public int getIntParameter(int key) {
         Parcel p = Parcel.obtain();
         getParameter(key, p);
-        return p.readInt();
+        int ret = p.readInt();
+        p.recycle();
+        return ret;
     }
 
     /**
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index e3cbd57..8f5d0e5 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -81,9 +81,6 @@
 
     private String mPath;
     private FileDescriptor mFd;
-    private boolean mPrepareAuxiliaryFile = false;
-    private String mPathAux;
-    private FileDescriptor mFdAux;
     private EventHandler mEventHandler;
     private OnErrorListener mOnErrorListener;
     private OnInfoListener mOnInfoListener;
@@ -179,6 +176,8 @@
         public static final int DEFAULT = 0;
         /** Camera video source */
         public static final int CAMERA = 1;
+        /** @hide */
+        public static final int GRALLOC_BUFFER = 2;
     }
 
     /**
@@ -557,84 +556,23 @@
     }
 
     /**
-     * Sets the auxiliary time lapse video's resolution and bitrate.
-     *
-     * The auxiliary video's resolution and bitrate are determined by the CamcorderProfile
-     * quality level {@link android.media.CamcorderProfile#QUALITY_HIGH}.
-     */
-    private void setAuxVideoParameters() {
-        CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
-        setParameter(String.format("video-aux-param-width=%d", profile.videoFrameWidth));
-        setParameter(String.format("video-aux-param-height=%d", profile.videoFrameHeight));
-        setParameter(String.format("video-aux-param-encoding-bitrate=%d", profile.videoBitRate));
-    }
-
-    /**
-     * Pass in the file descriptor for the auxiliary time lapse video. Call this before
-     * prepare().
-     *
-     * Sets file descriptor and parameters for auxiliary time lapse video. Time lapse mode
-     * can capture video (using the still camera) at resolutions higher than that can be
-     * played back on the device. This function or
-     * {@link #setAuxiliaryOutputFile(String)} enable capture of a smaller video in
-     * parallel with the main time lapse video, which can be used to play back on the
-     * device. The smaller video is created by downsampling the main video. This call is
-     * optional and does not have to be called if parallel capture of a downsampled video
-     * is not desired.
-     *
-     * Note that while the main video resolution and bitrate is determined from the
-     * CamcorderProfile in {@link #setProfile(CamcorderProfile)}, the auxiliary video's
-     * resolution and bitrate are determined by the CamcorderProfile quality level
-     * {@link android.media.CamcorderProfile#QUALITY_HIGH}. All other encoding parameters
-     * remain the same for the main video and the auxiliary video.
-     *
-     * E.g. if the device supports the time lapse profile quality level
-     * {@link android.media.CamcorderProfile#QUALITY_TIME_LAPSE_1080P} but can playback at
-     * most 480p, the application might want to capture an auxiliary video of resolution
-     * 480p using this call.
-     *
-     * @param fd an open file descriptor to be written into.
+     * Currently not implemented. It does nothing.
+     * @deprecated Time lapse mode video recording using camera still image capture
+     * is not desirable, and will not be supported.
      */
     public void setAuxiliaryOutputFile(FileDescriptor fd)
     {
-        mPrepareAuxiliaryFile = true;
-        mPathAux = null;
-        mFdAux = fd;
-        setAuxVideoParameters();
+        Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
     }
 
     /**
-     * Pass in the file path for the auxiliary time lapse video. Call this before
-     * prepare().
-     *
-     * Sets file path and parameters for auxiliary time lapse video. Time lapse mode can
-     * capture video (using the still camera) at resolutions higher than that can be
-     * played back on the device. This function or
-     * {@link #setAuxiliaryOutputFile(FileDescriptor)} enable capture of a smaller
-     * video in parallel with the main time lapse video, which can be used to play back on
-     * the device. The smaller video is created by downsampling the main video. This call
-     * is optional and does not have to be called if parallel capture of a downsampled
-     * video is not desired.
-     *
-     * Note that while the main video resolution and bitrate is determined from the
-     * CamcorderProfile in {@link #setProfile(CamcorderProfile)}, the auxiliary video's
-     * resolution and bitrate are determined by the CamcorderProfile quality level
-     * {@link android.media.CamcorderProfile#QUALITY_HIGH}. All other encoding parameters
-     * remain the same for the main video and the auxiliary video.
-     *
-     * E.g. if the device supports the time lapse profile quality level
-     * {@link android.media.CamcorderProfile#QUALITY_TIME_LAPSE_1080P} but can playback at
-     * most 480p, the application might want to capture an auxiliary video of resolution
-     * 480p using this call.
-     *
-     * @param path The pathname to use.
+     * Currently not implemented. It does nothing.
+     * @deprecated Time lapse mode video recording using camera still image capture
+     * is not desirable, and will not be supported.
      */
     public void setAuxiliaryOutputFile(String path)
     {
-        mPrepareAuxiliaryFile = true;
-        mFdAux = null;
-        mPathAux = path;
-        setAuxVideoParameters();
+        Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
     }
 
     /**
@@ -668,8 +606,6 @@
     // native implementation
     private native void _setOutputFile(FileDescriptor fd, long offset, long length)
         throws IllegalStateException, IOException;
-    private native void _setOutputFileAux(FileDescriptor fd)
-        throws IllegalStateException, IOException;
     private native void _prepare() throws IllegalStateException, IOException;
 
     /**
@@ -696,21 +632,6 @@
             throw new IOException("No valid output file");
         }
 
-        if (mPrepareAuxiliaryFile) {
-            if (mPathAux != null) {
-                FileOutputStream fos = new FileOutputStream(mPathAux);
-                try {
-                    _setOutputFileAux(fos.getFD());
-                } finally {
-                    fos.close();
-                }
-            } else if (mFdAux != null) {
-                _setOutputFileAux(mFdAux);
-            } else {
-                throw new IOException("No valid output file");
-            }
-        }
-
         _prepare();
     }
 
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index e8ddd2d..58f9432 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -372,8 +372,14 @@
 
     private class FileInserter {
 
-        ContentValues[] mValues = new ContentValues[1000];
-        int mIndex = 0;
+        private final Uri mUri;
+        private final ContentValues[] mValues;
+        private int mIndex;
+
+        public FileInserter(Uri uri, int count) {
+            mUri = uri;
+            mValues = new ContentValues[count];
+        }
 
         public Uri insert(ContentValues values) {
             if (mIndex == mValues.length) {
@@ -389,13 +395,17 @@
                 mValues[mIndex++] = null;
             }
             try {
-                mMediaProvider.bulkInsert(mFilesUri, mValues);
+                mMediaProvider.bulkInsert(mUri, mValues);
             } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException in FileInserter.flush()", e);
             }
             mIndex = 0;
         }
     }
+
+    private FileInserter mAudioInserter;
+    private FileInserter mVideoInserter;
+    private FileInserter mImageInserter;
     private FileInserter mFileInserter;
 
     // hashes file path to FileCacheEntry.
@@ -835,22 +845,41 @@
                 }
             }
 
+            Uri tableUri = mFilesUri;
+            FileInserter inserter = mFileInserter;
+            if (!mNoMedia) {
+                if (MediaFile.isVideoFileType(mFileType)) {
+                    tableUri = mVideoUri;
+                    inserter = mVideoInserter;
+                } else if (MediaFile.isImageFileType(mFileType)) {
+                    tableUri = mImagesUri;
+                    inserter = mImageInserter;
+                } else if (MediaFile.isAudioFileType(mFileType)) {
+                    tableUri = mAudioUri;
+                    inserter = mAudioInserter;
+                }
+            }
             Uri result = null;
             if (rowId == 0) {
                 if (mMtpObjectHandle != 0) {
                     values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
                 }
-                int format = entry.mFormat;
-                if (format == 0) {
-                    format = MediaFile.getFormatCode(entry.mPath, mMimeType);
+                if (tableUri == mFilesUri) {
+                    int format = entry.mFormat;
+                    if (format == 0) {
+                        format = MediaFile.getFormatCode(entry.mPath, mMimeType);
+                    }
+                    values.put(Files.FileColumns.FORMAT, format);
                 }
-                values.put(Files.FileColumns.FORMAT, format);
-
                 // new file, insert it
-                if (mFileInserter != null) {
-                    result = mFileInserter.insert(values);
+                // We insert directories immediately to ensure they are in the database
+                // before the files they contain.
+                // Otherwise we can get duplicate directory entries in the database
+                // if one of the media FileInserters is flushed before the files table FileInserter
+                if (inserter == null || entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
+                    result = mMediaProvider.insert(tableUri, values);
                 } else {
-                    result = mMediaProvider.insert(mFilesUri, values);
+                    result = inserter.insert(values);
                 }
 
                 if (result != null) {
@@ -859,7 +888,7 @@
                 }
             } else {
                 // updated file
-                result = ContentUris.withAppendedId(mFilesUri, rowId);
+                result = ContentUris.withAppendedId(tableUri, rowId);
                 // path should never change, and we want to avoid replacing mixed cased paths
                 // with squashed lower case paths
                 values.remove(MediaStore.MediaColumns.DATA);
@@ -909,19 +938,19 @@
             if (notifications && !mDefaultNotificationSet) {
                 if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
-                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, mFilesUri, rowId);
+                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
                     mDefaultNotificationSet = true;
                 }
             } else if (ringtones && !mDefaultRingtoneSet) {
                 if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
-                    setSettingIfNotSet(Settings.System.RINGTONE, mFilesUri, rowId);
+                    setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
                     mDefaultRingtoneSet = true;
                 }
             } else if (alarms && !mDefaultAlarmSet) {
                 if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
-                    setSettingIfNotSet(Settings.System.ALARM_ALERT, mFilesUri, rowId);
+                    setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
                     mDefaultAlarmSet = true;
                 }
             }
@@ -1185,12 +1214,25 @@
             initialize(volumeName);
             prescan(null, true);
             long prescan = System.currentTimeMillis();
-            mFileInserter = new FileInserter();
+
+            // create FileInserters for bulk inserts
+            mAudioInserter = new FileInserter(mAudioUri, 500);
+            mVideoInserter = new FileInserter(mVideoUri, 500);
+            mImageInserter = new FileInserter(mImagesUri, 500);
+            mFileInserter = new FileInserter(mFilesUri, 500);
 
             for (int i = 0; i < directories.length; i++) {
                 processDirectory(directories[i], mClient);
             }
+
+            // flush remaining inserts
+            mAudioInserter.flush();
+            mVideoInserter.flush();
+            mImageInserter.flush();
             mFileInserter.flush();
+            mAudioInserter = null;
+            mVideoInserter = null;
+            mImageInserter = null;
             mFileInserter = null;
 
             long scan = System.currentTimeMillis();
diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java
new file mode 100644
index 0000000..7197dd2
--- /dev/null
+++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java
@@ -0,0 +1,67 @@
+/*
+ * 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.media.audiofx;
+
+/**
+ * Acoustic Echo Canceler (AEC).
+ * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the
+ * signal received from the remote party from the captured audio signal.
+ * <p>AEC is used by voice communication applications (voice chat, video conferencing, SIP calls)
+ * where the presence of echo with significant delay in the signal received from the remote party
+ * is highly disturbing. AEC is often used in conjunction with noise suppression (NS).
+ * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC
+ * engine in the audio capture path.
+ * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AEC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AcousticEchoCanceler extends AudioEffect {
+
+    private final static String TAG = "AcousticEchoCanceler";
+
+    /**
+     * Class constructor.
+     * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the
+     * constructor is not guarantied to succeed:
+     * <ul>
+     *  <li>IllegalArgumentException is thrown if the device does not implement an AEC</li>
+     *  <li>UnsupportedOperationException is thrown is the resources allocated to audio
+     *  pre-procesing are currently exceeded.</li>
+     * </ul>
+     *
+     * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler
+     * will be applied to the AudioRecord with the same audio session.
+     *
+     * @throws java.lang.IllegalArgumentException
+     * @throws java.lang.UnsupportedOperationException
+     * @throws java.lang.RuntimeException
+     */
+    public AcousticEchoCanceler(int audioSession)
+            throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+        super(EFFECT_TYPE_AEC, EFFECT_TYPE_NULL, 0, audioSession);
+    }
+}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 39c6d3e..3ac0104 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -66,6 +66,8 @@
 
     private final static String TAG = "AudioEffect-JAVA";
 
+    // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h
+
     /**
      * The following UUIDs define effect types corresponding to standard audio
      * effects whose implementation and interface conform to the OpenSL ES
@@ -105,6 +107,27 @@
             .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
 
     /**
+     * UUID for Automatic Gain Control (AGC) audio pre-processing
+     * @hide
+     */
+    public static final UUID EFFECT_TYPE_AGC = UUID
+            .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
+
+    /**
+     * UUID for Acoustic Echo Canceler (AEC) audio pre-processing
+     * @hide
+     */
+    public static final UUID EFFECT_TYPE_AEC = UUID
+            .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
+
+    /**
+     * UUID for Noise Suppressor (NS) audio pre-processing
+     * @hide
+     */
+    public static final UUID EFFECT_TYPE_NS = UUID
+            .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
+
+    /**
      * Null effect UUID. Used when the UUID for effect type of
      * @hide
      */
@@ -180,7 +203,8 @@
      * <ul>
      *  <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
      *  <li>uuid: UUID for this particular implementation</li>
-     *  <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
+     *  <li>connectMode: {@link #EFFECT_INSERT}, {@link #EFFECT_AUXILIARY} or
+     *  {at_link #EFFECT_PRE_PROCESSING}</li>
      *  <li>name: human readable effect name</li>
      *  <li>implementor: human readable effect implementor name</li>
      * </ul>
@@ -212,11 +236,13 @@
          */
         public UUID uuid;
         /**
-         *  Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
-         *  category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied
+         *  Indicates if the effect is of insert category {@link #EFFECT_INSERT}, auxiliary
+         *  category {@link #EFFECT_AUXILIARY} or pre processing category
+         *  {at_link #EFFECT_PRE_PROCESSING}. Insert effects (Typically an Equalizer) are applied
          *  to the entire audio source and usually not shared by several sources. Auxiliary effects
          *  (typically a reverberator) are applied to part of the signal (wet) and the effect output
          *  is added to the original signal (dry).
+         *  Audio pre processing are applied to audio captured on a particular AudioRecord.
          */
         public String connectMode;
         /**
@@ -243,6 +269,12 @@
      * attaching it to the MediaPlayer or AudioTrack.
      */
     public static final String EFFECT_AUXILIARY = "Auxiliary";
+    /**
+     * Effect connection mode is pre processing.
+     * The audio pre processing effects are attached to an audio input (AudioRecord).
+     * @hide
+     */
+    public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
 
     // --------------------------------------------------------------------------
     // Member variables
@@ -410,6 +442,19 @@
         return (Descriptor[]) native_query_effects();
     }
 
+    /**
+     * Query all audio pre processing effects applied to the AudioRecord with the supplied
+     * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
+     * objects.
+     * @param audioSession system wide unique audio session identifier.
+     * @throws IllegalStateException
+     * @hide
+     */
+
+    static public Descriptor[] queryPreProcessings(int audioSession) {
+        return (Descriptor[]) native_query_pre_processing(audioSession);
+    }
+
     // --------------------------------------------------------------------------
     // Control methods
     // --------------------
@@ -1155,6 +1200,8 @@
 
     private static native Object[] native_query_effects();
 
+    private static native Object[] native_query_pre_processing(int audioSession);
+
     // ---------------------------------------------------------
     // Utility methods
     // ------------------
diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java
new file mode 100644
index 0000000..44574f0
--- /dev/null
+++ b/media/java/android/media/audiofx/AutomaticGainControl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.media.audiofx;
+
+/**
+ * Automatic Gain Control (AGC).
+ * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the
+ * output of the captured signal by boosting or lowering input from the microphone to match a preset
+ * level so that that the output signal level is virtually constant.
+ * AGC can be used by applications where the input signal dynamic range is not important but where
+ * a constant strong capture level is desired.
+ * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC
+ * engine in the audio framework.
+ * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AGC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AutomaticGainControl extends AudioEffect {
+
+    private final static String TAG = "AutomaticGainControl";
+
+    /**
+     * Class constructor.
+     * <p> The application must catch exceptions when creating an AutomaticGainControl as the
+     * constructor is not guarantied to succeed:
+     * <ul>
+     *  <li>IllegalArgumentException is thrown if the device does not implement an AGC</li>
+     *  <li>UnsupportedOperationException is thrown is the resources allocated to audio
+     *  pre-procesing are currently exceeded.</li>
+     * </ul>
+     *
+     * @param audioSession system wide unique audio session identifier. The AutomaticGainControl
+     * will be applied to the AudioRecord with the same audio session.
+     *
+     * @throws java.lang.IllegalArgumentException
+     * @throws java.lang.UnsupportedOperationException
+     * @throws java.lang.RuntimeException
+     */
+    public AutomaticGainControl(int audioSession)
+            throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+        super(EFFECT_TYPE_AGC, EFFECT_TYPE_NULL, 0, audioSession);
+    }
+}
diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java
new file mode 100644
index 0000000..4e7a8b6
--- /dev/null
+++ b/media/java/android/media/audiofx/NoiseSuppressor.java
@@ -0,0 +1,68 @@
+/*
+ * 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.media.audiofx;
+
+/**
+ * Noise Suppressor (NS).
+ * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the
+ * captured signal. The component of the signal considered as noise can be either stationary
+ * (car/airplane engine, AC system) or non-stationary (other peoples conversations, car horn) for
+ * more advanced implementations.
+ * <p>NS is mostly used by voice communication applications (voice chat, video conferencing,
+ * SIP calls).
+ * <p>An application creates a NoiseSuppressor object to instantiate and control an NS
+ * engine in the audio framework.
+ * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, NS can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class NoiseSuppressor extends AudioEffect {
+
+    private final static String TAG = "NoiseSuppressor";
+
+    /**
+     * Class constructor.
+     * <p> The application must catch exceptions when creating an NoiseSuppressor as the
+     * constructor is not guarantied to succeed:
+     * <ul>
+     *  <li>IllegalArgumentException is thrown if the device does not implement an NS</li>
+     *  <li>UnsupportedOperationException is thrown is the resources allocated to audio
+     *  pre-procesing are currently exceeded.</li>
+     * </ul>
+     *
+     * @param audioSession system wide unique audio session identifier. The NoiseSuppressor
+     * will be applied to the AudioRecord with the same audio session.
+     *
+     * @throws java.lang.IllegalArgumentException
+     * @throws java.lang.UnsupportedOperationException
+     * @throws java.lang.RuntimeException
+     */
+    public NoiseSuppressor(int audioSession)
+            throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+        super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession);
+    }
+}
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 0d2bcd5..6b0fb12 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -912,11 +912,14 @@
         /** 720p 1280 X 720 */
         public static final int V720p = 10;
 
-        /** 1080 x 720 */
+        /** W720p 1080 x 720 */
         public static final int W720p = 11;
 
-        /** 1080 960 x 720 */
+        /** S720p 960 x 720 */
         public static final int S720p = 12;
+
+        /** 1080p 1920 x 1080 */
+        public static final int V1080p = 13;
     }
 
     /**
@@ -3548,6 +3551,8 @@
                     retValue = VideoFrameSize.WVGA16x9;
                 else if (height == MediaProperties.HEIGHT_720)
                     retValue = VideoFrameSize.V720p;
+                else if (height == MediaProperties.HEIGHT_1080)
+                    retValue = VideoFrameSize.V1080p;
                 break;
             case MediaProperties.ASPECT_RATIO_4_3:
                 if (height == MediaProperties.HEIGHT_480)
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 4faa83a..73cc7e2 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -503,7 +503,60 @@
 
         return adjustedOverlays;
     }
+    /**
+     * This function get the proper width by given aspect ratio
+     * and height.
+     *
+     * @param aspectRatio  Given aspect ratio
+     * @param height  Given height
+     */
+    private int getWidthByAspectRatioAndHeight(int aspectRatio, int height) {
+        int width = 0;
 
+        switch (aspectRatio) {
+            case MediaProperties.ASPECT_RATIO_3_2:
+                if (height == MediaProperties.HEIGHT_480)
+                    width = 720;
+                else if (height == MediaProperties.HEIGHT_720)
+                    width = 1080;
+                break;
+
+            case MediaProperties.ASPECT_RATIO_16_9:
+                if (height == MediaProperties.HEIGHT_360)
+                    width = 640;
+                else if (height == MediaProperties.HEIGHT_480)
+                    width = 854;
+                else if (height == MediaProperties.HEIGHT_720)
+                    width = 1280;
+                else if (height == MediaProperties.HEIGHT_1080)
+                    width = 1920;
+                break;
+
+            case MediaProperties.ASPECT_RATIO_4_3:
+                if (height == MediaProperties.HEIGHT_480)
+                    width = 640;
+                if (height == MediaProperties.HEIGHT_720)
+                    width = 960;
+                break;
+
+            case MediaProperties.ASPECT_RATIO_5_3:
+                if (height == MediaProperties.HEIGHT_480)
+                    width = 800;
+                break;
+
+            case MediaProperties.ASPECT_RATIO_11_9:
+                if (height == MediaProperties.HEIGHT_144)
+                    width = 176;
+                break;
+
+            default : {
+                throw new IllegalArgumentException(
+                    "Illegal arguments for aspectRatio");
+            }
+        }
+
+        return width;
+    }
 
     /**
      * This function sets the Ken Burn effect generated clip
@@ -515,39 +568,10 @@
     void setGeneratedImageClip(String generatedFilePath) {
         super.setGeneratedImageClip(generatedFilePath);
 
-
         // set the Kenburns clip width and height
         mGeneratedClipHeight = getScaledHeight();
-        switch (mVideoEditor.getAspectRatio()) {
-            case MediaProperties.ASPECT_RATIO_3_2:
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                    mGeneratedClipWidth = 720;
-                else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                    mGeneratedClipWidth = 1080;
-                break;
-            case MediaProperties.ASPECT_RATIO_16_9:
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_360)
-                    mGeneratedClipWidth = 640;
-                else if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                    mGeneratedClipWidth = 854;
-                else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                    mGeneratedClipWidth = 1280;
-                break;
-            case MediaProperties.ASPECT_RATIO_4_3:
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                    mGeneratedClipWidth = 640;
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                    mGeneratedClipWidth = 960;
-                break;
-            case MediaProperties.ASPECT_RATIO_5_3:
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                    mGeneratedClipWidth = 800;
-                break;
-            case MediaProperties.ASPECT_RATIO_11_9:
-                if (mGeneratedClipHeight == MediaProperties.HEIGHT_144)
-                    mGeneratedClipWidth = 176;
-                break;
-        }
+        mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
+                mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
     }
 
     /**
@@ -841,37 +865,8 @@
             clipSettings.fileType = FileType.THREE_GPP;
 
             mGeneratedClipHeight = getScaledHeight();
-            switch (mVideoEditor.getAspectRatio()) {
-                case MediaProperties.ASPECT_RATIO_3_2:
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                        mGeneratedClipWidth = 720;
-                    else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                        mGeneratedClipWidth = 1080;
-                    break;
-                case MediaProperties.ASPECT_RATIO_16_9:
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_360)
-                        mGeneratedClipWidth = 640;
-                    else if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                        mGeneratedClipWidth = 854;
-                    else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                        mGeneratedClipWidth = 1280;
-                    break;
-                case MediaProperties.ASPECT_RATIO_4_3:
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                        mGeneratedClipWidth = 640;
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_720)
-                        mGeneratedClipWidth = 960;
-                    break;
-                case MediaProperties.ASPECT_RATIO_5_3:
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_480)
-                        mGeneratedClipWidth = 800;
-                    break;
-                case MediaProperties.ASPECT_RATIO_11_9:
-                    if (mGeneratedClipHeight == MediaProperties.HEIGHT_144)
-                        mGeneratedClipWidth = 176;
-                    break;
-            }
-
+            mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
+                    mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
         } else {
             if (getGeneratedImageClip() == null) {
                 clipSettings.clipPath = getDecodedImageFileName();
diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java
index 0225807..ff13e5d 100755
--- a/media/java/android/media/videoeditor/MediaProperties.java
+++ b/media/java/android/media/videoeditor/MediaProperties.java
@@ -17,8 +17,9 @@
 
 package android.media.videoeditor;
 
+import android.media.videoeditor.VideoEditorProfile;
 import android.util.Pair;
-
+import java.lang.System;
 /**
  * This class defines all properties of a media file such as supported height,
  * aspect ratio, bitrate for export function.
@@ -33,7 +34,7 @@
     public static final int HEIGHT_360 = 360;
     public static final int HEIGHT_480 = 480;
     public static final int HEIGHT_720 = 720;
-    public static final int HEIGHT_1088 = 1088;
+    public static final int HEIGHT_1080 = 1080;
 
     /**
      *  Supported aspect ratios
@@ -63,8 +64,7 @@
     private static final Pair<Integer, Integer>[] ASPECT_RATIO_3_2_RESOLUTIONS =
         new Pair[] {
         new Pair<Integer, Integer>(720, HEIGHT_480),
-//*tmpLSA*/        new Pair<Integer, Integer>(1080, HEIGHT_720)
-/*tmpLSA*/        new Pair<Integer, Integer>(1088, HEIGHT_720)
+        new Pair<Integer, Integer>(1080, HEIGHT_720)
     };
 
     @SuppressWarnings({"unchecked"})
@@ -92,6 +92,7 @@
         new Pair[] {
         new Pair<Integer, Integer>(848, HEIGHT_480),
         new Pair<Integer, Integer>(1280, HEIGHT_720),
+        new Pair<Integer, Integer>(1920, HEIGHT_1080),
     };
 
     /**
@@ -345,7 +346,31 @@
             }
         }
 
-        return resolutions;
+        /** Check the platform specific maximum export resolution */
+        VideoEditorProfile veProfile = VideoEditorProfile.get();
+        if (veProfile == null) {
+            throw new RuntimeException("Can't get the video editor profile");
+        }
+        final int maxWidth = veProfile.maxOutputVideoFrameWidth;
+        final int maxHeight = veProfile.maxOutputVideoFrameHeight;
+        Pair<Integer, Integer>[] tmpResolutions = new Pair[resolutions.length];
+        int numSupportedResolution = 0;
+        int i = 0;
+
+        /** Get supported resolution list */
+        for (i = 0; i < resolutions.length; i++) {
+            if ((resolutions[i].first <= maxWidth) &&
+                (resolutions[i].second <= maxHeight)) {
+                tmpResolutions[numSupportedResolution] = resolutions[i];
+                numSupportedResolution++;
+            }
+        }
+        final Pair<Integer, Integer>[] supportedResolutions =
+            new Pair[numSupportedResolution];
+        System.arraycopy(tmpResolutions, 0,
+            supportedResolutions, 0, numSupportedResolution);
+
+        return supportedResolutions;
     }
 
     /**
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 4758de6..6248651 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -23,6 +23,7 @@
 import android.graphics.Bitmap;
 import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
 import android.media.videoeditor.MediaArtistNativeHelper.Properties;
+import android.media.videoeditor.VideoEditorProfile;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 
@@ -118,6 +119,21 @@
             throw new IllegalArgumentException(e.getMessage() + " : " + filename);
         }
 
+        /** Check the platform specific maximum import resolution */
+        VideoEditorProfile veProfile = VideoEditorProfile.get();
+        if (veProfile == null) {
+            throw new RuntimeException("Can't get the video editor profile");
+        }
+        final int maxInputWidth = veProfile.maxInputVideoFrameWidth;
+        final int maxInputHeight = veProfile.maxInputVideoFrameHeight;
+        if ((properties.width > maxInputWidth) ||
+            (properties.height > maxInputHeight)) {
+            throw new IllegalArgumentException(
+                "Unsupported import resolution. Supported maximum width:" +
+                maxInputWidth + " height:" + maxInputHeight +
+                ", current width:" + properties.width +
+                " height:" + properties.height);
+        }
         switch (mMANativeHelper.getFileType(properties.fileType)) {
             case MediaProperties.FILE_3GP:
             case MediaProperties.FILE_MP4:
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
index 59e4540..720e8022 100755
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ b/media/java/android/media/videoeditor/VideoEditor.java
@@ -370,7 +370,7 @@
      */
     public void export(String filename, int height, int bitrate,
                        ExportProgressListener listener)
-    throws IOException;
+                       throws IOException;
 
     /**
      * Create the output movie based on all media items added and the applied
@@ -413,7 +413,7 @@
      */
     public void export(String filename, int height, int bitrate, int audioCodec,
                        int videoCodec, ExportProgressListener listener)
-                           throws IOException;
+                       throws IOException;
 
     /**
      * Cancel the running export operation. This method blocks until the export
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 649b98a..ea7fe63 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -337,7 +337,8 @@
      */
     public void export(String filename, int height, int bitrate,
                        int audioCodec, int videoCodec,
-                       ExportProgressListener listener) throws IOException {
+                       ExportProgressListener listener)
+                       throws IOException {
 
         switch (audioCodec) {
             case MediaProperties.ACODEC_AAC_LC:
@@ -372,7 +373,8 @@
      * {@inheritDoc}
      */
     public void export(String filename, int height, int bitrate,
-                       ExportProgressListener listener) throws IOException {
+                       ExportProgressListener listener)
+                       throws IOException {
         if (filename == null) {
             throw new IllegalArgumentException("export: filename is null");
         }
@@ -386,6 +388,20 @@
             throw new IllegalStateException("No MediaItems added");
         }
 
+        /** Check the platform specific maximum export resolution */
+        VideoEditorProfile veProfile = VideoEditorProfile.get();
+        if (veProfile == null) {
+            throw new RuntimeException("Can't get the video editor profile");
+        }
+        final int maxOutputHeight = veProfile.maxOutputVideoFrameHeight;
+        final int maxOutputWidth = veProfile.maxOutputVideoFrameWidth;
+        if (height > maxOutputHeight) {
+            throw new IllegalArgumentException(
+                    "Unsupported export resolution. Supported maximum width:" +
+                    maxOutputWidth + " height:" + maxOutputHeight +
+                    " current height:" + height);
+        }
+
         switch (height) {
             case MediaProperties.HEIGHT_144:
                 break;
@@ -397,6 +413,8 @@
                 break;
             case MediaProperties.HEIGHT_720:
                 break;
+            case MediaProperties.HEIGHT_1080:
+                break;
 
             default: {
                 String message = "Unsupported height value " + height;
diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java
new file mode 100755
index 0000000..7d9fc8f
--- /dev/null
+++ b/media/java/android/media/videoeditor/VideoEditorProfile.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.videoeditor;
+
+/**
+ * The VideoEditorProfile class is used to retrieve the
+ * predefined videoeditor profile settings for videoeditor applications.
+ * These settings are read-only.
+ *
+ * <p>The videoeditor profile specifies the following set of parameters:
+ * <ul>
+ * <li> max input video frame width
+ * <li> max input video frame height
+ * <li> max output video frame width
+ * <li> max output video frame height
+ * </ul>
+ * {@hide}
+ */
+public class VideoEditorProfile
+{
+    /**
+     * The max input video frame width
+     */
+    public int maxInputVideoFrameWidth;
+
+    /**
+     * The max input video frame height
+     */
+    public int maxInputVideoFrameHeight;
+
+    /**
+     * The max ouput video frame width
+     */
+    public int maxOutputVideoFrameWidth;
+
+    /**
+     * The max ouput video frame height
+     */
+    public int maxOutputVideoFrameHeight;
+
+    /**
+     * Returns the videoeditor profile
+     */
+    public static VideoEditorProfile get() {
+        return native_get_videoeditor_profile();
+    }
+
+    static {
+        System.loadLibrary("media_jni");
+        native_init();
+    }
+
+    // Private constructor called by JNI
+    private VideoEditorProfile(int inputWidth,
+                             int inputHeight,
+                             int outputWidth,
+                             int outputHeight) {
+
+        this.maxInputVideoFrameWidth = inputWidth;
+        this.maxInputVideoFrameHeight = inputHeight;
+        this.maxOutputVideoFrameWidth = outputWidth;
+        this.maxOutputVideoFrameHeight = outputHeight;
+    }
+
+    // Methods implemented by JNI
+    private static native final void native_init();
+    private static native final VideoEditorProfile
+	    native_get_videoeditor_profile();
+}
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index 08a6de1..2b8dfe4 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -286,6 +286,44 @@
     }
     return static_cast<jint>(levels[index]);
 }
+static jobject
+android_media_MediaProfiles_native_get_videoeditor_profile(JNIEnv *env, jobject thiz)
+{
+    LOGV("native_get_videoeditor_profile");
+
+    int maxInputFrameWidth =
+            sProfiles->getVideoEditorCapParamByName("videoeditor.input.width.max");
+    int maxInputFrameHeight =
+            sProfiles->getVideoEditorCapParamByName("videoeditor.input.height.max");
+    int maxOutputFrameWidth =
+            sProfiles->getVideoEditorCapParamByName("videoeditor.output.width.max");
+    int maxOutputFrameHeight =
+            sProfiles->getVideoEditorCapParamByName("videoeditor.output.height.max");
+
+    // Check on the values retrieved
+    if (maxInputFrameWidth == -1 || maxInputFrameHeight == -1 ||
+        maxOutputFrameWidth == -1 || maxOutputFrameHeight == -1) {
+
+        jniThrowException(env, "java/lang/RuntimeException",\
+            "Error retrieving videoeditor profile params");
+        return NULL;
+    }
+    LOGV("native_get_videoeditor_profile \
+        inWidth:%d inHeight:%d,outWidth:%d, outHeight:%d",\
+        maxInputFrameWidth,maxInputFrameHeight,\
+        maxOutputFrameWidth,maxOutputFrameHeight);
+
+    jclass VideoEditorProfileClazz =
+        env->FindClass("android/media/videoeditor/VideoEditorProfile");
+    jmethodID VideoEditorProfileConstructorMethodID =
+        env->GetMethodID(VideoEditorProfileClazz, "<init>", "(IIII)V");
+    return env->NewObject(VideoEditorProfileClazz,
+                          VideoEditorProfileConstructorMethodID,
+                          maxInputFrameWidth,
+                          maxInputFrameHeight,
+                          maxOutputFrameWidth,
+                          maxOutputFrameHeight);
+}
 
 static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
     {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
@@ -324,10 +362,17 @@
     {"native_get_image_encoding_quality_level","(II)I",                   (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
 };
 
+static JNINativeMethod gMethodsForVideoEditorProfileClass[] = {
+    {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
+    {"native_get_videoeditor_profile",           "()Landroid/media/videoeditor/VideoEditorProfile;",
+                                                                         (void *)android_media_MediaProfiles_native_get_videoeditor_profile},
+};
+
 static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities";
 static const char* const kDecoderCapabilitiesClassPathName = "android/media/DecoderCapabilities";
 static const char* const kCamcorderProfileClassPathName = "android/media/CamcorderProfile";
 static const char* const kCameraProfileClassPathName = "android/media/CameraProfile";
+static const char* const kVideoEditorProfileClassPathName = "android/media/videoeditor/VideoEditorProfile";
 
 // This function only registers the native methods, and is called from
 // JNI_OnLoad in android_media_MediaPlayer.cpp
@@ -353,6 +398,11 @@
                gMethodsForCameraProfileClass,
                NELEM(gMethodsForCameraProfileClass));
 
+    int ret5 = AndroidRuntime::registerNativeMethods(env,
+               kVideoEditorProfileClassPathName,
+               gMethodsForVideoEditorProfileClass,
+               NELEM(gMethodsForVideoEditorProfileClass));
+
     // Success if all return values from above are 0
-    return (ret1 || ret2 || ret3 || ret4);
+    return (ret1 || ret2 || ret3 || ret4 || ret5);
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 12391c8..e1d3219 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -261,20 +261,6 @@
 }
 
 static void
-android_media_MediaRecorder_setOutputFileAuxFD(JNIEnv *env, jobject thiz, jobject fileDescriptor)
-{
-    LOGV("setOutputFile");
-    if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
-    status_t opStatus = mr->setOutputFileAuxiliary(fd);
-    process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
-}
-
-static void
 android_media_MediaRecorder_setVideoSize(JNIEnv *env, jobject thiz, jint width, jint height)
 {
     LOGV("setVideoSize(%d, %d)", width, height);
@@ -475,7 +461,6 @@
     {"setAudioEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setAudioEncoder},
     {"setParameter",         "(Ljava/lang/String;)V",           (void *)android_media_MediaRecorder_setParameter},
     {"_setOutputFile",       "(Ljava/io/FileDescriptor;JJ)V",   (void *)android_media_MediaRecorder_setOutputFileFD},
-    {"_setOutputFileAux",    "(Ljava/io/FileDescriptor;)V",     (void *)android_media_MediaRecorder_setOutputFileAuxFD},
     {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
     {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
     {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index d0d2d1e..b88296f 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -46,6 +46,16 @@
 };
 static fields_t fields;
 
+static status_t checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        LOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+        return UNKNOWN_ERROR;
+    }
+    return OK;
+}
+
 class MyMediaScannerClient : public MediaScannerClient
 {
 public:
@@ -86,9 +96,7 @@
         mEnv->DeleteGlobalRef(mClient);
     }
 
-    // Returns true if it succeeded, false if an exception occured
-    // in the Java code
-    virtual bool scanFile(const char* path, long long lastModified,
+    virtual status_t scanFile(const char* path, long long lastModified,
             long long fileSize, bool isDirectory, bool noMedia)
     {
         LOGV("scanFile: path(%s), time(%lld), size(%lld) and isDir(%d)",
@@ -96,27 +104,29 @@
 
         jstring pathStr;
         if ((pathStr = mEnv->NewStringUTF(path)) == NULL) {
-            return false;
+            mEnv->ExceptionClear();
+            return NO_MEMORY;
         }
 
         mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified,
                 fileSize, isDirectory, noMedia);
 
         mEnv->DeleteLocalRef(pathStr);
-        return (!mEnv->ExceptionCheck());
+        return checkAndClearExceptionFromCallback(mEnv, "scanFile");
     }
 
-    // Returns true if it succeeded, false if an exception occured
-    // in the Java code
-    virtual bool handleStringTag(const char* name, const char* value)
+    virtual status_t handleStringTag(const char* name, const char* value)
     {
         LOGV("handleStringTag: name(%s) and value(%s)", name, value);
         jstring nameStr, valueStr;
         if ((nameStr = mEnv->NewStringUTF(name)) == NULL) {
-            return false;
+            mEnv->ExceptionClear();
+            return NO_MEMORY;
         }
         if ((valueStr = mEnv->NewStringUTF(value)) == NULL) {
-            return false;
+            mEnv->DeleteLocalRef(nameStr);
+            mEnv->ExceptionClear();
+            return NO_MEMORY;
         }
 
         mEnv->CallVoidMethod(
@@ -124,23 +134,22 @@
 
         mEnv->DeleteLocalRef(nameStr);
         mEnv->DeleteLocalRef(valueStr);
-        return (!mEnv->ExceptionCheck());
+        return checkAndClearExceptionFromCallback(mEnv, "handleStringTag");
     }
 
-    // Returns true if it succeeded, false if an exception occured
-    // in the Java code
-    virtual bool setMimeType(const char* mimeType)
+    virtual status_t setMimeType(const char* mimeType)
     {
         LOGV("setMimeType: %s", mimeType);
         jstring mimeTypeStr;
         if ((mimeTypeStr = mEnv->NewStringUTF(mimeType)) == NULL) {
-            return false;
+            mEnv->ExceptionClear();
+            return NO_MEMORY;
         }
 
         mEnv->CallVoidMethod(mClient, mSetMimeTypeMethodID, mimeTypeStr);
 
         mEnv->DeleteLocalRef(mimeTypeStr);
-        return (!mEnv->ExceptionCheck());
+        return checkAndClearExceptionFromCallback(mEnv, "setMimeType");
     }
 
 private:
@@ -152,12 +161,6 @@
 };
 
 
-static bool ExceptionCheck(void* env)
-{
-    LOGV("ExceptionCheck");
-    return ((JNIEnv *)env)->ExceptionCheck();
-}
-
 static MediaScanner *getNativeScanner_l(JNIEnv* env, jobject thiz)
 {
     return (MediaScanner *) env->GetIntField(thiz, fields.context);
@@ -190,7 +193,10 @@
     }
 
     MyMediaScannerClient myClient(env, client);
-    mp->processDirectory(pathStr, myClient, ExceptionCheck, env);
+    MediaScanResult result = mp->processDirectory(pathStr, myClient);
+    if (result == MEDIA_SCAN_RESULT_ERROR) {
+        LOGE("An error occurred while scanning directory '%s'.", pathStr);
+    }
     env->ReleaseStringUTFChars(path, pathStr);
 }
 
@@ -227,7 +233,10 @@
     }
 
     MyMediaScannerClient myClient(env, client);
-    mp->processFile(pathStr, mimeTypeStr, myClient);
+    MediaScanResult result = mp->processFile(pathStr, mimeTypeStr, myClient);
+    if (result == MEDIA_SCAN_RESULT_ERROR) {
+        LOGE("An error occurred while scanning file '%s'.", pathStr);
+    }
     env->ReleaseStringUTFChars(path, pathStr);
     if (mimeType) {
         env->ReleaseStringUTFChars(mimeType, mimeTypeStr);
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 0f3c063..4dbcb90 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -79,7 +79,6 @@
     return (MtpDatabase *)env->GetIntField(database, field_context);
 }
 
-#ifdef HAVE_ANDROID_OS
 // ----------------------------------------------------------------------------
 
 class MyMtpDatabase : public MtpDatabase {
@@ -1066,42 +1065,32 @@
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
-#endif // HAVE_ANDROID_OS
-
 // ----------------------------------------------------------------------------
 
 static void
 android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
 {
-#ifdef HAVE_ANDROID_OS
     MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
     env->SetIntField(thiz, field_context, (int)database);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
 }
 
 static void
 android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
 {
-#ifdef HAVE_ANDROID_OS
     MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
     database->cleanup(env);
     delete database;
     env->SetIntField(thiz, field_context, 0);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
 }
 
 static jstring
 android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
 {
-#ifdef HAVE_ANDROID_OS
     char    date[20];
     formatDateTime(seconds, date, sizeof(date));
     return env->NewStringUTF(date);
-#else
-    return NULL;
-#endif
 }
 
 // ----------------------------------------------------------------------------
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 40bbaa3..6b73f6c 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -85,8 +85,6 @@
 static jfieldID field_objectInfo_dateModified;
 static jfieldID field_objectInfo_keywords;
 
-#ifdef HAVE_ANDROID_OS
-
 MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
 {
     return (MtpDevice*)env->GetIntField(javaDevice, field_context);
@@ -100,15 +98,11 @@
     }
 }
 
-#endif // HAVE_ANDROID_OS
-
 // ----------------------------------------------------------------------------
 
 static jboolean
 android_mtp_MtpDevice_open(JNIEnv *env, jobject thiz, jstring deviceName, jint fd)
 {
-#ifdef HAVE_ANDROID_OS
-    LOGD("open\n");
     const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
     if (deviceNameStr == NULL) {
         return false;
@@ -120,27 +114,22 @@
     if (device)
         env->SetIntField(thiz, field_context, (int)device);
     return (device != NULL);
-#endif
 }
 
 static void
 android_mtp_MtpDevice_close(JNIEnv *env, jobject thiz)
 {
-#ifdef HAVE_ANDROID_OS
-    LOGD("close\n");
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device) {
         device->close();
         delete device;
         env->SetIntField(thiz, field_context, 0);
     }
-#endif
 }
 
 static jobject
 android_mtp_MtpDevice_get_device_info(JNIEnv *env, jobject thiz)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device) {
         LOGD("android_mtp_MtpDevice_get_device_info device is null");
@@ -173,15 +162,11 @@
 
     delete deviceInfo;
     return info;
-#else
-    return NULL;
-#endif
 }
 
 static jintArray
 android_mtp_MtpDevice_get_storage_ids(JNIEnv *env, jobject thiz)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -196,15 +181,11 @@
 
     delete storageIDs;
     return array;
-#else
-    return NULL;
-#endif
 }
 
 static jobject
 android_mtp_MtpDevice_get_storage_info(JNIEnv *env, jobject thiz, jint storageID)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -234,16 +215,12 @@
 
     delete storageInfo;
     return info;
-#else
-    return NULL;
-#endif
 }
 
 static jintArray
 android_mtp_MtpDevice_get_object_handles(JNIEnv *env, jobject thiz,
         jint storageID, jint format, jint objectID)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -258,15 +235,11 @@
 
     delete handles;
     return array;
-#else
-    return NULL;
-#endif
 }
 
 static jobject
 android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -324,9 +297,6 @@
 
     delete objectInfo;
     return info;
-#else
-    return NULL;
-#endif
 }
 
 struct get_object_callback_data {
@@ -344,7 +314,6 @@
 static jbyteArray
 android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint objectSize)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -361,14 +330,12 @@
 
     if (device->readObject(objectID, get_object_callback, objectSize, &data))
         return array;
-#endif
     return NULL;
 }
 
 static jbyteArray
 android_mtp_MtpDevice_get_thumbnail(JNIEnv *env, jobject thiz, jint objectID)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return NULL;
@@ -382,51 +349,41 @@
 
     free(thumbnail);
     return array;
-#else
-    return NULL;
-#endif
 }
 
 static jboolean
 android_mtp_MtpDevice_delete_object(JNIEnv *env, jobject thiz, jint object_id)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
         return device->deleteObject(object_id);
     else
- #endif
         return NULL;
 }
 
 static jlong
 android_mtp_MtpDevice_get_parent(JNIEnv *env, jobject thiz, jint object_id)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
         return device->getParent(object_id);
     else
-#endif
         return -1;
 }
 
 static jlong
 android_mtp_MtpDevice_get_storage_id(JNIEnv *env, jobject thiz, jint object_id)
 {
- #ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
         return device->getStorageID(object_id);
     else
-#endif
         return -1;
 }
 
 static jboolean
 android_mtp_MtpDevice_import_file(JNIEnv *env, jobject thiz, jint object_id, jstring dest_path)
 {
-#ifdef HAVE_ANDROID_OS
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device) {
         const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
@@ -438,7 +395,7 @@
         env->ReleaseStringUTFChars(dest_path, destPathStr);
         return result;
     }
-#endif
+
     return false;
 }
 
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index e71e727..57cabe2 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -725,18 +725,22 @@
             goto queryEffects_failure;
         }
 
+        if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            jdescConnect = env->NewStringUTF("Auxiliary");
+        } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT) {
+            jdescConnect = env->NewStringUTF("Insert");
+        } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+            jdescConnect = env->NewStringUTF("Pre Processing");
+        } else {
+            continue;
+        }
+
         AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
         jdescType = env->NewStringUTF(str);
 
         AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
         jdescUuid = env->NewStringUTF(str);
 
-        if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
-            jdescConnect = env->NewStringUTF("Auxiliary");
-        } else {
-            jdescConnect = env->NewStringUTF("Insert");
-        }
-
         jdescName = env->NewStringUTF(desc.name);
         jdescImplementor = env->NewStringUTF(desc.implementor);
 
@@ -771,6 +775,87 @@
 
 }
 
+
+
+static jobjectArray
+android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz, jint audioSession)
+{
+    // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
+    // most devices to get all active audio pre processing on a given session.
+    static const uint32_t kDefaultNumEffects = 5;
+
+    effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects];
+    uint32_t numEffects = kDefaultNumEffects;
+
+    status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
+                                           descriptors,
+                                           &numEffects);
+    if ((status != NO_ERROR && status != NO_MEMORY) ||
+            numEffects == 0) {
+        delete[] descriptors;
+        return NULL;
+    }
+    if (status == NO_MEMORY) {
+        delete [] descriptors;
+        descriptors = new effect_descriptor_t[numEffects];
+        status = AudioEffect::queryDefaultPreProcessing(audioSession,
+                                               descriptors,
+                                               &numEffects);
+    }
+    if (status != NO_ERROR || numEffects == 0) {
+        delete[] descriptors;
+        return NULL;
+    }
+    LOGV("queryDefaultPreProcessing() got %d effects", numEffects);
+
+    jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
+    if (ret == NULL) {
+        delete[] descriptors;
+        return ret;
+    }
+
+    char str[EFFECT_STRING_LEN_MAX];
+    jstring jdescType;
+    jstring jdescUuid;
+    jstring jdescConnect;
+    jstring jdescName;
+    jstring jdescImplementor;
+    jobject jdesc;
+
+    for (uint32_t i = 0; i < numEffects; i++) {
+
+        AudioEffect::guidToString(&descriptors[i].type, str, EFFECT_STRING_LEN_MAX);
+        jdescType = env->NewStringUTF(str);
+        AudioEffect::guidToString(&descriptors[i].uuid, str, EFFECT_STRING_LEN_MAX);
+        jdescUuid = env->NewStringUTF(str);
+        jdescConnect = env->NewStringUTF("Pre Processing");
+        jdescName = env->NewStringUTF(descriptors[i].name);
+        jdescImplementor = env->NewStringUTF(descriptors[i].implementor);
+
+        jdesc = env->NewObject(fields.clazzDesc,
+                               fields.midDescCstor,
+                               jdescType,
+                               jdescUuid,
+                               jdescConnect,
+                               jdescName,
+                               jdescImplementor);
+        env->DeleteLocalRef(jdescType);
+        env->DeleteLocalRef(jdescUuid);
+        env->DeleteLocalRef(jdescConnect);
+        env->DeleteLocalRef(jdescName);
+        env->DeleteLocalRef(jdescImplementor);
+        if (jdesc == NULL) {
+            LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
+            env->DeleteLocalRef(ret);
+            return NULL;;
+        }
+
+        env->SetObjectArrayElement(ret, i, jdesc);
+   }
+
+   return ret;
+}
+
 // ----------------------------------------------------------------------------
 
 // Dalvik VM type signatures
@@ -787,6 +872,8 @@
     {"native_getParameter",  "(I[BI[B)I",  (void *)android_media_AudioEffect_native_getParameter},
     {"native_command",       "(II[BI[B)I", (void *)android_media_AudioEffect_native_command},
     {"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects},
+    {"native_query_pre_processing", "(I)[Ljava/lang/Object;",
+            (void *)android_media_AudioEffect_native_queryPreProcessings},
 };
 
 
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 69cfe8c..1af78e31 100755
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -42,11 +42,13 @@
     $(TOP)/frameworks/media/libvideoeditor/vss/common/inc \
     $(TOP)/frameworks/media/libvideoeditor/vss/mcs/inc \
     $(TOP)/frameworks/media/libvideoeditor/vss/stagefrightshells/inc \
+    $(TOP)/frameworks/media/libvideoeditor/include \
     $(TOP)/frameworks/media/libvideoeditor/lvpp \
     $(TOP)/frameworks/media/libvideoeditor/osal/inc
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
+    libdl \
     libutils \
     libandroid_runtime \
     libnativehelper \
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 277e16c..4c0e7315 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -439,9 +439,10 @@
     VIDEOEDIT_JAVA_CONSTANT_INIT("NTSC", M4VIDEOEDITING_kNTSC),
     VIDEOEDIT_JAVA_CONSTANT_INIT("nHD", M4VIDEOEDITING_k640_360),
     VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA16x9", M4VIDEOEDITING_k854_480),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_kHD1280),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_kHD1080),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_kHD960)
+    VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_k1280_720),
+    VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_k1080_720),
+    VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_k960_720),
+    VIDEOEDIT_JAVA_CONSTANT_INIT("V1080p", M4VIDEOEDITING_k1920_1080)
 };
 
 VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameSize, VIDEO_FRAME_SIZE_CLASS_NAME,
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
index 13f6350..ec8050f 100755
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ b/media/jni/mediaeditor/VideoEditorJava.cpp
@@ -25,11 +25,13 @@
 
 
 void
-videoEditJava_checkAndThrowIllegalArgumentException(
+videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
                 bool*                               pResult,
                 JNIEnv*                             pEnv,
                 bool                                condition,
-                const char*                         pMessage)
+                const char*                         pMessage,
+                const char*                         pFile,
+                int                                 lineNo)
 {
     // Check if the previous action succeeded.
     if (*pResult)
@@ -39,7 +41,8 @@
         {
             // Log the exception.
             VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",\
-                    "videoEditJava_checkAndThrowIllegalArgumentException, %s", pMessage);
+                    "videoEditJava_checkAndThrowIllegalArgumentException, %s (%s:%d)",
+                    pMessage, pFile, lineNo);
 
             // Reset the result flag.
             (*pResult) = false;
@@ -51,11 +54,14 @@
 }
 
 void
-videoEditJava_checkAndThrowRuntimeException(
+videoEditJava_checkAndThrowRuntimeExceptionFunc(
                 bool*                               pResult,
                 JNIEnv*                             pEnv,
                 bool                                condition,
-                M4OSA_ERR                           result)
+                M4OSA_ERR                           result,
+                const char*                         pFile,
+                int                                 lineNo
+                )
 {
     const char* pMessage = NULL;
 
@@ -70,7 +76,8 @@
 
             // Log the exception.
             VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_checkAndThrowRuntimeException, %s", pMessage);
+                    "videoEditJava_checkAndThrowRuntimeException, %s (%s:%d)",
+                    pMessage, pFile, lineNo);
 
             // Reset the result flag.
             (*pResult) = false;
@@ -82,11 +89,14 @@
 }
 
 void
-videoEditJava_checkAndThrowIllegalStateException(
+videoEditJava_checkAndThrowIllegalStateExceptionFunc(
                 bool*                               pResult,
                 JNIEnv*                             pEnv,
                 bool                                condition,
-                const char*                         pMessage)
+                const char*                         pMessage,
+                const char*                         pFile,
+                int                                 lineNo
+                )
 {
     // Check if the previous action succeeded.
     if (*pResult)
@@ -96,7 +106,8 @@
         {
             // Log the exception.
             VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_checkAndThrowIllegalStateException, %s", pMessage);
+                    "videoEditJava_checkAndThrowIllegalStateException, %s (%s:%d)",
+                    pMessage, pFile, lineNo);
 
             // Reset the result flag.
             (*pResult) = false;
diff --git a/media/jni/mediaeditor/VideoEditorJava.h b/media/jni/mediaeditor/VideoEditorJava.h
index 9d7f096..0a2db08 100755
--- a/media/jni/mediaeditor/VideoEditorJava.h
+++ b/media/jni/mediaeditor/VideoEditorJava.h
@@ -351,26 +351,47 @@
     jmethodID methodIds[];
 } VideoEditJava_MethodIds;
 
-void
-videoEditJava_checkAndThrowIllegalArgumentException(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                const char*                         pMessage);
+#define videoEditJava_checkAndThrowIllegalArgumentException(\
+    a, b, c, d) videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(\
+    a, b, c, d, __FILE__, __LINE__)
+
+#define videoEditJava_checkAndThrowRuntimeException(\
+    a, b, c, d) videoEditJava_checkAndThrowRuntimeExceptionFunc(\
+    a, b, c, d, __FILE__, __LINE__)
+
+#define videoEditJava_checkAndThrowIllegalStateException(\
+    a, b, c, d) videoEditJava_checkAndThrowIllegalStateExceptionFunc(\
+    a, b, c, d, __FILE__, __LINE__)
 
 void
-videoEditJava_checkAndThrowRuntimeException(
+videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
                 bool*                               pResult,
                 JNIEnv*                             pEnv,
                 bool                                condition,
-                M4OSA_ERR                           result);
+                const char*                         pMessage,
+                const char*                         pFile,
+                int                                 lineNo
+                );
 
 void
-videoEditJava_checkAndThrowIllegalStateException(
+videoEditJava_checkAndThrowRuntimeExceptionFunc(
                 bool*                               pResult,
                 JNIEnv*                             pEnv,
                 bool                                condition,
-                const char*                         pMessage);
+                M4OSA_ERR                           result,
+                const char*                         pFile,
+                int                                 lineNo
+                );
+
+void
+videoEditJava_checkAndThrowIllegalStateExceptionFunc(
+                bool*                               pResult,
+                JNIEnv*                             pEnv,
+                bool                                condition,
+                const char*                         pMessage,
+                const char*                         pFile,
+                int                                 lineNo
+                );
 
 void
 videoEditJava_getClass(
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 9de7207..93fe702 100755
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -214,18 +214,6 @@
                             "Invalid File or File not found ");
                 }
 
-                /**
-                 * Max resolution supported is 1280 x 720.
-                 */
-                if ( (pClipProperties->uiVideoWidth > 1280)
-                    || (pClipProperties->uiVideoHeight > 720) )
-                {
-                    result = M4MCS_ERR_INVALID_INPUT_VIDEO_FRAME_SIZE;
-                    videoEditJava_checkAndThrowIllegalArgumentException(
-                            &gotten, pEnv, (M4NO_ERROR != result),
-                            "Unsupported input video frame size");
-                }
-
 #ifdef USE_SOFTWARE_DECODER
                 /**
                  * Input clip with non-multiples of 16 is not supported.
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
index e6a7b37..b8fa487 100644
--- a/media/libeffects/data/audio_effects.conf
+++ b/media/libeffects/data/audio_effects.conf
@@ -1,5 +1,10 @@
 # List of effect libraries to load. Each library element must contain a "path" element
 # giving the full path of the library .so file.
+#    libraries {
+#        <lib name> {
+#          path <lib path>
+#        }
+#    }
 libraries {
   bundle {
     path /system/lib/soundfx/libbundlewrapper.so
@@ -10,6 +15,9 @@
   visualizer {
     path /system/lib/soundfx/libvisualizer.so
   }
+  pre_processing {
+    path /system/lib/soundfx/libaudiopreprocessing.so
+  }
 }
 
 # list of effects to load. Each effect element must contain a "library" and a "uuid" element.
@@ -17,6 +25,16 @@
 # "libraries" element.
 # The name of the effect element is indicative, only the value of the "uuid" element
 # designates the effect.
+# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the
+# generic effect type UUID.
+#    effects {
+#        <fx name> {
+#            library <lib name>
+#            uuid <effect uuid>
+#        }
+#        ...
+#    }
+
 effects {
   bassboost {
     library bundle
@@ -54,4 +72,55 @@
     library visualizer
     uuid d069d9e0-8329-11df-9168-0002a5d5c51b
   }
+  agc {
+    library pre_processing
+    uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b
+  }
+  aec {
+    library pre_processing
+    uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b
+  }
+  ns {
+    library pre_processing
+    uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+  }
 }
+# Audio preprocessor configurations.
+# The pre processor configuration consists in a list of elements each describing
+# pre processor settings for a given input source. Valid input source names are:
+# "mic", "camcorder", "voice_recognition", "voice_communication"
+# Each input source element contains a list of effects elements. The name of the effect
+# element must be the name of one of the effects in the "effects" list of the file.
+# Each effect element may optionally contain a list of parameters and their
+# default value to apply when the pre processor effect is created.
+# A parameter is defined by a "param" element and a "value" element. Each of these elements
+# consists in one or more elements specifying a type followed by a value.
+# The types defined are: "int", "short", "float", "bool" and "string"
+# When both "param" and "value" are a single int, a simple form is allowed where just
+# the param and value pair is present in the parameter description
+#    pre_processing {
+#        <input source name> {
+#            <fx name> {
+#                <param 1 name> {
+#                    param {
+#                        int|short|float|bool|string <value>
+#                        [ int|short|float|bool|string <value> ]
+#                        ...
+#                    }
+#                    value {
+#                        int|short|float|bool|string <value>
+#                        [ int|short|float|bool|string <value> ]
+#                        ...
+#                    }
+#                }
+#                <param 2 name > {<param> <value>}
+#                ...
+#            }
+#            ...
+#        }
+#        ...
+#    }
+
+#
+# TODO: add default audio pre processor configurations after debug and tuning phase
+#
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 26265ae..2f2b974 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -14,4 +14,7 @@
 
 LOCAL_SHARED_LIBRARIES += libdl
 
+LOCAL_C_INCLUDES := \
+    system/media/audio_effects/include
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index a9689bc..d333510 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -24,6 +24,7 @@
 
 #include <cutils/misc.h>
 #include <cutils/config_utils.h>
+#include <audio_effects/audio_effects_conf.h>
 
 static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
 static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index fcc0dba..c1d4319 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -26,13 +26,6 @@
 extern "C" {
 #endif
 
-#define AUDIO_EFFECT_DEFAULT_CONFIG_FILE "/system/etc/audio_effects.conf"
-#define AUDIO_EFFECT_VENDOR_CONFIG_FILE "/vendor/etc/audio_effects.conf"
-#define EFFECTS_TAG "effects"
-#define LIBRARIES_TAG "libraries"
-#define PATH_TAG "path"
-#define LIBRARY_TAG "library"
-#define UUID_TAG "uuid"
 
 typedef struct list_elem_s {
     void *object;
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
new file mode 100755
index 0000000..77d40b6
--- /dev/null
+++ b/media/libeffects/preprocessing/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+# audio preprocessing wrapper
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libaudiopreprocessing
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+LOCAL_SRC_FILES:= \
+    PreProcessing.cpp
+
+LOCAL_C_INCLUDES += \
+    external/webrtc/src \
+    external/webrtc/src/modules/interface \
+    external/webrtc/src/modules/audio_processing/main/interface \
+    system/media/audio_effects/include
+
+LOCAL_C_INCLUDES += $(call include-path-for, speex)
+
+LOCAL_SHARED_LIBRARIES := \
+    libwebrtc_audio_preprocessing \
+    libspeexresampler \
+    libutils
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_LDLIBS += -ldl
+else
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
new file mode 100755
index 0000000..ba286a1
--- /dev/null
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -0,0 +1,1609 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#define LOG_TAG "PreProcessing"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <hardware/audio_effect.h>
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_ns.h>
+#include "modules/interface/module_common_types.h"
+#include "modules/audio_processing/main/interface/audio_processing.h"
+#include "speex/speex_resampler.h"
+
+
+//------------------------------------------------------------------------------
+// local definitions
+//------------------------------------------------------------------------------
+
+// maximum number of sessions
+#define PREPROC_NUM_SESSIONS 8
+
+// types of pre processing modules
+enum preproc_id
+{
+    PREPROC_AGC,        // Automatic Gain Control
+    PREPROC_AEC,        // Acoustic Echo Canceler
+    PREPROC_NS,         // Noise Suppressor
+    PREPROC_NUM_EFFECTS
+};
+
+// Session state
+enum preproc_session_state {
+    PREPROC_SESSION_STATE_INIT,        // initialized
+    PREPROC_SESSION_STATE_CONFIG       // configuration received
+};
+
+// Effect/Preprocessor state
+enum preproc_effect_state {
+    PREPROC_EFFECT_STATE_INIT,         // initialized
+    PREPROC_EFFECT_STATE_CREATED,      // webRTC engine created
+    PREPROC_EFFECT_STATE_CONFIG,       // configuration received/disabled
+    PREPROC_EFFECT_STATE_ACTIVE        // active/enabled
+};
+
+// handle on webRTC engine
+typedef void* preproc_fx_handle_t;
+
+typedef struct preproc_session_s preproc_session_t;
+typedef struct preproc_effect_s preproc_effect_t;
+typedef struct preproc_ops_s preproc_ops_t;
+
+// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
+// Function pointer can be null if no action required.
+struct preproc_ops_s {
+    int (* create)(preproc_effect_t *fx);
+    int (* init)(preproc_effect_t *fx);
+    int (* reset)(preproc_effect_t *fx);
+    void (* enable)(preproc_effect_t *fx);
+    void (* disable)(preproc_effect_t *fx);
+    int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
+    int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value);
+    int (* set_device)(preproc_effect_t *fx, uint32_t device);
+};
+
+// Effect context
+struct preproc_effect_s {
+    const struct effect_interface_s *itfe;
+    uint32_t procId;                // type of pre processor (enum preproc_id)
+    uint32_t state;                 // current state (enum preproc_effect_state)
+    preproc_session_t *session;     // session the effect is on
+    const preproc_ops_t *ops;       // effect ops table
+    preproc_fx_handle_t engine;     // handle on webRTC engine
+};
+
+// Session context
+struct preproc_session_s {
+    struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
+    uint32_t state;                     // current state (enum preproc_session_state)
+    int id;                             // audio session ID
+    int io;                             // handle of input stream this session is on
+    webrtc::AudioProcessing* apm;       // handle on webRTC audio processing module (APM)
+    size_t apmFrameCount;               // buffer size for webRTC process (10 ms)
+    uint32_t apmSamplingRate;           // webRTC APM sampling rate (8/16 or 32 kHz)
+    size_t frameCount;                  // buffer size before input resampler ( <=> apmFrameCount)
+    uint32_t samplingRate;              // sampling rate at effect process interface
+    uint32_t inChannelCount;            // input channel count
+    uint32_t outChannelCount;           // output channel count
+    uint32_t createdMsk;                // bit field containing IDs of crested pre processors
+    uint32_t enabledMsk;                // bit field containing IDs of enabled pre processors
+    uint32_t processedMsk;              // bit field containing IDs of pre processors already
+                                        // processed in current round
+    webrtc::AudioFrame *procFrame;      // audio frame passed to webRTC AMP ProcessStream()
+    int16_t *inBuf;                     // input buffer used when resampling
+    size_t inBufSize;                   // input buffer size in frames
+    size_t framesIn;                    // number of frames in input buffer
+    SpeexResamplerState *inResampler;   // handle on input speex resampler
+    int16_t *outBuf;                    // output buffer used when resampling
+    size_t outBufSize;                  // output buffer size in frames
+    size_t framesOut;                   // number of frames in output buffer
+    SpeexResamplerState *outResampler;  // handle on output speex resampler
+    uint32_t revChannelCount;           // number of channels on reverse stream
+    uint32_t revEnabledMsk;             // bit field containing IDs of enabled pre processors
+                                        // with reverse channel
+    uint32_t revProcessedMsk;           // bit field containing IDs of pre processors with reverse
+                                        // channel already processed in current round
+    webrtc::AudioFrame *revFrame;       // audio frame passed to webRTC AMP AnalyzeReverseStream()
+    int16_t *revBuf;                    // reverse channel input buffer
+    size_t revBufSize;                  // reverse channel input buffer size
+    size_t framesRev;                   // number of frames in reverse channel input buffer
+    SpeexResamplerState *revResampler;  // handle on reverse channel input speex resampler
+};
+
+//------------------------------------------------------------------------------
+// Effect descriptors
+//------------------------------------------------------------------------------
+
+// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
+// as the pre processing effects are not defined by OpenSL ES
+
+// Automatic Gain Control
+static const effect_descriptor_t sAgcDescriptor = {
+        { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+        { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+        EFFECT_CONTROL_API_VERSION,
+        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+        0, //FIXME indicate CPU load
+        0, //FIXME indicate memory usage
+        "Automatic Gain Control",
+        "The Android Open Source Project"
+};
+
+// Acoustic Echo Cancellation
+static const effect_descriptor_t sAecDescriptor = {
+        { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+        { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+        EFFECT_CONTROL_API_VERSION,
+        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+        0, //FIXME indicate CPU load
+        0, //FIXME indicate memory usage
+        "Acoustic Echo Canceler",
+        "The Android Open Source Project"
+};
+
+// Noise suppression
+static const effect_descriptor_t sNsDescriptor = {
+        { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+        { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+        EFFECT_CONTROL_API_VERSION,
+        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+        0, //FIXME indicate CPU load
+        0, //FIXME indicate memory usage
+        "Noise Suppression",
+        "The Android Open Source Project"
+};
+
+
+static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
+        &sAgcDescriptor,
+        &sAecDescriptor,
+        &sNsDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Helper functions
+//------------------------------------------------------------------------------
+
+const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
+        FX_IID_AGC,
+        FX_IID_AEC,
+        FX_IID_NS
+};
+
+
+const effect_uuid_t * ProcIdToUuid(int procId)
+{
+    if (procId >= PREPROC_NUM_EFFECTS) {
+        return EFFECT_UUID_NULL;
+    }
+    return sUuidToPreProcTable[procId];
+}
+
+uint32_t UuidToProcId(const effect_uuid_t * uuid)
+{
+    size_t i;
+    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+        if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
+            break;
+        }
+    }
+    return i;
+}
+
+bool HasReverseStream(uint32_t procId)
+{
+    if (procId == PREPROC_AEC) {
+        return true;
+    }
+    return false;
+}
+
+
+//------------------------------------------------------------------------------
+// Automatic Gain Control (AGC)
+//------------------------------------------------------------------------------
+
+static const int kAgcDefaultTargetLevel = 0;
+static const int kAgcDefaultCompGain = 90;
+static const bool kAgcDefaultLimiter = true;
+
+int  AgcInit (preproc_effect_t *effect)
+{
+    LOGV("AgcInit");
+    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+    agc->set_mode(webrtc::GainControl::kFixedDigital);
+    agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
+    agc->set_compression_gain_db(kAgcDefaultCompGain);
+    agc->enable_limiter(kAgcDefaultLimiter);
+    return 0;
+}
+
+int  AgcCreate(preproc_effect_t *effect)
+{
+    webrtc::GainControl *agc = effect->session->apm->gain_control();
+    LOGV("AgcCreate got agc %p", agc);
+    if (agc == NULL) {
+        LOGW("AgcCreate Error");
+        return -ENOMEM;
+    }
+    effect->engine = static_cast<preproc_fx_handle_t>(agc);
+    AgcInit(effect);
+    return 0;
+}
+
+int AgcGetParameter(preproc_effect_t *effect,
+                    void *pParam,
+                    size_t *pValueSize,
+                    void *pValue)
+{
+    int status = 0;
+    uint32_t param = *(uint32_t *)pParam;
+    t_agc_settings *pProperties = (t_agc_settings *)pValue;
+    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+
+    switch (param) {
+    case AGC_PARAM_TARGET_LEVEL:
+    case AGC_PARAM_COMP_GAIN:
+        if (*pValueSize < sizeof(int16_t)) {
+            *pValueSize = 0;
+            return -EINVAL;
+        }
+        break;
+    case AGC_PARAM_LIMITER_ENA:
+        if (*pValueSize < sizeof(bool)) {
+            *pValueSize = 0;
+            return -EINVAL;
+        }
+        break;
+    case AGC_PARAM_PROPERTIES:
+        if (*pValueSize < sizeof(t_agc_settings)) {
+            *pValueSize = 0;
+            return -EINVAL;
+        }
+        break;
+
+    default:
+        LOGW("AgcGetParameter() unknown param %08x", param);
+        status = -EINVAL;
+        break;
+    }
+
+    switch (param) {
+    case AGC_PARAM_TARGET_LEVEL:
+        *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
+        LOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
+        break;
+    case AGC_PARAM_COMP_GAIN:
+        *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
+        LOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
+        break;
+    case AGC_PARAM_LIMITER_ENA:
+        *(bool *) pValue = (bool)agc->is_limiter_enabled();
+        LOGV("AgcGetParameter() limiter enabled %s",
+             (*(int16_t *) pValue != 0) ? "true" : "false");
+        break;
+    case AGC_PARAM_PROPERTIES:
+        pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
+        pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
+        pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
+        break;
+    default:
+        LOGW("AgcGetParameter() unknown param %d", param);
+        status = -EINVAL;
+        break;
+    }
+    return status;
+}
+
+int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+    int status = 0;
+    uint32_t param = *(uint32_t *)pParam;
+    t_agc_settings *pProperties = (t_agc_settings *)pValue;
+    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+
+    switch (param) {
+    case AGC_PARAM_TARGET_LEVEL:
+        LOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
+        status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
+        break;
+    case AGC_PARAM_COMP_GAIN:
+        LOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
+        status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
+        break;
+    case AGC_PARAM_LIMITER_ENA:
+        LOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
+        status = agc->enable_limiter(*(bool *)pValue);
+        break;
+    case AGC_PARAM_PROPERTIES:
+        LOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
+             pProperties->targetLevel,
+             pProperties->compGain,
+             pProperties->limiterEnabled);
+        status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
+        if (status != 0) break;
+        status = agc->set_compression_gain_db(pProperties->compGain / 100);
+        if (status != 0) break;
+        status = agc->enable_limiter(pProperties->limiterEnabled);
+        break;
+    default:
+        LOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+        status = -EINVAL;
+        break;
+    }
+
+    LOGV("AgcSetParameter() done status %d", status);
+
+    return status;
+}
+
+void AgcEnable(preproc_effect_t *effect)
+{
+    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+    LOGV("AgcEnable agc %p", agc);
+    agc->Enable(true);
+}
+
+void AgcDisable(preproc_effect_t *effect)
+{
+    LOGV("AgcDisable");
+    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+    agc->Enable(false);
+}
+
+
+static const preproc_ops_t sAgcOps = {
+        AgcCreate,
+        AgcInit,
+        NULL,
+        AgcEnable,
+        AgcDisable,
+        AgcSetParameter,
+        AgcGetParameter,
+        NULL
+};
+
+
+//------------------------------------------------------------------------------
+// Acoustic Echo Canceler (AEC)
+//------------------------------------------------------------------------------
+
+static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
+        webrtc::EchoControlMobile::kEarpiece;
+static const bool kAecDefaultComfortNoise = true;
+
+int  AecInit (preproc_effect_t *effect)
+{
+    LOGV("AecInit");
+    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+    aec->set_routing_mode(kAecDefaultMode);
+    aec->enable_comfort_noise(kAecDefaultComfortNoise);
+    return 0;
+}
+
+int  AecCreate(preproc_effect_t *effect)
+{
+    webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
+    LOGV("AecCreate got aec %p", aec);
+    if (aec == NULL) {
+        LOGW("AgcCreate Error");
+        return -ENOMEM;
+    }
+    effect->engine = static_cast<preproc_fx_handle_t>(aec);
+    AecInit (effect);
+    return 0;
+}
+
+int AecGetParameter(preproc_effect_t     *effect,
+                    void              *pParam,
+                    size_t            *pValueSize,
+                    void              *pValue)
+{
+    int status = 0;
+    uint32_t param = *(uint32_t *)pParam;
+
+    if (*pValueSize < sizeof(uint32_t)) {
+        return -EINVAL;
+    }
+    switch (param) {
+    case AEC_PARAM_ECHO_DELAY:
+    case AEC_PARAM_PROPERTIES:
+        *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
+        LOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
+        break;
+    default:
+        LOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+        status = -EINVAL;
+        break;
+    }
+    return status;
+}
+
+int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+    int status = 0;
+    uint32_t param = *(uint32_t *)pParam;
+    uint32_t value = *(uint32_t *)pValue;
+
+    switch (param) {
+    case AEC_PARAM_ECHO_DELAY:
+    case AEC_PARAM_PROPERTIES:
+        status = effect->session->apm->set_stream_delay_ms(value/1000);
+        LOGV("AecSetParameter() echo delay %d us, status %d", value, status);
+        break;
+    default:
+        LOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+        status = -EINVAL;
+        break;
+    }
+    return status;
+}
+
+void AecEnable(preproc_effect_t *effect)
+{
+    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+    LOGV("AecEnable aec %p", aec);
+    aec->Enable(true);
+}
+
+void AecDisable(preproc_effect_t *effect)
+{
+    LOGV("AecDisable");
+    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+    aec->Enable(false);
+}
+
+int AecSetDevice(preproc_effect_t *effect, uint32_t device)
+{
+    LOGV("AecSetDevice %08x", device);
+    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+    webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
+
+    switch(device) {
+    case AUDIO_DEVICE_OUT_EARPIECE:
+        mode = webrtc::EchoControlMobile::kEarpiece;
+        break;
+    case AUDIO_DEVICE_OUT_SPEAKER:
+        mode = webrtc::EchoControlMobile::kSpeakerphone;
+        break;
+    case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+    case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+    default:
+        break;
+    }
+    aec->set_routing_mode(mode);
+    return 0;
+}
+
+static const preproc_ops_t sAecOps = {
+        AecCreate,
+        AecInit,
+        NULL,
+        AecEnable,
+        AecDisable,
+        AecSetParameter,
+        AecGetParameter,
+        AecSetDevice
+};
+
+//------------------------------------------------------------------------------
+// Noise Suppression (NS)
+//------------------------------------------------------------------------------
+
+static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
+
+int  NsInit (preproc_effect_t *effect)
+{
+    LOGV("NsInit");
+    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+    ns->set_level(kNsDefaultLevel);
+    return 0;
+}
+
+int  NsCreate(preproc_effect_t *effect)
+{
+    webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
+    LOGV("NsCreate got ns %p", ns);
+    if (ns == NULL) {
+        LOGW("AgcCreate Error");
+        return -ENOMEM;
+    }
+    effect->engine = static_cast<preproc_fx_handle_t>(ns);
+    NsInit (effect);
+    return 0;
+}
+
+int NsGetParameter(preproc_effect_t     *effect,
+                   void              *pParam,
+                   size_t            *pValueSize,
+                   void              *pValue)
+{
+    int status = 0;
+    return status;
+}
+
+int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+    int status = 0;
+    return status;
+}
+
+void NsEnable(preproc_effect_t *effect)
+{
+    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+    LOGV("NsEnable ns %p", ns);
+    ns->Enable(true);
+}
+
+void NsDisable(preproc_effect_t *effect)
+{
+    LOGV("NsDisable");
+    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+    ns->Enable(false);
+}
+
+static const preproc_ops_t sNsOps = {
+        NsCreate,
+        NsInit,
+        NULL,
+        NsEnable,
+        NsDisable,
+        NsSetParameter,
+        NsGetParameter,
+        NULL
+};
+
+
+static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
+        &sAgcOps,
+        &sAecOps,
+        &sNsOps
+};
+
+
+//------------------------------------------------------------------------------
+// Effect functions
+//------------------------------------------------------------------------------
+
+void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
+
+extern "C" const struct effect_interface_s sEffectInterface;
+extern "C" const struct effect_interface_s sEffectInterfaceReverse;
+
+#define BAD_STATE_ABORT(from, to) \
+        LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
+
+int Effect_SetState(preproc_effect_t *effect, uint32_t state)
+{
+    int status = 0;
+    LOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
+    switch(state) {
+    case PREPROC_EFFECT_STATE_INIT:
+        switch(effect->state) {
+        case PREPROC_EFFECT_STATE_ACTIVE:
+            effect->ops->disable(effect);
+            Session_SetProcEnabled(effect->session, effect->procId, false);
+        case PREPROC_EFFECT_STATE_CONFIG:
+        case PREPROC_EFFECT_STATE_CREATED:
+        case PREPROC_EFFECT_STATE_INIT:
+            break;
+        default:
+            BAD_STATE_ABORT(effect->state, state);
+        }
+        break;
+    case PREPROC_EFFECT_STATE_CREATED:
+        switch(effect->state) {
+        case PREPROC_EFFECT_STATE_INIT:
+            status = effect->ops->create(effect);
+            break;
+        case PREPROC_EFFECT_STATE_CREATED:
+        case PREPROC_EFFECT_STATE_ACTIVE:
+        case PREPROC_EFFECT_STATE_CONFIG:
+            LOGE("Effect_SetState invalid transition");
+            status = -ENOSYS;
+            break;
+        default:
+            BAD_STATE_ABORT(effect->state, state);
+        }
+        break;
+    case PREPROC_EFFECT_STATE_CONFIG:
+        switch(effect->state) {
+        case PREPROC_EFFECT_STATE_INIT:
+            LOGE("Effect_SetState invalid transition");
+            status = -ENOSYS;
+            break;
+        case PREPROC_EFFECT_STATE_ACTIVE:
+            effect->ops->disable(effect);
+            Session_SetProcEnabled(effect->session, effect->procId, false);
+            break;
+        case PREPROC_EFFECT_STATE_CREATED:
+        case PREPROC_EFFECT_STATE_CONFIG:
+            break;
+        default:
+            BAD_STATE_ABORT(effect->state, state);
+        }
+        break;
+    case PREPROC_EFFECT_STATE_ACTIVE:
+        switch(effect->state) {
+        case PREPROC_EFFECT_STATE_INIT:
+        case PREPROC_EFFECT_STATE_CREATED:
+        case PREPROC_EFFECT_STATE_ACTIVE:
+            LOGE("Effect_SetState invalid transition");
+            status = -ENOSYS;
+            break;
+        case PREPROC_EFFECT_STATE_CONFIG:
+            effect->ops->enable(effect);
+            Session_SetProcEnabled(effect->session, effect->procId, true);
+            break;
+        default:
+            BAD_STATE_ABORT(effect->state, state);
+        }
+        break;
+    default:
+        BAD_STATE_ABORT(effect->state, state);
+    }
+    if (status == 0) {
+        effect->state = state;
+    }
+    return status;
+}
+
+int Effect_Init(preproc_effect_t *effect, uint32_t procId)
+{
+    if (HasReverseStream(procId)) {
+        effect->itfe = &sEffectInterfaceReverse;
+    } else {
+        effect->itfe = &sEffectInterface;
+    }
+    effect->ops = sPreProcOps[procId];
+    effect->procId = procId;
+    effect->state = PREPROC_EFFECT_STATE_INIT;
+    return 0;
+}
+
+int Effect_Create(preproc_effect_t *effect,
+               preproc_session_t *session,
+               effect_handle_t  *interface)
+{
+    effect->session = session;
+    *interface = (effect_handle_t)&effect->itfe;
+    return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
+}
+
+int Effect_Release(preproc_effect_t *effect)
+{
+    return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
+}
+
+
+//------------------------------------------------------------------------------
+// Session functions
+//------------------------------------------------------------------------------
+
+#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
+
+static const int kPreprocDefaultSr = 16000;
+static const int kPreProcDefaultCnl = 1;
+
+int Session_Init(preproc_session_t *session)
+{
+    size_t i;
+    int status = 0;
+
+    session->state = PREPROC_SESSION_STATE_INIT;
+    session->id = 0;
+    session->io = 0;
+    session->createdMsk = 0;
+    session->apm = NULL;
+    for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
+        status = Effect_Init(&session->effects[i], i);
+    }
+    return status;
+}
+
+
+extern "C" int Session_CreateEffect(preproc_session_t *session,
+                                    int32_t procId,
+                                    effect_handle_t  *interface)
+{
+    int status = -ENOMEM;
+
+    LOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
+
+    if (session->createdMsk == 0) {
+        session->apm = webrtc::AudioProcessing::Create(session->io);
+        if (session->apm == NULL) {
+            LOGW("Session_CreateEffect could not get apm engine");
+            goto error;
+        }
+        session->apm->set_sample_rate_hz(kPreprocDefaultSr);
+        session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl);
+        session->apm->set_num_reverse_channels(kPreProcDefaultCnl);
+        session->procFrame = new webrtc::AudioFrame();
+        if (session->procFrame == NULL) {
+            LOGW("Session_CreateEffect could not allocate audio frame");
+            goto error;
+        }
+        session->revFrame = new webrtc::AudioFrame();
+        if (session->revFrame == NULL) {
+            LOGW("Session_CreateEffect could not allocate reverse audio frame");
+            goto error;
+        }
+        session->apmSamplingRate = kPreprocDefaultSr;
+        session->apmFrameCount = (kPreprocDefaultSr) / 100;
+        session->frameCount = session->apmFrameCount;
+        session->samplingRate = kPreprocDefaultSr;
+        session->inChannelCount = kPreProcDefaultCnl;
+        session->outChannelCount = kPreProcDefaultCnl;
+        session->procFrame->_frequencyInHz = kPreprocDefaultSr;
+        session->procFrame->_audioChannel = kPreProcDefaultCnl;
+        session->revChannelCount = kPreProcDefaultCnl;
+        session->revFrame->_frequencyInHz = kPreprocDefaultSr;
+        session->revFrame->_audioChannel = kPreProcDefaultCnl;
+        session->enabledMsk = 0;
+        session->processedMsk = 0;
+        session->revEnabledMsk = 0;
+        session->revProcessedMsk = 0;
+        session->inResampler = NULL;
+        session->inBuf = NULL;
+        session->inBufSize = 0;
+        session->outResampler = NULL;
+        session->outBuf = NULL;
+        session->outBufSize = 0;
+        session->revResampler = NULL;
+        session->revBuf = NULL;
+        session->revBufSize = 0;
+    }
+    status = Effect_Create(&session->effects[procId], session, interface);
+    if (status < 0) {
+        goto error;
+    }
+    LOGV("Session_CreateEffect OK");
+    session->createdMsk |= (1<<procId);
+    return status;
+
+error:
+    if (session->createdMsk == 0) {
+        delete session->revFrame;
+        session->revFrame = NULL;
+        delete session->procFrame;
+        session->procFrame = NULL;
+        webrtc::AudioProcessing::Destroy(session->apm);
+        session->apm = NULL;
+    }
+    return status;
+}
+
+int Session_ReleaseEffect(preproc_session_t *session,
+                          preproc_effect_t *fx)
+{
+    LOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
+    session->createdMsk &= ~(1<<fx->procId);
+    if (session->createdMsk == 0) {
+        webrtc::AudioProcessing::Destroy(session->apm);
+        session->apm = NULL;
+        delete session->procFrame;
+        session->procFrame = NULL;
+        delete session->revFrame;
+        session->revFrame = NULL;
+        if (session->inResampler != NULL) {
+            speex_resampler_destroy(session->inResampler);
+            session->inResampler = NULL;
+        }
+        if (session->outResampler != NULL) {
+            speex_resampler_destroy(session->outResampler);
+            session->outResampler = NULL;
+        }
+        if (session->revResampler != NULL) {
+            speex_resampler_destroy(session->revResampler);
+            session->revResampler = NULL;
+        }
+        delete session->inBuf;
+        session->inBuf = NULL;
+        delete session->outBuf;
+        session->outBuf = NULL;
+        delete session->revBuf;
+        session->revBuf = NULL;
+
+        session->io = 0;
+    }
+
+    return 0;
+}
+
+
+int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
+{
+    uint32_t sr;
+    uint32_t inCnl = popcount(config->inputCfg.channels);
+    uint32_t outCnl = popcount(config->outputCfg.channels);
+
+    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
+        config->inputCfg.format != config->outputCfg.format ||
+        config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+        return -EINVAL;
+    }
+
+    LOGV("Session_SetConfig sr %d cnl %08x",
+         config->inputCfg.samplingRate, config->inputCfg.channels);
+    int status;
+
+    // AEC implementation is limited to 16kHz
+    if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
+        session->apmSamplingRate = 32000;
+    } else
+    if (config->inputCfg.samplingRate >= 16000) {
+        session->apmSamplingRate = 16000;
+    } else if (config->inputCfg.samplingRate >= 8000) {
+        session->apmSamplingRate = 8000;
+    }
+    status = session->apm->set_sample_rate_hz(session->apmSamplingRate);
+    if (status < 0) {
+        return -EINVAL;
+    }
+    status = session->apm->set_num_channels(inCnl, outCnl);
+    if (status < 0) {
+        return -EINVAL;
+    }
+    status = session->apm->set_num_reverse_channels(inCnl);
+    if (status < 0) {
+        return -EINVAL;
+    }
+
+    session->samplingRate = config->inputCfg.samplingRate;
+    session->apmFrameCount = session->apmSamplingRate / 100;
+    if (session->samplingRate == session->apmSamplingRate) {
+        session->frameCount = session->apmFrameCount;
+    } else {
+        session->frameCount = (session->apmFrameCount * session->samplingRate) /
+                session->apmSamplingRate  + 1;
+    }
+    session->inChannelCount = inCnl;
+    session->outChannelCount = outCnl;
+    session->procFrame->_audioChannel = inCnl;
+    session->procFrame->_frequencyInHz = session->apmSamplingRate;
+
+    session->revChannelCount = inCnl;
+    session->revFrame->_audioChannel = inCnl;
+    session->revFrame->_frequencyInHz = session->apmSamplingRate;
+
+    if (session->inResampler != NULL) {
+        speex_resampler_destroy(session->inResampler);
+        session->inResampler = NULL;
+    }
+    if (session->outResampler != NULL) {
+        speex_resampler_destroy(session->outResampler);
+        session->outResampler = NULL;
+    }
+    if (session->revResampler != NULL) {
+        speex_resampler_destroy(session->revResampler);
+        session->revResampler = NULL;
+    }
+    if (session->samplingRate != session->apmSamplingRate) {
+        int error;
+        session->inResampler = speex_resampler_init(session->inChannelCount,
+                                                    session->samplingRate,
+                                                    session->apmSamplingRate,
+                                                    RESAMPLER_QUALITY,
+                                                    &error);
+        if (session->inResampler == NULL) {
+            LOGW("Session_SetConfig Cannot create speex resampler: %s",
+                 speex_resampler_strerror(error));
+            return -EINVAL;
+        }
+        session->outResampler = speex_resampler_init(session->outChannelCount,
+                                                    session->apmSamplingRate,
+                                                    session->samplingRate,
+                                                    RESAMPLER_QUALITY,
+                                                    &error);
+        if (session->outResampler == NULL) {
+            LOGW("Session_SetConfig Cannot create speex resampler: %s",
+                 speex_resampler_strerror(error));
+            speex_resampler_destroy(session->inResampler);
+            session->inResampler = NULL;
+            return -EINVAL;
+        }
+        session->revResampler = speex_resampler_init(session->inChannelCount,
+                                                    session->samplingRate,
+                                                    session->apmSamplingRate,
+                                                    RESAMPLER_QUALITY,
+                                                    &error);
+        if (session->revResampler == NULL) {
+            LOGW("Session_SetConfig Cannot create speex resampler: %s",
+                 speex_resampler_strerror(error));
+            speex_resampler_destroy(session->inResampler);
+            session->inResampler = NULL;
+            speex_resampler_destroy(session->outResampler);
+            session->outResampler = NULL;
+            return -EINVAL;
+        }
+    }
+
+    session->state = PREPROC_SESSION_STATE_CONFIG;
+    return 0;
+}
+
+int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
+{
+    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
+            config->inputCfg.format != config->outputCfg.format ||
+            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+        return -EINVAL;
+    }
+
+    LOGV("Session_SetReverseConfig sr %d cnl %08x",
+         config->inputCfg.samplingRate, config->inputCfg.channels);
+
+    if (session->state < PREPROC_SESSION_STATE_CONFIG) {
+        return -ENOSYS;
+    }
+    if (config->inputCfg.samplingRate != session->samplingRate ||
+            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+        return -EINVAL;
+    }
+    uint32_t inCnl = popcount(config->inputCfg.channels);
+    int status = session->apm->set_num_reverse_channels(inCnl);
+    if (status < 0) {
+        return -EINVAL;
+    }
+    session->revChannelCount = inCnl;
+    session->revFrame->_audioChannel = inCnl;
+    session->revFrame->_frequencyInHz = session->apmSamplingRate;
+    return 0;
+}
+
+void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
+{
+    if (enabled) {
+        if(session->enabledMsk == 0) {
+            session->framesIn = 0;
+            if (session->inResampler != NULL) {
+                speex_resampler_reset_mem(session->inResampler);
+            }
+            session->framesOut = 0;
+            if (session->outResampler != NULL) {
+                speex_resampler_reset_mem(session->outResampler);
+            }
+        }
+        session->enabledMsk |= (1 << procId);
+        if (HasReverseStream(procId)) {
+            session->framesRev = 0;
+            if (session->revResampler != NULL) {
+                speex_resampler_reset_mem(session->revResampler);
+            }
+            session->revEnabledMsk |= (1 << procId);
+        }
+    } else {
+        session->enabledMsk &= ~(1 << procId);
+        if (HasReverseStream(procId)) {
+            session->revEnabledMsk &= ~(1 << procId);
+        }
+    }
+    LOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
+         procId, enabled, session->enabledMsk, session->revEnabledMsk);
+    session->processedMsk = 0;
+    if (HasReverseStream(procId)) {
+        session->revProcessedMsk = 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+// Bundle functions
+//------------------------------------------------------------------------------
+
+static int sInitStatus = 1;
+static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
+
+preproc_session_t *PreProc_GetSession(int32_t procId, int32_t  sessionId, int32_t  ioId)
+{
+    size_t i;
+    int free = -1;
+    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
+        if (sSessions[i].io == ioId) {
+            if (sSessions[i].createdMsk & (1 << procId)) {
+                return NULL;
+            }
+            return &sSessions[i];
+        }
+    }
+    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
+        if (sSessions[i].io == 0) {
+            sSessions[i].id = sessionId;
+            sSessions[i].io = ioId;
+            return &sSessions[i];
+        }
+    }
+    return NULL;
+}
+
+
+int PreProc_Init() {
+    size_t i;
+    int status = 0;
+
+    if (sInitStatus <= 0) {
+        return sInitStatus;
+    }
+    for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
+        status = Session_Init(&sSessions[i]);
+    }
+    sInitStatus = status;
+    return sInitStatus;
+}
+
+const effect_descriptor_t *PreProc_GetDescriptor(effect_uuid_t *uuid)
+{
+    size_t i;
+    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+        if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+            return sDescriptors[i];
+        }
+    }
+    return NULL;
+}
+
+
+extern "C" {
+
+//------------------------------------------------------------------------------
+// Effect Control Interface Implementation
+//------------------------------------------------------------------------------
+
+int PreProcessingFx_Process(effect_handle_t     self,
+                            audio_buffer_t    *inBuffer,
+                            audio_buffer_t    *outBuffer)
+{
+    preproc_effect_t * effect = (preproc_effect_t *)self;
+    int    status = 0;
+
+    if (effect == NULL){
+        LOGV("PreProcessingFx_Process() ERROR effect == NULL");
+        return -EINVAL;
+    }
+    preproc_session_t * session = (preproc_session_t *)effect->session;
+
+    if (inBuffer == NULL  || inBuffer->raw == NULL  ||
+            outBuffer == NULL || outBuffer->raw == NULL){
+        LOGW("PreProcessingFx_Process() ERROR bad pointer");
+        return -EINVAL;
+    }
+
+    session->processedMsk |= (1<<effect->procId);
+
+//    LOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
+//         inBuffer->frameCount, session->enabledMsk, session->processedMsk);
+
+    if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
+        effect->session->processedMsk = 0;
+        size_t framesRq = outBuffer->frameCount;
+        size_t framesWr = 0;
+        if (session->framesOut) {
+            size_t fr = session->framesOut;
+            if (outBuffer->frameCount < fr) {
+                fr = outBuffer->frameCount;
+            }
+            memcpy(outBuffer->s16,
+                  session->outBuf,
+                  fr * session->outChannelCount * sizeof(int16_t));
+            memcpy(session->outBuf,
+                  session->outBuf + fr * session->outChannelCount,
+                  (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
+            session->framesOut -= fr;
+            framesWr += fr;
+        }
+        outBuffer->frameCount = framesWr;
+        if (framesWr == framesRq) {
+            inBuffer->frameCount = 0;
+            return 0;
+        }
+
+        if (session->inResampler != NULL) {
+            size_t fr = session->frameCount - session->framesIn;
+            if (inBuffer->frameCount < fr) {
+                fr = inBuffer->frameCount;
+            }
+            if (session->inBufSize < session->framesIn + fr) {
+                session->inBufSize = session->framesIn + fr;
+                session->inBuf = (int16_t *)realloc(session->inBuf,
+                                 session->inBufSize * session->inChannelCount * sizeof(int16_t));
+            }
+            memcpy(session->inBuf + session->framesIn * session->inChannelCount,
+                   inBuffer->s16,
+                   fr * session->inChannelCount * sizeof(int16_t));
+
+            session->framesIn += fr;
+            inBuffer->frameCount = fr;
+            if (session->framesIn < session->frameCount) {
+                return 0;
+            }
+            size_t frIn = session->framesIn;
+            size_t frOut = session->apmFrameCount;
+            if (session->inChannelCount == 1) {
+                speex_resampler_process_int(session->inResampler,
+                                            0,
+                                            session->inBuf,
+                                            &frIn,
+                                            session->procFrame->_payloadData,
+                                            &frOut);
+            } else {
+                speex_resampler_process_interleaved_int(session->inResampler,
+                                                        session->inBuf,
+                                                        &frIn,
+                                                        session->procFrame->_payloadData,
+                                                        &frOut);
+            }
+            memcpy(session->inBuf,
+                   session->inBuf + frIn * session->inChannelCount,
+                   (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
+            session->framesIn -= frIn;
+        } else {
+            size_t fr = session->frameCount - session->framesIn;
+            if (inBuffer->frameCount < fr) {
+                fr = inBuffer->frameCount;
+            }
+            memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount,
+                   inBuffer->s16,
+                   fr * session->inChannelCount * sizeof(int16_t));
+            session->framesIn += fr;
+            inBuffer->frameCount = fr;
+            if (session->framesIn < session->frameCount) {
+                return 0;
+            }
+            session->framesIn = 0;
+        }
+        session->procFrame->_payloadDataLengthInSamples =
+                session->apmFrameCount * session->inChannelCount;
+
+        effect->session->apm->ProcessStream(session->procFrame);
+
+        if (session->outBufSize < session->framesOut + session->frameCount) {
+            session->outBufSize = session->framesOut + session->frameCount;
+            session->outBuf = (int16_t *)realloc(session->outBuf,
+                              session->outBufSize * session->outChannelCount * sizeof(int16_t));
+        }
+
+        if (session->outResampler != NULL) {
+            size_t frIn = session->apmFrameCount;
+            size_t frOut = session->frameCount;
+            if (session->inChannelCount == 1) {
+                speex_resampler_process_int(session->outResampler,
+                                    0,
+                                    session->procFrame->_payloadData,
+                                    &frIn,
+                                    session->outBuf + session->framesOut * session->outChannelCount,
+                                    &frOut);
+            } else {
+                speex_resampler_process_interleaved_int(session->outResampler,
+                                    session->procFrame->_payloadData,
+                                    &frIn,
+                                    session->outBuf + session->framesOut * session->outChannelCount,
+                                    &frOut);
+            }
+            session->framesOut += frOut;
+        } else {
+            memcpy(session->outBuf + session->framesOut * session->outChannelCount,
+                   session->procFrame->_payloadData,
+                   session->frameCount * session->outChannelCount * sizeof(int16_t));
+            session->framesOut += session->frameCount;
+        }
+        size_t fr = session->framesOut;
+        if (framesRq - framesWr < fr) {
+            fr = framesRq - framesWr;
+        }
+        memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
+              session->outBuf,
+              fr * session->outChannelCount * sizeof(int16_t));
+        memcpy(session->outBuf,
+              session->outBuf + fr * session->outChannelCount,
+              (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
+        session->framesOut -= fr;
+        outBuffer->frameCount += fr;
+
+        return 0;
+    } else {
+        return -ENODATA;
+    }
+}
+
+int PreProcessingFx_Command(effect_handle_t  self,
+                            uint32_t            cmdCode,
+                            uint32_t            cmdSize,
+                            void                *pCmdData,
+                            uint32_t            *replySize,
+                            void                *pReplyData)
+{
+    preproc_effect_t * effect = (preproc_effect_t *) self;
+    int retsize;
+    int status;
+
+    if (effect == NULL){
+        return -EINVAL;
+    }
+
+    //LOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode){
+        case EFFECT_CMD_INIT:
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                return -EINVAL;
+            }
+            if (effect->ops->init) {
+                effect->ops->init(effect);
+            }
+            *(int *)pReplyData = 0;
+            break;
+
+        case EFFECT_CMD_CONFIGURE:
+            if (pCmdData    == NULL||
+                cmdSize     != sizeof(effect_config_t)||
+                pReplyData  == NULL||
+                *replySize  != sizeof(int)){
+                LOGV("PreProcessingFx_Command cmdCode Case: "
+                        "EFFECT_CMD_CONFIGURE: ERROR");
+                return -EINVAL;
+            }
+            *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
+            if (*(int *)pReplyData != 0) {
+                break;
+            }
+            *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+            break;
+
+        case EFFECT_CMD_CONFIGURE_REVERSE:
+            if (pCmdData    == NULL||
+                cmdSize     != sizeof(effect_config_t)||
+                pReplyData  == NULL||
+                *replySize  != sizeof(int)){
+                LOGV("PreProcessingFx_Command cmdCode Case: "
+                        "EFFECT_CMD_CONFIGURE_REVERSE: ERROR");
+                return -EINVAL;
+            }
+            *(int *)pReplyData = Session_SetReverseConfig(effect->session,
+                                                          (effect_config_t *)pCmdData);
+            if (*(int *)pReplyData != 0) {
+                break;
+            }
+            break;
+
+        case EFFECT_CMD_RESET:
+            if (effect->ops->reset) {
+                effect->ops->reset(effect);
+            }
+            break;
+
+        case EFFECT_CMD_GET_PARAM:{
+            if (pCmdData == NULL ||
+                    cmdSize < (int)sizeof(effect_param_t) ||
+                    pReplyData == NULL ||
+                    *replySize < (int)sizeof(effect_param_t)){
+                LOGV("PreProcessingFx_Command cmdCode Case: "
+                        "EFFECT_CMD_GET_PARAM: ERROR");
+                return -EINVAL;
+            }
+            effect_param_t *p = (effect_param_t *)pCmdData;
+
+            memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+            p = (effect_param_t *)pReplyData;
+
+            int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+            if (effect->ops->get_parameter) {
+                p->status = effect->ops->get_parameter(effect, p->data,
+                                                       (size_t  *)&p->vsize,
+                                                       p->data + voffset);
+                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+            }
+        } break;
+
+        case EFFECT_CMD_SET_PARAM:{
+            if (pCmdData == NULL||
+                    cmdSize < (int)sizeof(effect_param_t) ||
+                    pReplyData == NULL ||
+                    *replySize != sizeof(int32_t)){
+                LOGV("PreProcessingFx_Command cmdCode Case: "
+                        "EFFECT_CMD_SET_PARAM: ERROR");
+                return -EINVAL;
+            }
+            effect_param_t *p = (effect_param_t *) pCmdData;
+
+            if (p->psize != sizeof(int32_t)){
+                LOGV("PreProcessingFx_Command cmdCode Case: "
+                        "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+                return -EINVAL;
+            }
+            if (effect->ops->set_parameter) {
+                *(int *)pReplyData = effect->ops->set_parameter(effect,
+                                                                (void *)p->data,
+                                                                p->data + p->psize);
+            }
+        } break;
+
+        case EFFECT_CMD_ENABLE:
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
+                return -EINVAL;
+            }
+            *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
+            break;
+
+        case EFFECT_CMD_DISABLE:
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
+                return -EINVAL;
+            }
+            *(int *)pReplyData  = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+            break;
+
+        case EFFECT_CMD_SET_DEVICE:
+        case EFFECT_CMD_SET_INPUT_DEVICE:
+            if (pCmdData == NULL ||
+                cmdSize != sizeof(uint32_t)) {
+                LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
+                return -EINVAL;
+            }
+
+            if (effect->ops->set_device) {
+                effect->ops->set_device(effect, *(uint32_t *)pCmdData);
+            }
+            break;
+
+        case EFFECT_CMD_SET_VOLUME:
+        case EFFECT_CMD_SET_AUDIO_MODE:
+            break;
+
+        default:
+            return -EINVAL;
+    }
+    return 0;
+}
+
+
+int PreProcessingFx_GetDescriptor(effect_handle_t   self,
+                                  effect_descriptor_t *pDescriptor)
+{
+    preproc_effect_t * effect = (preproc_effect_t *) self;
+
+    if (effect == NULL || pDescriptor == NULL) {
+        return -EINVAL;
+    }
+
+    memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t));
+
+    return 0;
+}
+
+int PreProcessingFx_ProcessReverse(effect_handle_t     self,
+                                   audio_buffer_t    *inBuffer,
+                                   audio_buffer_t    *outBuffer)
+{
+    preproc_effect_t * effect = (preproc_effect_t *)self;
+    int    status = 0;
+
+    if (effect == NULL){
+        LOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
+        return -EINVAL;
+    }
+    preproc_session_t * session = (preproc_session_t *)effect->session;
+
+    if (inBuffer == NULL  || inBuffer->raw == NULL){
+        LOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
+        return -EINVAL;
+    }
+
+    session->revProcessedMsk |= (1<<effect->procId);
+
+//    LOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
+//         inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
+
+
+    if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
+        effect->session->revProcessedMsk = 0;
+        if (session->revResampler != NULL) {
+            size_t fr = session->frameCount - session->framesRev;
+            if (inBuffer->frameCount < fr) {
+                fr = inBuffer->frameCount;
+            }
+            if (session->revBufSize < session->framesRev + fr) {
+                session->revBufSize = session->framesRev + fr;
+                session->revBuf = (int16_t *)realloc(session->revBuf,
+                                  session->revBufSize * session->inChannelCount * sizeof(int16_t));
+            }
+            memcpy(session->revBuf + session->framesRev * session->inChannelCount,
+                   inBuffer->s16,
+                   fr * session->inChannelCount * sizeof(int16_t));
+
+            session->framesRev += fr;
+            inBuffer->frameCount = fr;
+            if (session->framesRev < session->frameCount) {
+                return 0;
+            }
+            size_t frIn = session->framesRev;
+            size_t frOut = session->apmFrameCount;
+            if (session->inChannelCount == 1) {
+                speex_resampler_process_int(session->revResampler,
+                                            0,
+                                            session->revBuf,
+                                            &frIn,
+                                            session->revFrame->_payloadData,
+                                            &frOut);
+            } else {
+                speex_resampler_process_interleaved_int(session->revResampler,
+                                                        session->revBuf,
+                                                        &frIn,
+                                                        session->revFrame->_payloadData,
+                                                        &frOut);
+            }
+            memcpy(session->revBuf,
+                   session->revBuf + frIn * session->inChannelCount,
+                   (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
+            session->framesRev -= frIn;
+        } else {
+            size_t fr = session->frameCount - session->framesRev;
+            if (inBuffer->frameCount < fr) {
+                fr = inBuffer->frameCount;
+            }
+            memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount,
+                   inBuffer->s16,
+                   fr * session->inChannelCount * sizeof(int16_t));
+            session->framesRev += fr;
+            inBuffer->frameCount = fr;
+            if (session->framesRev < session->frameCount) {
+                return 0;
+            }
+            session->framesRev = 0;
+        }
+        session->revFrame->_payloadDataLengthInSamples =
+                session->apmFrameCount * session->inChannelCount;
+        effect->session->apm->AnalyzeReverseStream(session->revFrame);
+        return 0;
+    } else {
+        return -ENODATA;
+    }
+}
+
+
+// effect_handle_t interface implementation for effect
+const struct effect_interface_s sEffectInterface = {
+    PreProcessingFx_Process,
+    PreProcessingFx_Command,
+    PreProcessingFx_GetDescriptor,
+    NULL
+};
+
+const struct effect_interface_s sEffectInterfaceReverse = {
+    PreProcessingFx_Process,
+    PreProcessingFx_Command,
+    PreProcessingFx_GetDescriptor,
+    PreProcessingFx_ProcessReverse
+};
+
+//------------------------------------------------------------------------------
+// Effect Library Interface Implementation
+//------------------------------------------------------------------------------
+
+int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects)
+{
+    if (PreProc_Init() != 0) {
+        return sInitStatus;
+    }
+    if (pNumEffects == NULL) {
+        return -EINVAL;
+    }
+    *pNumEffects = PREPROC_NUM_EFFECTS;
+    return sInitStatus;
+}
+
+int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+{
+    if (PreProc_Init() != 0) {
+        return sInitStatus;
+    }
+    if (index >= PREPROC_NUM_EFFECTS) {
+        return -EINVAL;
+    }
+    memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t));
+    return 0;
+}
+
+int PreProcessingLib_Create(effect_uuid_t       *uuid,
+                            int32_t             sessionId,
+                            int32_t             ioId,
+                            effect_handle_t  *pInterface)
+{
+    LOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
+
+    int status;
+    const effect_descriptor_t *desc;
+    preproc_session_t *session;
+    uint32_t procId;
+
+    if (PreProc_Init() != 0) {
+        return sInitStatus;
+    }
+    desc =  PreProc_GetDescriptor(uuid);
+    if (desc == NULL) {
+        LOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
+        return -EINVAL;
+    }
+    procId = UuidToProcId(&desc->type);
+
+    session = PreProc_GetSession(procId, sessionId, ioId);
+    if (session == NULL) {
+        LOGW("EffectCreate: no more session available");
+        return -EINVAL;
+    }
+
+    status = Session_CreateEffect(session, procId, pInterface);
+
+    if (status < 0 && session->createdMsk == 0) {
+        session->io = 0;
+    }
+    return status;
+}
+
+int PreProcessingLib_Release(effect_handle_t interface)
+{
+    int status;
+    LOGV("EffectRelease start %p", interface);
+    if (PreProc_Init() != 0) {
+        return sInitStatus;
+    }
+
+    preproc_effect_t *fx = (preproc_effect_t *)interface;
+
+    if (fx->session->io == 0) {
+        return -EINVAL;
+    }
+    return Session_ReleaseEffect(fx->session, fx);
+}
+
+int PreProcessingLib_GetDescriptor(effect_uuid_t       *uuid,
+                                   effect_descriptor_t *pDescriptor) {
+
+    if (pDescriptor == NULL || uuid == NULL){
+        return -EINVAL;
+    }
+
+    const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
+    if (desc == NULL) {
+        LOGV("PreProcessingLib_GetDescriptor() not found");
+        return  -EINVAL;
+    }
+
+    LOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
+
+    memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+    return 0;
+}
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+    tag : AUDIO_EFFECT_LIBRARY_TAG,
+    version : EFFECT_LIBRARY_API_VERSION,
+    name : "Audio Preprocessing Library",
+    implementor : "The Android Open Source Project",
+    query_num_effects : PreProcessingLib_QueryNumberEffects,
+    query_effect : PreProcessingLib_QueryEffect,
+    create_effect : PreProcessingLib_Create,
+    release_effect : PreProcessingLib_Release,
+    get_descriptor : PreProcessingLib_GetDescriptor
+};
+
+}; // extern "C"
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 8d98900..0633744 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -47,11 +47,11 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output
+                audio_io_handle_t io
                 )
     : mStatus(NO_INIT)
 {
-    mStatus = set(type, uuid, priority, cbf, user, sessionId, output);
+    mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
 }
 
 AudioEffect::AudioEffect(const char *typeStr,
@@ -60,7 +60,7 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output
+                audio_io_handle_t io
                 )
     : mStatus(NO_INIT)
 {
@@ -83,7 +83,7 @@
         }
     }
 
-    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
+    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
 }
 
 status_t AudioEffect::set(const effect_uuid_t *type,
@@ -92,13 +92,13 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output)
+                audio_io_handle_t io)
 {
     sp<IEffect> iEffect;
     sp<IMemory> cblk;
     int enabled;
 
-    LOGV("set %p mUserData: %p", this, user);
+    LOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
 
     if (mIEffect != 0) {
         LOGW("Effect already in use");
@@ -135,7 +135,7 @@
     mIEffectClient = new EffectClient(this);
 
     iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
-            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+            mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled);
 
     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
         LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
@@ -419,6 +419,15 @@
     return af->getEffectDescriptor(uuid, descriptor);
 }
 
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+                                          effect_descriptor_t *descriptors,
+                                          uint32_t *count)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
 // -------------------------------------------------------------------------
 
 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 4c4aad0..16554c2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -162,8 +162,19 @@
 
     int channelCount = popcount(channelMask);
 
+    if (sessionId == 0 ) {
+        mSessionId = AudioSystem::newAudioSessionId();
+    } else {
+        mSessionId = sessionId;
+    }
+    LOGV("set(): mSessionId %d", mSessionId);
+
     audio_io_handle_t input = AudioSystem::getInput(inputSource,
-                                    sampleRate, format, channelMask, (audio_in_acoustics_t)flags);
+                                                    sampleRate,
+                                                    format,
+                                                    channelMask,
+                                                    (audio_in_acoustics_t)flags,
+                                                    mSessionId);
     if (input == 0) {
         LOGE("Could not get audio input for record source %d", inputSource);
         return BAD_VALUE;
@@ -187,8 +198,6 @@
         notificationFrames = frameCount/2;
     }
 
-    mSessionId = sessionId;
-
     // create the IAudioRecord
     status = openRecord_l(sampleRate, format, channelMask,
                         frameCount, flags, input);
@@ -581,7 +590,7 @@
 audio_io_handle_t AudioRecord::getInput()
 {
     AutoMutex lock(mLock);
-    return getInput_l();
+    return mInput;
 }
 
 // must be called with mLock held
@@ -589,8 +598,10 @@
 {
     mInput = AudioSystem::getInput(mInputSource,
                                 mCblk->sampleRate,
-                                mFormat, mChannelMask,
-                                (audio_in_acoustics_t)mFlags);
+                                mFormat,
+                                mChannelMask,
+                                (audio_in_acoustics_t)mFlags,
+                                mSessionId);
     return mInput;
 }
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 6cb3847..5009957 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -605,11 +605,12 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int sessionId)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return 0;
-    return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
+    return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
 }
 
 status_t AudioSystem::startInput(audio_io_handle_t input)
@@ -678,14 +679,14 @@
 }
 
 status_t AudioSystem::registerEffect(effect_descriptor_t *desc,
-                                audio_io_handle_t output,
+                                audio_io_handle_t io,
                                 uint32_t strategy,
                                 int session,
                                 int id)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
-    return aps->registerEffect(desc, output, strategy, session, id);
+    return aps->registerEffect(desc, io, strategy, session, id);
 }
 
 status_t AudioSystem::unregisterEffect(int id)
@@ -695,9 +696,11 @@
     return aps->unregisterEffect(id);
 }
 
-status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) {
+status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs)
+{
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
+    if (state == NULL) return BAD_VALUE;
     *state = aps->isStreamActive(stream, inPastMs);
     return NO_ERROR;
 }
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 9fbcee0..15f4be0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -53,6 +53,7 @@
     UNREGISTER_EFFECT,
     IS_STREAM_ACTIVE,
     GET_DEVICES_FOR_STREAM,
+    QUERY_DEFAULT_PRE_PROCESSING
 };
 
 class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -184,7 +185,8 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int audioSession)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -193,6 +195,7 @@
         data.writeInt32(static_cast <uint32_t>(format));
         data.writeInt32(channels);
         data.writeInt32(static_cast <uint32_t>(acoustics));
+        data.writeInt32(audioSession);
         remote()->transact(GET_INPUT, data, &reply);
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
@@ -285,7 +288,7 @@
     }
 
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                        audio_io_handle_t output,
+                                        audio_io_handle_t io,
                                         uint32_t strategy,
                                         int session,
                                         int id)
@@ -293,7 +296,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.write(desc, sizeof(effect_descriptor_t));
-        data.writeInt32(output);
+        data.writeInt32(io);
         data.writeInt32(strategy);
         data.writeInt32(session);
         data.writeInt32(id);
@@ -319,6 +322,31 @@
         remote()->transact(IS_STREAM_ACTIVE, data, &reply);
         return reply.readInt32();
     }
+
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                               effect_descriptor_t *descriptors,
+                                               uint32_t *count)
+    {
+        if (descriptors == NULL || count == NULL) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(audioSession);
+        data.writeInt32(*count);
+        status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = static_cast <status_t> (reply.readInt32());
+        uint32_t retCount = reply.readInt32();
+        if (retCount != 0) {
+            uint32_t numDesc = (retCount < *count) ? retCount : *count;
+            reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+        }
+        *count = retCount;
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -439,11 +467,13 @@
             uint32_t channels = data.readInt32();
             audio_in_acoustics_t acoustics =
                     static_cast <audio_in_acoustics_t>(data.readInt32());
+            int audioSession = data.readInt32();
             audio_io_handle_t input = getInput(inputSource,
                                                samplingRate,
                                                format,
                                                channels,
-                                               acoustics);
+                                               acoustics,
+                                               audioSession);
             reply->writeInt32(static_cast <int>(input));
             return NO_ERROR;
         } break;
@@ -528,12 +558,12 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc;
             data.read(&desc, sizeof(effect_descriptor_t));
-            audio_io_handle_t output = data.readInt32();
+            audio_io_handle_t io = data.readInt32();
             uint32_t strategy = data.readInt32();
             int session = data.readInt32();
             int id = data.readInt32();
             reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
-                                                                   output,
+                                                                   io,
                                                                    strategy,
                                                                    session,
                                                                    id)));
@@ -555,6 +585,29 @@
             return NO_ERROR;
         } break;
 
+        case QUERY_DEFAULT_PRE_PROCESSING: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int audioSession = data.readInt32();
+            uint32_t count = data.readInt32();
+            uint32_t retCount = count;
+            effect_descriptor_t *descriptors =
+                    (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+            status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+            reply->writeInt32(status);
+            if (status != NO_ERROR && status != NO_MEMORY) {
+                retCount = 0;
+            }
+            reply->writeInt32(retCount);
+            if (retCount) {
+                if (retCount < count) {
+                    count = retCount;
+                }
+                reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+            }
+            delete[] descriptors;
+            return status;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a44ef5a..38e111e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -23,14 +23,17 @@
 #include <camera/ICamera.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
+#include <gui/ISurfaceTexture.h>
 #include <unistd.h>
 
+
 namespace android {
 
 enum {
     RELEASE = IBinder::FIRST_CALL_TRANSACTION,
     INIT,
     CLOSE,
+    QUERY_SURFACE_MEDIASOURCE,
     RESET,
     STOP,
     START,
@@ -43,7 +46,6 @@
     SET_AUDIO_ENCODER,
     SET_OUTPUT_FILE_PATH,
     SET_OUTPUT_FILE_FD,
-    SET_OUTPUT_FILE_AUXILIARY_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
     SET_PARAMETERS,
@@ -71,6 +73,19 @@
         return reply.readInt32();
     }
 
+    sp<ISurfaceTexture> querySurfaceMediaSource()
+    {
+        LOGV("Query SurfaceMediaSource");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply);
+        int returnedNull = reply.readInt32();
+        if (returnedNull) {
+            return NULL;
+        }
+        return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
+    }
+
     status_t setPreviewSurface(const sp<Surface>& surface)
     {
         LOGV("setPreviewSurface(%p)", surface.get());
@@ -161,15 +176,6 @@
         return reply.readInt32();
     }
 
-    status_t setOutputFileAuxiliary(int fd) {
-        LOGV("setOutputFileAuxiliary(%d)", fd);
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeFileDescriptor(fd);
-        remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply);
-        return reply.readInt32();
-    }
-
     status_t setVideoSize(int width, int height)
     {
         LOGV("setVideoSize(%dx%d)", width, height);
@@ -388,13 +394,6 @@
             ::close(fd);
             return NO_ERROR;
         } break;
-        case SET_OUTPUT_FILE_AUXILIARY_FD: {
-            LOGV("SET_OUTPUT_FILE_AUXILIARY_FD");
-            CHECK_INTERFACE(IMediaRecorder, data, reply);
-            int fd = dup(data.readFileDescriptor());
-            reply->writeInt32(setOutputFileAuxiliary(fd));
-            return NO_ERROR;
-        } break;
         case SET_VIDEO_SIZE: {
             LOGV("SET_VIDEO_SIZE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
@@ -440,6 +439,20 @@
             reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
+        case QUERY_SURFACE_MEDIASOURCE: {
+            LOGV("QUERY_SURFACE_MEDIASOURCE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            // call the mediaserver side to create
+            // a surfacemediasource
+            sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource();
+            // The mediaserver might have failed to create a source
+            int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
+            reply->writeInt32(returnedNull);
+            if (!returnedNull) {
+                reply->writeStrongBinder(surfaceMediaSource->asBinder());
+            }
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 069bbb7..f0f07a2 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -132,6 +132,16 @@
     LOGV("codec = %d", cap.mCodec);
 }
 
+/*static*/ void
+MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap)
+{
+    LOGV("videoeditor cap:");
+    LOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth);
+    LOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight);
+    LOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth);
+    LOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight);
+}
+
 /*static*/ int
 MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
 {
@@ -368,6 +378,24 @@
     mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
 }
 
+/*static*/ MediaProfiles::VideoEditorCap*
+MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles)
+{
+    CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
+          !strcmp("maxInputFrameHeight", atts[2])  &&
+          !strcmp("maxOutputFrameWidth", atts[4]) &&
+          !strcmp("maxOutputFrameHeight", atts[6]));
+
+    MediaProfiles::VideoEditorCap *pVideoEditorCap =
+        new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
+                atoi(atts[5]), atoi(atts[7]));
+
+    logVideoEditorCap(*pVideoEditorCap);
+    profiles->mVideoEditorCap = pVideoEditorCap;
+
+    return pVideoEditorCap;
+}
+
 /*static*/ void
 MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
 {
@@ -398,6 +426,8 @@
             createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
     } else if (strcmp("ImageEncoding", name) == 0) {
         profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
+    } else if (strcmp("VideoEditorCap", name) == 0) {
+        createVideoEditorCap(atts, profiles);
     }
 }
 
@@ -790,6 +820,17 @@
     profiles->mImageEncodingQualityLevels.add(levels);
 }
 
+/*static*/ void
+MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles)
+{
+    profiles->mVideoEditorCap =
+        new MediaProfiles::VideoEditorCap(
+                VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
+                VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
+                VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
+                VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT);
+}
+
 /*static*/ MediaProfiles*
 MediaProfiles::createDefaultInstance()
 {
@@ -801,6 +842,7 @@
     createDefaultAudioDecoders(profiles);
     createDefaultEncoderOutputFileFormats(profiles);
     createDefaultImageEncodingQualityLevels(profiles);
+    createDefaultVideoEditorCap(profiles);
     return profiles;
 }
 
@@ -899,6 +941,28 @@
     return -1;
 }
 
+int MediaProfiles::getVideoEditorCapParamByName(const char *name) const
+{
+    LOGV("getVideoEditorCapParamByName: %s", name);
+
+    if (mVideoEditorCap == NULL) {
+        LOGE("The mVideoEditorCap is not created, then create default cap.");
+        createDefaultVideoEditorCap(sInstance);
+    }
+
+    if (!strcmp("videoeditor.input.width.max", name))
+        return mVideoEditorCap->mMaxInputFrameWidth;
+    if (!strcmp("videoeditor.input.height.max", name))
+        return mVideoEditorCap->mMaxInputFrameHeight;
+    if (!strcmp("videoeditor.output.width.max", name))
+        return mVideoEditorCap->mMaxOutputFrameWidth;
+    if (!strcmp("videoeditor.output.height.max", name))
+        return mVideoEditorCap->mMaxOutputFrameHeight;
+
+    LOGE("The given video editor param name %s is not found", name);
+    return -1;
+}
+
 Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
 {
     Vector<audio_encoder> encoders;
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 45bdff4..41f8593 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -47,16 +47,15 @@
     return mLocale;
 }
 
-status_t MediaScanner::processDirectory(
-        const char *path, MediaScannerClient &client,
-        ExceptionCheck exceptionCheck, void *exceptionEnv) {
+MediaScanResult MediaScanner::processDirectory(
+        const char *path, MediaScannerClient &client) {
     int pathLength = strlen(path);
     if (pathLength >= PATH_MAX) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
     char* pathBuffer = (char *)malloc(PATH_MAX + 1);
     if (!pathBuffer) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_ERROR;
     }
 
     int pathRemaining = PATH_MAX - pathLength;
@@ -69,21 +68,18 @@
 
     client.setLocale(locale());
 
-    status_t result =
-        doProcessDirectory(pathBuffer, pathRemaining, client, false, exceptionCheck, exceptionEnv);
+    MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false);
 
     free(pathBuffer);
 
     return result;
 }
 
-status_t MediaScanner::doProcessDirectory(
-        char *path, int pathRemaining, MediaScannerClient &client,
-        bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv) {
+MediaScanResult MediaScanner::doProcessDirectory(
+        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
     // place to copy file or directory name
     char* fileSpot = path + strlen(path);
     struct dirent* entry;
-    struct stat statbuf;
 
     // Treat all files as non-media in directories that contain a  ".nomedia" file
     if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
@@ -99,76 +95,88 @@
 
     DIR* dir = opendir(path);
     if (!dir) {
-        LOGD("opendir %s failed, errno: %d", path, errno);
-        return UNKNOWN_ERROR;
+        LOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno));
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
+    MediaScanResult result = MEDIA_SCAN_RESULT_OK;
     while ((entry = readdir(dir))) {
-        const char* name = entry->d_name;
-
-        // ignore "." and ".."
-        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
-            continue;
+        if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
+                == MEDIA_SCAN_RESULT_ERROR) {
+            result = MEDIA_SCAN_RESULT_ERROR;
+            break;
         }
+    }
+    closedir(dir);
+    return result;
+}
 
-        int nameLength = strlen(name);
-        if (nameLength + 1 > pathRemaining) {
-            // path too long!
-            continue;
+MediaScanResult MediaScanner::doProcessDirectoryEntry(
+        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+        struct dirent* entry, char* fileSpot) {
+    struct stat statbuf;
+    const char* name = entry->d_name;
+
+    // ignore "." and ".."
+    if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+        return MEDIA_SCAN_RESULT_SKIPPED;
+    }
+
+    int nameLength = strlen(name);
+    if (nameLength + 1 > pathRemaining) {
+        // path too long!
+        return MEDIA_SCAN_RESULT_SKIPPED;
+    }
+    strcpy(fileSpot, name);
+
+    int type = entry->d_type;
+    if (type == DT_UNKNOWN) {
+        // If the type is unknown, stat() the file instead.
+        // This is sometimes necessary when accessing NFS mounted filesystems, but
+        // could be needed in other cases well.
+        if (stat(path, &statbuf) == 0) {
+            if (S_ISREG(statbuf.st_mode)) {
+                type = DT_REG;
+            } else if (S_ISDIR(statbuf.st_mode)) {
+                type = DT_DIR;
+            }
+        } else {
+            LOGD("stat() failed for %s: %s", path, strerror(errno) );
         }
-        strcpy(fileSpot, name);
+    }
+    if (type == DT_DIR) {
+        bool childNoMedia = noMedia;
+        // set noMedia flag on directories with a name that starts with '.'
+        // for example, the Mac ".Trashes" directory
+        if (name[0] == '.')
+            childNoMedia = true;
 
-        int type = entry->d_type;
-        if (type == DT_UNKNOWN) {
-            // If the type is unknown, stat() the file instead.
-            // This is sometimes necessary when accessing NFS mounted filesystems, but
-            // could be needed in other cases well.
-            if (stat(path, &statbuf) == 0) {
-                if (S_ISREG(statbuf.st_mode)) {
-                    type = DT_REG;
-                } else if (S_ISDIR(statbuf.st_mode)) {
-                    type = DT_DIR;
-                }
-            } else {
-                LOGD("stat() failed for %s: %s", path, strerror(errno) );
+        // report the directory to the client
+        if (stat(path, &statbuf) == 0) {
+            status_t status = client.scanFile(path, statbuf.st_mtime, 0,
+                    true /*isDirectory*/, childNoMedia);
+            if (status) {
+                return MEDIA_SCAN_RESULT_ERROR;
             }
         }
-        if (type == DT_REG || type == DT_DIR) {
-            if (type == DT_DIR) {
-                bool childNoMedia = noMedia;
-                // set noMedia flag on directories with a name that starts with '.'
-                // for example, the Mac ".Trashes" directory
-                if (name[0] == '.')
-                    childNoMedia = true;
 
-                // report the directory to the client
-                if (stat(path, &statbuf) == 0) {
-                    client.scanFile(path, statbuf.st_mtime, 0, true, childNoMedia);
-                }
-
-                // and now process its contents
-                strcat(fileSpot, "/");
-                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
-                        childNoMedia, exceptionCheck, exceptionEnv);
-                if (err) {
-                    // pass exceptions up - ignore other errors
-                    if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
-                    LOGE("Error processing '%s' - skipping\n", path);
-                    continue;
-                }
-            } else {
-                stat(path, &statbuf);
-                client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false, noMedia);
-                if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
-            }
+        // and now process its contents
+        strcat(fileSpot, "/");
+        MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
+                client, childNoMedia);
+        if (result == MEDIA_SCAN_RESULT_ERROR) {
+            return MEDIA_SCAN_RESULT_ERROR;
+        }
+    } else if (type == DT_REG) {
+        stat(path, &statbuf);
+        status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
+                false /*isDirectory*/, noMedia);
+        if (status) {
+            return MEDIA_SCAN_RESULT_ERROR;
         }
     }
 
-    closedir(dir);
-    return OK;
-failure:
-    closedir(dir);
-    return -1;
+    return MEDIA_SCAN_RESULT_OK;
 }
 
 }  // namespace android
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index bd3596e..7a7aeb6 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -62,7 +62,7 @@
     mValues = new StringArray;
 }
 
-bool MediaScannerClient::addStringTag(const char* name, const char* value)
+status_t MediaScannerClient::addStringTag(const char* name, const char* value)
 {
     if (mLocaleEncoding != kEncodingNone) {
         // don't bother caching strings that are all ASCII.
@@ -212,8 +212,10 @@
 
         // finally, push all name/value pairs to the client
         for (int i = 0; i < mNames->size(); i++) {
-            if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
+            status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
+            if (status) {
                 break;
+            }
         }
     }
     // else addStringTag() has done all the work so we have nothing to do
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 7b7ba74..a11fb80 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -27,6 +27,8 @@
 #include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 
+#include <gui/SurfaceTextureClient.h>
+
 #include <media/mediaplayer.h>
 #include <media/AudioTrack.h>
 
@@ -38,6 +40,7 @@
 #include <utils/String8.h>
 
 #include <system/audio.h>
+#include <system/window.h>
 
 namespace android {
 
@@ -81,6 +84,8 @@
     if (p != 0) {
         p->disconnect();
     }
+
+    disconnectNativeWindow();
 }
 
 // always call with lock held
@@ -194,13 +199,63 @@
     return mPlayer->getMetadata(update_only, apply_filter, metadata);
 }
 
+void MediaPlayer::disconnectNativeWindow() {
+    if (mConnectedWindow != NULL) {
+        status_t err = native_window_disconnect(mConnectedWindow.get(),
+                NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            LOGW("native_window_disconnect returned an error: %s (%d)",
+                    strerror(-err), err);
+        }
+    }
+    mConnectedWindow.clear();
+}
+
 status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
 {
     LOGV("setVideoSurface");
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return NO_INIT;
 
-    return mPlayer->setVideoSurface(surface);
+    sp<IBinder> binder(surface == NULL ? NULL : surface->asBinder());
+    if (mConnectedWindowBinder == binder) {
+        return OK;
+    }
+
+    if (surface != NULL) {
+        status_t err = native_window_connect(surface.get(),
+                NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            LOGE("setVideoSurface failed: %d", err);
+            // Note that we must do the reset before disconnecting from the ANW.
+            // Otherwise queue/dequeue calls could be made on the disconnected
+            // ANW, which may result in errors.
+            reset_l();
+
+            disconnectNativeWindow();
+
+            return err;
+        }
+    }
+
+    // Note that we must set the player's new surface before disconnecting the
+    // old one.  Otherwise queue/dequeue calls could be made on the disconnected
+    // ANW, which may result in errors.
+    status_t err = mPlayer->setVideoSurface(surface);
+
+    disconnectNativeWindow();
+
+    mConnectedWindow = surface;
+
+    if (err == OK) {
+        mConnectedWindowBinder = binder;
+    } else {
+        disconnectNativeWindow();
+    }
+
+    return err;
 }
 
 status_t MediaPlayer::setVideoSurfaceTexture(
@@ -210,7 +265,47 @@
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return NO_INIT;
 
-    return mPlayer->setVideoSurfaceTexture(surfaceTexture);
+    sp<IBinder> binder(surfaceTexture == NULL ? NULL :
+            surfaceTexture->asBinder());
+    if (mConnectedWindowBinder == binder) {
+        return OK;
+    }
+
+    sp<ANativeWindow> anw;
+    if (surfaceTexture != NULL) {
+        anw = new SurfaceTextureClient(surfaceTexture);
+        status_t err = native_window_connect(anw.get(),
+                NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            LOGE("setVideoSurfaceTexture failed: %d", err);
+            // Note that we must do the reset before disconnecting from the ANW.
+            // Otherwise queue/dequeue calls could be made on the disconnected
+            // ANW, which may result in errors.
+            reset_l();
+
+            disconnectNativeWindow();
+
+            return err;
+        }
+    }
+
+    // Note that we must set the player's new SurfaceTexture before
+    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
+    // on the disconnected ANW, which may result in errors.
+    status_t err = mPlayer->setVideoSurfaceTexture(surfaceTexture);
+
+    disconnectNativeWindow();
+
+    mConnectedWindow = anw;
+
+    if (err == OK) {
+        mConnectedWindowBinder = binder;
+    } else {
+        disconnectNativeWindow();
+    }
+
+    return err;
 }
 
 // must call with lock held
@@ -434,10 +529,8 @@
     return result;
 }
 
-status_t MediaPlayer::reset()
+status_t MediaPlayer::reset_l()
 {
-    LOGV("reset");
-    Mutex::Autolock _l(mLock);
     mLoop = false;
     if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
     mPrepareSync = false;
@@ -458,6 +551,13 @@
     return NO_ERROR;
 }
 
+status_t MediaPlayer::reset()
+{
+    LOGV("reset");
+    Mutex::Autolock _l(mLock);
+    return reset_l();
+}
+
 status_t MediaPlayer::setAudioStreamType(int type)
 {
     LOGV("MediaPlayer::setAudioStreamType");
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 9e4edd0..11d281f 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -25,6 +25,7 @@
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 #include <media/mediaplayer.h>  // for MEDIA_ERROR_SERVER_DIED
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -127,7 +128,9 @@
         return INVALID_OPERATION;
     }
 
+    // following call is made over the Binder Interface
     status_t ret = mMediaRecorder->setVideoSource(vs);
+
     if (OK != ret) {
         LOGV("setVideoSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
@@ -319,32 +322,6 @@
     return ret;
 }
 
-status_t MediaRecorder::setOutputFileAuxiliary(int fd)
-{
-    LOGV("setOutputFileAuxiliary(%d)", fd);
-    if(mMediaRecorder == NULL) {
-        LOGE("media recorder is not initialized yet");
-        return INVALID_OPERATION;
-    }
-    if (mIsAuxiliaryOutputFileSet) {
-        LOGE("output file has already been set");
-        return INVALID_OPERATION;
-    }
-    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
-        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
-        return INVALID_OPERATION;
-    }
-
-    status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd);
-    if (OK != ret) {
-        LOGV("setOutputFileAuxiliary failed: %d", ret);
-        mCurrentState = MEDIA_RECORDER_ERROR;
-        return ret;
-    }
-    mIsAuxiliaryOutputFileSet = true;
-    return ret;
-}
-
 status_t MediaRecorder::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%d, %d)", width, height);
@@ -357,7 +334,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video size without setting video source first");
+        LOGE("Cannot set video size without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -367,9 +344,27 @@
         mCurrentState = MEDIA_RECORDER_ERROR;
         return ret;
     }
+
     return ret;
 }
 
+// Query a SurfaceMediaSurface through the Mediaserver, over the
+// binder interface. This is used by the Filter Framework (MeidaEncoder)
+// to get an <ISurfaceTexture> object to hook up to ANativeWindow.
+sp<ISurfaceTexture> MediaRecorder::
+        querySurfaceMediaSourceFromMediaServer()
+{
+    Mutex::Autolock _l(mLock);
+    mSurfaceMediaSource =
+            mMediaRecorder->querySurfaceMediaSource();
+    if (mSurfaceMediaSource == NULL) {
+        LOGE("SurfaceMediaSource could not be initialized!");
+    }
+    return mSurfaceMediaSource;
+}
+
+
+
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
 {
     LOGV("setVideoFrameRate(%d)", frames_per_second);
@@ -382,7 +377,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video frame rate without setting video source first");
+        LOGE("Cannot set video frame rate without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -608,7 +603,6 @@
     mIsAudioEncoderSet = false;
     mIsVideoEncoderSet = false;
     mIsOutputFileSet   = false;
-    mIsAuxiliaryOutputFileSet = false;
 }
 
 // Release should be OK in any state
@@ -621,7 +615,7 @@
     return INVALID_OPERATION;
 }
 
-MediaRecorder::MediaRecorder()
+MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL)
 {
     LOGV("constructor");
 
@@ -632,6 +626,8 @@
     if (mMediaRecorder != NULL) {
         mCurrentState = MEDIA_RECORDER_IDLE;
     }
+
+
     doCleanUp();
 }
 
@@ -646,6 +642,10 @@
     if (mMediaRecorder != NULL) {
         mMediaRecorder.clear();
     }
+
+    if (mSurfaceMediaSource != NULL) {
+        mSurfaceMediaSource.clear();
+    }
 }
 
 status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 115db1a..6f80b35 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -41,6 +41,7 @@
 #include "MediaPlayerService.h"
 
 #include "StagefrightRecorder.h"
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -57,6 +58,20 @@
     return ok;
 }
 
+
+sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource()
+{
+    LOGV("Query SurfaceMediaSource");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NULL;
+    }
+    return mRecorder->querySurfaceMediaSource();
+}
+
+
+
 status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
                                         const sp<ICameraRecordingProxy>& proxy)
 {
@@ -163,17 +178,6 @@
     return mRecorder->setOutputFile(fd, offset, length);
 }
 
-status_t MediaRecorderClient::setOutputFileAuxiliary(int fd)
-{
-    LOGV("setOutputFileAuxiliary(%d)", fd);
-    Mutex::Autolock lock(mLock);
-    if (mRecorder == NULL) {
-        LOGE("recorder is not initialized");
-        return NO_INIT;
-    }
-    return mRecorder->setOutputFileAuxiliary(fd);
-}
-
 status_t MediaRecorderClient::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%dx%d)", width, height);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index bbca529..c9ccf22 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,45 +25,50 @@
 class MediaRecorderBase;
 class MediaPlayerService;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    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);
-    virtual     status_t        setOutputFormat(int of);
-    virtual     status_t        setVideoEncoder(int ve);
-    virtual     status_t        setAudioEncoder(int ae);
-    virtual     status_t        setOutputFile(const char* path);
-    virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
-    virtual     status_t        setOutputFileAuxiliary(int fd);
-    virtual     status_t        setVideoSize(int width, int height);
-    virtual     status_t        setVideoFrameRate(int frames_per_second);
-    virtual     status_t        setParameters(const String8& params);
-    virtual     status_t        setListener(const sp<IMediaRecorderClient>& listener);
-    virtual     status_t        prepare();
-    virtual     status_t        getMaxAmplitude(int* max);
-    virtual     status_t        start();
-    virtual     status_t        stop();
-    virtual     status_t        reset();
-    virtual     status_t        init();
-    virtual     status_t        close();
-    virtual     status_t        release();
+    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);
+    virtual     status_t   setOutputFormat(int of);
+    virtual     status_t   setVideoEncoder(int ve);
+    virtual     status_t   setAudioEncoder(int ae);
+    virtual     status_t   setOutputFile(const char* path);
+    virtual     status_t   setOutputFile(int fd, int64_t offset,
+                                                  int64_t length);
+    virtual     status_t   setVideoSize(int width, int height);
+    virtual     status_t   setVideoFrameRate(int frames_per_second);
+    virtual     status_t   setParameters(const String8& params);
+    virtual     status_t   setListener(
+                              const sp<IMediaRecorderClient>& listener);
+    virtual     status_t   prepare();
+    virtual     status_t   getMaxAmplitude(int* max);
+    virtual     status_t   start();
+    virtual     status_t   stop();
+    virtual     status_t   reset();
+    virtual     status_t   init();
+    virtual     status_t   close();
+    virtual     status_t   release();
+    virtual     status_t   dump(int fd, const Vector<String16>& args) const;
+    virtual     sp<ISurfaceTexture> querySurfaceMediaSource();
 
-    virtual     status_t        dump(int fd, const Vector<String16>& args) const;
 private:
-    friend class                MediaPlayerService;  // for accessing private constructor
+    friend class           MediaPlayerService;  // for accessing private constructor
 
-                                MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
-    virtual                     ~MediaRecorderClient();
+                           MediaRecorderClient(
+                                   const sp<MediaPlayerService>& service,
+                                                               pid_t pid);
+    virtual                ~MediaRecorderClient();
 
-    pid_t                       mPid;
-    Mutex                       mLock;
-    MediaRecorderBase           *mRecorder;
-    sp<MediaPlayerService>      mMediaPlayerService;
+    pid_t                  mPid;
+    Mutex                  mLock;
+    MediaRecorderBase      *mRecorder;
+    sp<MediaPlayerService> mMediaPlayerService;
 };
 
 }; // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 223e0be..6fdb726 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -28,9 +28,7 @@
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AACWriter.h>
 #include <media/stagefright/CameraSource.h>
-#include <media/stagefright/VideoSourceDownSampler.h>
 #include <media/stagefright/CameraSourceTimeLapse.h>
-#include <media/stagefright/MediaSourceSplitter.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaDebug.h>
@@ -38,10 +36,12 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SurfaceMediaSource.h>
 #include <media/MediaProfiles.h>
 #include <camera/ICamera.h>
 #include <camera/CameraParameters.h>
 #include <surfaceflinger/Surface.h>
+
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
@@ -65,11 +65,11 @@
 
 
 StagefrightRecorder::StagefrightRecorder()
-    : mWriter(NULL), mWriterAux(NULL),
-      mOutputFd(-1), mOutputFdAux(-1),
+    : mWriter(NULL),
+      mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false) {
+      mStarted(false), mSurfaceMediaSource(NULL) {
 
     LOGV("Constructor");
     reset();
@@ -85,6 +85,14 @@
     return OK;
 }
 
+// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// and return a interface reference. The client side will use that
+// while encoding GL Frames
+sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const {
+    LOGV("Get SurfaceMediaSource");
+    return mSurfaceMediaSource;
+}
+
 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
     LOGV("setAudioSource: %d", as);
     if (as < AUDIO_SOURCE_DEFAULT ||
@@ -249,24 +257,6 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) {
-    LOGV("setOutputFileAuxiliary: %d", fd);
-
-    if (fd < 0) {
-        LOGE("Invalid file descriptor: %d", fd);
-        return -EBADF;
-    }
-
-    mCaptureAuxVideo = true;
-
-    if (mOutputFdAux >= 0) {
-        ::close(mOutputFdAux);
-    }
-    mOutputFdAux = dup(fd);
-
-    return OK;
-}
-
 // Attempt to parse an int64 literal optionally surrounded by whitespace,
 // returns true on success, false otherwise.
 static bool safe_strtoi64(const char *s, int64_t *val) {
@@ -563,42 +553,6 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) {
-    LOGV("setParamAuxVideoWidth : %d", width);
-
-    if (width <= 0) {
-        LOGE("Width (%d) is not positive", width);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoWidth = width;
-    return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) {
-    LOGV("setParamAuxVideoHeight : %d", height);
-
-    if (height <= 0) {
-        LOGE("Height (%d) is not positive", height);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoHeight = height;
-    return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) {
-    LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate);
-
-    if (bitRate <= 0) {
-        LOGE("Invalid video encoding bit rate: %d", bitRate);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoBitRate = bitRate;
-    return OK;
-}
-
 status_t StagefrightRecorder::setParamGeoDataLongitude(
     int32_t longitudex10000) {
 
@@ -728,21 +682,6 @@
             return setParamTimeBetweenTimeLapseFrameCapture(
                     1000LL * timeBetweenTimeLapseFrameCaptureMs);
         }
-    } else if (key == "video-aux-param-width") {
-        int32_t auxWidth;
-        if (safe_strtoi32(value.string(), &auxWidth)) {
-            return setParamAuxVideoWidth(auxWidth);
-        }
-    } else if (key == "video-aux-param-height") {
-        int32_t auxHeight;
-        if (safe_strtoi32(value.string(), &auxHeight)) {
-            return setParamAuxVideoHeight(auxHeight);
-        }
-    } else if (key == "video-aux-param-encoding-bitrate") {
-        int32_t auxVideoBitRate;
-        if (safe_strtoi32(value.string(), &auxVideoBitRate)) {
-            return setParamAuxVideoEncodingBitRate(auxVideoBitRate);
-        }
     } else {
         LOGE("setParameter: failed to find key %s", key.string());
     }
@@ -1006,13 +945,13 @@
         source = createAudioSource();
     } else {
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &source);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &source);
         if (err != OK) {
             return err;
         }
@@ -1042,20 +981,19 @@
         }
     }
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
         if (mVideoEncoder != VIDEO_ENCODER_H264) {
             return ERROR_UNSUPPORTED;
         }
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
 
         if (err != OK) {
             return err;
@@ -1289,6 +1227,60 @@
     }
 }
 
+// Set up the appropriate MediaSource depending on the chosen option
+status_t StagefrightRecorder::setupMediaSource(
+                      sp<MediaSource> *mediaSource) {
+    if (mVideoSource == VIDEO_SOURCE_DEFAULT
+            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+        sp<CameraSource> cameraSource;
+        status_t err = setupCameraSource(&cameraSource);
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = cameraSource;
+    } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+        // If using GRAlloc buffers, setup surfacemediasource.
+        // Later a handle to that will be passed
+        // to the client side when queried
+        status_t err = setupSurfaceMediaSource();
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = mSurfaceMediaSource;
+    } else {
+        return INVALID_OPERATION;
+    }
+    return OK;
+}
+
+// setupSurfaceMediaSource creates a source with the given
+// width and height and framerate.
+// TODO: This could go in a static function inside SurfaceMediaSource
+// similar to that in CameraSource
+status_t StagefrightRecorder::setupSurfaceMediaSource() {
+    status_t err = OK;
+    mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight);
+    if (mSurfaceMediaSource == NULL) {
+        return NO_INIT;
+    }
+
+    if (mFrameRate == -1) {
+        int32_t frameRate = 0;
+        CHECK (mSurfaceMediaSource->getFormat()->findInt32(
+                                        kKeyFrameRate, &frameRate));
+        LOGI("Frame rate is not explicitly set. Use the current frame "
+             "rate (%d fps)", frameRate);
+        mFrameRate = frameRate;
+    } else {
+        err = mSurfaceMediaSource->setFrameRate(mFrameRate);
+    }
+    CHECK(mFrameRate != -1);
+
+    mIsMetaDataStoredInVideoBuffers =
+        mSurfaceMediaSource->isMetaDataStoredInVideoBuffers();
+    return err;
+}
+
 status_t StagefrightRecorder::setupCameraSource(
         sp<CameraSource> *cameraSource) {
     status_t err = OK;
@@ -1454,7 +1446,6 @@
 }
 
 status_t StagefrightRecorder::setupMPEG4Recording(
-        bool useSplitCameraSource,
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
@@ -1465,29 +1456,16 @@
     status_t err = OK;
     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
 
-        sp<MediaSource> cameraMediaSource;
-        if (useSplitCameraSource) {
-            LOGV("Using Split camera source");
-            cameraMediaSource = mCameraSourceSplitter->createClient();
-        } else {
-            sp<CameraSource> cameraSource;
-            err = setupCameraSource(&cameraSource);
-            cameraMediaSource = cameraSource;
-        }
-        if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) {
-            // Use downsampling from the original source.
-            cameraMediaSource =
-                new VideoSourceDownSampler(cameraMediaSource, videoWidth, videoHeight);
-        }
+        sp<MediaSource> mediaSource;
+        err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraMediaSource, videoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
         if (err != OK) {
             return err;
         }
@@ -1549,24 +1527,8 @@
 }
 
 status_t StagefrightRecorder::startMPEG4Recording() {
-    if (mCaptureAuxVideo) {
-        if (!mCaptureTimeLapse) {
-            LOGE("Auxiliary video can be captured only in time lapse mode");
-            return UNKNOWN_ERROR;
-        }
-        LOGV("Creating MediaSourceSplitter");
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
-        if (err != OK) {
-            return err;
-        }
-        mCameraSourceSplitter = new MediaSourceSplitter(cameraSource);
-    } else {
-        mCameraSourceSplitter = NULL;
-    }
-
     int32_t totalBitRate;
-    status_t err = setupMPEG4Recording(mCaptureAuxVideo,
+    status_t err = setupMPEG4Recording(
             mOutputFd, mVideoWidth, mVideoHeight,
             mVideoBitRate, &totalBitRate, &mWriter);
     if (err != OK) {
@@ -1582,33 +1544,6 @@
         return err;
     }
 
-    if (mCaptureAuxVideo) {
-        CHECK(mOutputFdAux >= 0);
-        if (mWriterAux != NULL) {
-            LOGE("Auxiliary File writer is not avaialble");
-            return UNKNOWN_ERROR;
-        }
-        if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) ||
-                ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) {
-            LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)",
-                    mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight);
-            return UNKNOWN_ERROR;
-        }
-
-        int32_t totalBitrateAux;
-        err = setupMPEG4Recording(mCaptureAuxVideo,
-                mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight,
-                mAuxVideoBitRate, &totalBitrateAux, &mWriterAux);
-        if (err != OK) {
-            return err;
-        }
-
-        sp<MetaData> metaAux = new MetaData;
-        setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux);
-
-        return mWriterAux->start(metaAux.get());
-    }
-
     return OK;
 }
 
@@ -1619,13 +1554,6 @@
     }
     mWriter->pause();
 
-    if (mCaptureAuxVideo) {
-        if (mWriterAux == NULL) {
-            return UNKNOWN_ERROR;
-        }
-        mWriterAux->pause();
-    }
-
     if (mStarted) {
         mStarted = false;
 
@@ -1653,13 +1581,6 @@
         mCameraSourceTimeLapse = NULL;
     }
 
-    if (mCaptureAuxVideo) {
-        if (mWriterAux != NULL) {
-            mWriterAux->stop();
-            mWriterAux.clear();
-        }
-    }
-
     if (mWriter != NULL) {
         err = mWriter->stop();
         mWriter.clear();
@@ -1670,13 +1591,6 @@
         mOutputFd = -1;
     }
 
-    if (mCaptureAuxVideo) {
-        if (mOutputFdAux >= 0) {
-            ::close(mOutputFdAux);
-            mOutputFdAux = -1;
-        }
-    }
-
     if (mStarted) {
         mStarted = false;
 
@@ -1716,11 +1630,8 @@
     mVideoEncoder  = VIDEO_ENCODER_H263;
     mVideoWidth    = 176;
     mVideoHeight   = 144;
-    mAuxVideoWidth    = 176;
-    mAuxVideoHeight   = 144;
     mFrameRate     = -1;
     mVideoBitRate  = 192000;
-    mAuxVideoBitRate = 192000;
     mSampleRate    = 8000;
     mAudioChannels = 1;
     mAudioBitRate  = 12200;
@@ -1740,8 +1651,6 @@
     mTrackEveryTimeDurationUs = 0;
     mCaptureTimeLapse = false;
     mTimeBetweenTimeLapseFrameCaptureUs = -1;
-    mCaptureAuxVideo = false;
-    mCameraSourceSplitter = NULL;
     mCameraSourceTimeLapse = NULL;
     mIsMetaDataStoredInVideoBuffers = false;
     mEncoderProfiles = MediaProfiles::getInstance();
@@ -1750,7 +1659,6 @@
     mLongitudex10000 = -3600000;
 
     mOutputFd = -1;
-    mOutputFdAux = -1;
 
     return OK;
 }
@@ -1787,8 +1695,6 @@
     snprintf(buffer, SIZE, "   Recorder: %p\n", this);
     snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
     result.append(buffer);
-    snprintf(buffer, SIZE, "   Output file Auxiliary (fd %d):\n", mOutputFdAux);
-    result.append(buffer);
     snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
     result.append(buffer);
     snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
@@ -1833,14 +1739,10 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
     result.append(buffer);
-    snprintf(buffer, SIZE, "     Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight);
-    result.append(buffer);
     snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
     result.append(buffer);
     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
     result.append(buffer);
-    snprintf(buffer, SIZE, "     Aux Bit rate (bps): %d\n", mAuxVideoBitRate);
-    result.append(buffer);
     ::write(fd, result.string(), result.size());
     return OK;
 }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 034b373..5c5f05c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -30,12 +30,13 @@
 class ICameraRecordingProxy;
 class CameraSource;
 class CameraSourceTimeLapse;
-class MediaSourceSplitter;
 struct MediaSource;
 struct MediaWriter;
 class MetaData;
 struct AudioSource;
 class MediaProfiles;
+class ISurfaceTexture;
+class SurfaceMediaSource;
 
 struct StagefrightRecorder : public MediaRecorderBase {
     StagefrightRecorder();
@@ -53,7 +54,6 @@
     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);
-    virtual status_t setOutputFileAuxiliary(int fd);
     virtual status_t setParameters(const String8& params);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
@@ -64,14 +64,16 @@
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
     virtual status_t dump(int fd, const Vector<String16>& args) const;
+    // Querying a SurfaceMediaSourcer
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() const;
 
 private:
     sp<ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<Surface> mPreviewSurface;
     sp<IMediaRecorderClient> mListener;
-    sp<MediaWriter> mWriter, mWriterAux;
-    int mOutputFd, mOutputFdAux;
+    sp<MediaWriter> mWriter;
+    int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
     audio_source_t mAudioSource;
@@ -81,9 +83,8 @@
     video_encoder mVideoEncoder;
     bool mUse64BitFileOffset;
     int32_t mVideoWidth, mVideoHeight;
-    int32_t mAuxVideoWidth, mAuxVideoHeight;
     int32_t mFrameRate;
-    int32_t mVideoBitRate, mAuxVideoBitRate;
+    int32_t mVideoBitRate;
     int32_t mAudioBitRate;
     int32_t mAudioChannels;
     int32_t mSampleRate;
@@ -105,19 +106,22 @@
 
     bool mCaptureTimeLapse;
     int64_t mTimeBetweenTimeLapseFrameCaptureUs;
-    bool mCaptureAuxVideo;
-    sp<MediaSourceSplitter> mCameraSourceSplitter;
     sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
 
+
     String8 mParams;
 
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     bool mStarted;
+    // Needed when GLFrames are encoded.
+    // An <ISurfaceTexture> pointer
+    // will be sent to the client side using which the
+    // frame buffers will be queued and dequeued
+    sp<SurfaceMediaSource> mSurfaceMediaSource;
 
     status_t setupMPEG4Recording(
-        bool useSplitCameraSource,
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
@@ -134,7 +138,14 @@
     sp<MediaSource> createAudioSource();
     status_t checkVideoEncoderCapabilities();
     status_t checkAudioEncoderCapabilities();
+    // Generic MediaSource set-up. Returns the appropriate
+    // source (CameraSource or SurfaceMediaSource)
+    // depending on the videosource type
+    status_t setupMediaSource(sp<MediaSource> *mediaSource);
     status_t setupCameraSource(sp<CameraSource> *cameraSource);
+    // setup the surfacemediasource for the encoder
+    status_t setupSurfaceMediaSource();
+
     status_t setupAudioEncoder(const sp<MediaWriter>& writer);
     status_t setupVideoEncoder(
             sp<MediaSource> cameraSource,
@@ -149,9 +160,6 @@
     status_t setParamAudioTimeScale(int32_t timeScale);
     status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
     status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
-    status_t setParamAuxVideoHeight(int32_t height);
-    status_t setParamAuxVideoWidth(int32_t width);
-    status_t setParamAuxVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoIFramesInterval(int32_t seconds);
     status_t setParamVideoEncoderProfile(int32_t profile);
@@ -176,6 +184,7 @@
     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 5a5330d..0251baf 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -58,8 +58,10 @@
 }
 
 NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
-    mLiveSession->disconnect();
-    mLiveLooper->stop();
+    if (mLiveSession != NULL) {
+        mLiveSession->disconnect();
+        mLiveLooper->stop();
+    }
 }
 
 void NuPlayer::HTTPLiveSource::start() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7cd8b6c..c6fca2c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -118,9 +118,15 @@
             mPlayer->start();
 
             if (mStartupSeekTimeUs >= 0) {
-                mPlayer->seekToAsync(mStartupSeekTimeUs);
+                if (mStartupSeekTimeUs == 0) {
+                    notifySeekComplete();
+                } else {
+                    mPlayer->seekToAsync(mStartupSeekTimeUs);
+                }
+
                 mStartupSeekTimeUs = -1;
             }
+
             break;
         }
         case PLAYING:
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d4d07b2..174ec92 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -445,6 +445,13 @@
         return err;
     }
 
+    err = native_window_set_scaling_mode(mNativeWindow.get(),
+            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+    if (err != OK) {
+        return err;
+    }
+
     err = native_window_set_buffers_geometry(
             mNativeWindow.get(),
             def.format.video.nFrameWidth,
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 7b3b95b..3a3c082 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -3,8 +3,6 @@
 
 include frameworks/base/media/libstagefright/codecs/common/Config.mk
 
-BUILD_WITH_SOFTWARE_DECODERS := false
-
 LOCAL_SRC_FILES:=                         \
         ACodec.cpp                        \
         AACExtractor.cpp                  \
@@ -24,7 +22,6 @@
         FileSource.cpp                    \
         FLACExtractor.cpp                 \
         HTTPBase.cpp                      \
-        HTTPStream.cpp                    \
         JPEGSource.cpp                    \
         MP3Extractor.cpp                  \
         MPEG2TSWriter.cpp                 \
@@ -38,15 +35,14 @@
         MediaSourceSplitter.cpp           \
         MetaData.cpp                      \
         NuCachedSource2.cpp               \
-        NuHTTPDataSource.cpp              \
         OMXClient.cpp                     \
         OMXCodec.cpp                      \
         OggExtractor.cpp                  \
         SampleIterator.cpp                \
         SampleTable.cpp                   \
-        ShoutcastSource.cpp               \
         StagefrightMediaScanner.cpp       \
         StagefrightMetadataRetriever.cpp  \
+        SurfaceMediaSource.cpp            \
         ThrottledSource.cpp               \
         TimeSource.cpp                    \
         TimedEventQueue.cpp               \
@@ -96,26 +92,6 @@
         libstagefright_id3 \
         libFLAC \
 
-ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)
-
-LOCAL_SRC_FILES += \
-        ThreadedSource.cpp                \
-
-LOCAL_STATIC_LIBRARIES += \
-        libstagefright_aacdec \
-        libstagefright_amrnbdec \
-        libstagefright_amrwbdec \
-        libstagefright_avcdec \
-        libstagefright_g711dec \
-        libstagefright_mp3dec \
-        libstagefright_m4vh263dec \
-        libstagefright_vorbisdec \
-        libstagefright_vpxdec \
-        libvpx \
-
-endif
-
-
 ################################################################################
 
 # The following was shamelessly copied from external/webkit/Android.mk and
@@ -177,10 +153,6 @@
 
 LOCAL_CFLAGS += -Wno-multichar
 
-ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)
-    LOCAL_CFLAGS += -DHAVE_SOFTWARE_DECODERS
-endif
-
 LOCAL_MODULE:= libstagefright
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 77c25d1..67f6c79 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -453,7 +453,6 @@
 }
 
 void AwesomePlayer::reset() {
-    LOGI("reset");
     Mutex::Autolock autoLock(mLock);
     reset_l();
 }
@@ -467,10 +466,8 @@
                     Playback::STOP, 0);
             mDecryptHandle = NULL;
             mDrmManagerClient = NULL;
-            LOGI("DRM manager client stopped");
     }
 
-
     if (mFlags & PLAYING) {
         uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
         if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
@@ -503,7 +500,6 @@
         mPreparedCondition.wait(mLock);
     }
 
-    LOGI("cancel player events");
     cancelPlayerEvents();
 
     mWVMExtractor.clear();
@@ -890,7 +886,11 @@
         CHECK(!(mFlags & AUDIO_RUNNING));
 
         if (mVideoSource == NULL) {
-            status_t err = startAudioPlayer_l();
+            // We don't want to post an error notification at this point,
+            // the error returned from MediaPlayer::start() will suffice.
+
+            status_t err = startAudioPlayer_l(
+                    false /* sendErrorNotification */);
 
             if (err != OK) {
                 delete mAudioPlayer;
@@ -940,7 +940,7 @@
     return OK;
 }
 
-status_t AwesomePlayer::startAudioPlayer_l() {
+status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
     CHECK(!(mFlags & AUDIO_RUNNING));
 
     if (mAudioSource == NULL || mAudioPlayer == NULL) {
@@ -958,7 +958,10 @@
                 true /* sourceAlreadyStarted */);
 
         if (err != OK) {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+            if (sendErrorNotification) {
+                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+            }
+
             return err;
         }
 
@@ -1684,7 +1687,7 @@
     if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
         status_t err = startAudioPlayer_l();
         if (err != OK) {
-            LOGE("Startung the audio player failed w/ err %d", err);
+            LOGE("Starting the audio player failed w/ err %d", err);
             return;
         }
     }
@@ -2235,7 +2238,22 @@
 }
 
 status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
-    return OK;
+    switch (key) {
+    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
+        {
+            int32_t channelCount;
+            if (mAudioTrack == 0 ||
+                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
+                channelCount = 0;
+            }
+            reply->writeInt32(channelCount);
+        }
+        return OK;
+    default:
+        {
+            return ERROR_UNSUPPORTED;
+        }
+    }
 }
 
 bool AwesomePlayer::isStreamingHTTP() const {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 1bc2fb9..de66d99 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -179,9 +179,6 @@
     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
@@ -192,12 +189,12 @@
         if (mCamera == 0) return -EBUSY;
         mCameraRecordingProxy = proxy;
         mCameraFlags |= FLAGS_HOT_CAMERA;
+        mDeathNotifier = new DeathNotifier();
+        // isBinderAlive needs linkToDeath to work.
+        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
     }
 
     mCamera->lock();
-    mDeathNotifier = new DeathNotifier();
-    // isBinderAlive needs linkToDeath to work.
-    mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
 
     return OK;
 }
@@ -292,7 +289,7 @@
         CameraParameters* params,
         int32_t width, int32_t height,
         int32_t frameRate) {
-
+    LOGV("configureCamera");
     Vector<Size> sizes;
     bool isSetVideoSizeSupportedByCamera = true;
     getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
@@ -368,6 +365,7 @@
         const CameraParameters& params,
         int32_t width, int32_t height) {
 
+    LOGV("checkVideoSize");
     // The actual video size is the same as the preview size
     // if the camera hal does not support separate video and
     // preview output. In this case, we retrieve the video
@@ -419,6 +417,7 @@
         const CameraParameters& params,
         int32_t frameRate) {
 
+    LOGV("checkFrameRate");
     int32_t frameRateActual = params.getPreviewFrameRate();
     if (frameRateActual < 0) {
         LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
@@ -464,6 +463,7 @@
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
 
+    LOGV("init");
     status_t err = OK;
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     err = initWithCameraAccess(camera, proxy, cameraId,
@@ -480,6 +480,7 @@
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
+    LOGV("initWithCameraAccess");
     status_t err = OK;
 
     if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
@@ -552,17 +553,25 @@
 }
 
 void CameraSource::startCameraRecording() {
+    LOGV("startCameraRecording");
     // 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();
+    if (mCameraFlags & FLAGS_HOT_CAMERA) {
+        mCamera->unlock();
+        mCamera.clear();
+        CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
+    } else {
+        mCamera->setListener(new CameraSourceListener(this));
+        mCamera->startRecording();
+        CHECK(mCamera->recordingEnabled());
+    }
     IPCThreadState::self()->restoreCallingIdentity(token);
-    CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
 }
 
 status_t CameraSource::start(MetaData *meta) {
+    LOGV("start");
     CHECK(!mStarted);
     if (mInitCheck != OK) {
         LOGE("CameraSource is not initialized yet");
@@ -588,7 +597,13 @@
 }
 
 void CameraSource::stopCameraRecording() {
-    mCameraRecordingProxy->stopRecording();
+    LOGV("stopCameraRecording");
+    if (mCameraFlags & FLAGS_HOT_CAMERA) {
+        mCameraRecordingProxy->stopRecording();
+    } else {
+        mCamera->setListener(NULL);
+        mCamera->stopRecording();
+    }
 }
 
 void CameraSource::releaseCamera() {
@@ -599,11 +614,10 @@
             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->unlock();
         mCamera.clear();
+        mCamera = 0;
         IPCThreadState::self()->restoreCallingIdentity(token);
     }
     if (mCameraRecordingProxy != 0) {
@@ -646,8 +660,13 @@
 }
 
 void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
+    LOGV("releaseRecordingFrame");
     if (mCameraRecordingProxy != NULL) {
         mCameraRecordingProxy->releaseRecordingFrame(frame);
+    } else {
+        int64_t token = IPCThreadState::self()->clearCallingIdentity();
+        mCamera->releaseRecordingFrame(frame);
+        IPCThreadState::self()->restoreCallingIdentity(token);
     }
 }
 
@@ -707,7 +726,8 @@
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
                 mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
-                if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+                if (mCameraRecordingProxy != 0 &&
+                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
                     LOGW("camera recording proxy is gone");
                     return ERROR_END_OF_STREAM;
                 }
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index fe78c46..1ba79e5 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -24,15 +24,10 @@
 #include <media/stagefright/CameraSourceTimeLapse.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/YUVImage.h>
-#include <media/stagefright/YUVCanvas.h>
 #include <camera/Camera.h>
 #include <camera/CameraParameters.h>
-#include <ui/Rect.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
-#include "OMX_Video.h"
-#include <limits.h>
 
 namespace android {
 
@@ -74,20 +69,14 @@
       mLastTimeLapseFrameRealTimestampUs(0),
       mSkipCurrentFrame(false) {
 
-    LOGD("starting time lapse mode: %lld us", mTimeBetweenTimeLapseFrameCaptureUs);
+    LOGD("starting time lapse mode: %lld us",
+        mTimeBetweenTimeLapseFrameCaptureUs);
+
     mVideoWidth = videoSize.width;
     mVideoHeight = videoSize.height;
 
-    if (trySettingVideoSize(videoSize.width, videoSize.height)) {
-        mUseStillCameraForTimeLapse = false;
-    } else {
-        // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
-        // than the fastest rate at which the still camera can take pictures.
-        mUseStillCameraForTimeLapse = true;
-        CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height));
-        mNeedCropping = computeCropRectangleOffset();
-        mMeta->setInt32(kKeyWidth, videoSize.width);
-        mMeta->setInt32(kKeyHeight, videoSize.height);
+    if (!trySettingVideoSize(videoSize.width, videoSize.height)) {
+        mInitCheck = NO_INIT;
     }
 
     // Initialize quick stop variables.
@@ -101,24 +90,22 @@
 }
 
 void CameraSourceTimeLapse::startQuickReadReturns() {
+    LOGV("startQuickReadReturns");
     Mutex::Autolock autoLock(mQuickStopLock);
-    LOGV("Enabling quick read returns");
 
     // Enable quick stop mode.
     mQuickStop = true;
 
-    if (mUseStillCameraForTimeLapse) {
-        // wake up the thread right away.
-        mTakePictureCondition.signal();
-    } else {
-        // Force dataCallbackTimestamp() coming from the video camera to not skip the
-        // next frame as we want read() to get a get a frame right away.
-        mForceRead = true;
-    }
+    // Force dataCallbackTimestamp() coming from the video camera to
+    // not skip the next frame as we want read() to get a get a frame
+    // right away.
+    mForceRead = true;
 }
 
-bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) {
-    LOGV("trySettingVideoSize: %dx%d", width, height);
+bool CameraSourceTimeLapse::trySettingVideoSize(
+        int32_t width, int32_t height) {
+
+    LOGV("trySettingVideoSize");
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     String8 s = mCamera->getParameters();
 
@@ -162,53 +149,8 @@
     return isSuccessful;
 }
 
-bool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
-    LOGV("setPictureSizeToClosestSupported: %dx%d", width, height);
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    String8 s = mCamera->getParameters();
-    IPCThreadState::self()->restoreCallingIdentity(token);
-
-    CameraParameters params(s);
-    Vector<Size> supportedSizes;
-    params.getSupportedPictureSizes(supportedSizes);
-
-    int32_t minPictureSize = INT_MAX;
-    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
-        int32_t pictureWidth = supportedSizes[i].width;
-        int32_t pictureHeight = supportedSizes[i].height;
-
-        if ((pictureWidth >= width) && (pictureHeight >= height)) {
-            int32_t pictureSize = pictureWidth*pictureHeight;
-            if (pictureSize < minPictureSize) {
-                minPictureSize = pictureSize;
-                mPictureWidth = pictureWidth;
-                mPictureHeight = pictureHeight;
-            }
-        }
-    }
-    LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
-    return (minPictureSize != INT_MAX);
-}
-
-bool CameraSourceTimeLapse::computeCropRectangleOffset() {
-    if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
-        return false;
-    }
-
-    CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
-
-    int32_t widthDifference = mPictureWidth - mVideoWidth;
-    int32_t heightDifference = mPictureHeight - mVideoHeight;
-
-    mCropRectStartX = widthDifference/2;
-    mCropRectStartY = heightDifference/2;
-
-    LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
-
-    return true;
-}
-
 void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
+    LOGV("signalBufferReturned");
     Mutex::Autolock autoLock(mQuickStopLock);
     if (mQuickStop && (buffer == mLastReadBufferCopy)) {
         buffer->setObserver(NULL);
@@ -218,7 +160,12 @@
     }
 }
 
-void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) {
+void createMediaBufferCopy(
+        const MediaBuffer& sourceBuffer,
+        int64_t frameTime,
+        MediaBuffer **newBuffer) {
+
+    LOGV("createMediaBufferCopy");
     size_t sourceSize = sourceBuffer.size();
     void* sourcePointer = sourceBuffer.data();
 
@@ -229,6 +176,7 @@
 }
 
 void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
+    LOGV("fillLastReadBufferCopy");
     int64_t frameTime;
     CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
     createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
@@ -238,11 +186,12 @@
 
 status_t CameraSourceTimeLapse::read(
         MediaBuffer **buffer, const ReadOptions *options) {
+    LOGV("read");
     if (mLastReadBufferCopy == NULL) {
         mLastReadStatus = CameraSource::read(buffer, options);
 
-        // mQuickStop may have turned to true while read was blocked. Make a copy of
-        // the buffer in that case.
+        // mQuickStop may have turned to true while read was blocked.
+        // Make a copy of the buffer in that case.
         Mutex::Autolock autoLock(mQuickStopLock);
         if (mQuickStop && *buffer) {
             fillLastReadBufferCopy(**buffer);
@@ -255,105 +204,19 @@
     }
 }
 
-// static
-void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
-    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
-    source->threadTimeLapseEntry();
-    return NULL;
-}
-
-void CameraSourceTimeLapse::threadTimeLapseEntry() {
-    while (mStarted) {
-        {
-            Mutex::Autolock autoLock(mCameraIdleLock);
-            if (!mCameraIdle) {
-                mCameraIdleCondition.wait(mCameraIdleLock);
-            }
-            CHECK(mCameraIdle);
-            mCameraIdle = false;
-        }
-
-        // Even if mQuickStop == true we need to take one more picture
-        // as a read() may be blocked, waiting for a frame to get available.
-        // After this takePicture, if mQuickStop == true, we can safely exit
-        // this thread as read() will make a copy of this last frame and keep
-        // returning it in the quick stop mode.
-        Mutex::Autolock autoLock(mQuickStopLock);
-        CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
-        if (mQuickStop) {
-            LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
-            return;
-        }
-        mTakePictureCondition.waitRelative(mQuickStopLock,
-                mTimeBetweenTimeLapseFrameCaptureUs * 1000);
-    }
-    LOGV("threadTimeLapseEntry: Exiting due to mStarted = false");
-}
-
-void CameraSourceTimeLapse::startCameraRecording() {
-    if (mUseStillCameraForTimeLapse) {
-        LOGV("start time lapse recording using still camera");
-
-        int64_t token = IPCThreadState::self()->clearCallingIdentity();
-        String8 s = mCamera->getParameters();
-
-        CameraParameters params(s);
-        params.setPictureSize(mPictureWidth, mPictureHeight);
-        mCamera->setParameters(params.flatten());
-        mCameraIdle = true;
-        mStopWaitingForIdleCamera = false;
-
-        // disable shutter sound and play the recording sound.
-        mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
-        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
-        IPCThreadState::self()->restoreCallingIdentity(token);
-
-        // create a thread which takes pictures in a loop
-        pthread_attr_t attr;
-        pthread_attr_init(&attr);
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-        pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
-        pthread_attr_destroy(&attr);
-    } else {
-        LOGV("start time lapse recording using video camera");
-        CameraSource::startCameraRecording();
-    }
-}
-
 void CameraSourceTimeLapse::stopCameraRecording() {
-    if (mUseStillCameraForTimeLapse) {
-        void *dummy;
-        pthread_join(mThreadTimeLapse, &dummy);
-
-        // Last takePicture may still be underway. Wait for the camera to get
-        // idle.
-        Mutex::Autolock autoLock(mCameraIdleLock);
-        mStopWaitingForIdleCamera = true;
-        if (!mCameraIdle) {
-            mCameraIdleCondition.wait(mCameraIdleLock);
-        }
-        CHECK(mCameraIdle);
-        mCamera->setListener(NULL);
-
-        // play the recording sound.
-        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
-    } else {
-        CameraSource::stopCameraRecording();
-    }
+    LOGV("stopCameraRecording");
+    CameraSource::stopCameraRecording();
     if (mLastReadBufferCopy) {
         mLastReadBufferCopy->release();
         mLastReadBufferCopy = NULL;
     }
 }
 
-void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse) {
-        CameraSource::releaseRecordingFrame(frame);
-    }
-}
+sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
+        const sp<IMemory> &source_data) {
 
-sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
+    LOGV("createIMemoryCopy");
     size_t source_size = source_data->size();
     void* source_pointer = source_data->pointer();
 
@@ -363,102 +226,8 @@
     return newMemory;
 }
 
-// Allocates IMemory of final type MemoryBase with the given size.
-sp<IMemory> allocateIMemory(size_t size) {
-    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
-    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
-    return newMemory;
-}
-
-// static
-void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
-    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
-    source->threadStartPreview();
-    return NULL;
-}
-
-void CameraSourceTimeLapse::threadStartPreview() {
-    CHECK_EQ(OK, mCamera->startPreview());
-    Mutex::Autolock autoLock(mCameraIdleLock);
-    mCameraIdle = true;
-    mCameraIdleCondition.signal();
-}
-
-void CameraSourceTimeLapse::restartPreview() {
-    // Start this in a different thread, so that the dataCallback can return
-    LOGV("restartPreview");
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-    pthread_t threadPreview;
-    pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
-    pthread_attr_destroy(&attr);
-}
-
-sp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
-    // find the YUV format
-    int32_t srcFormat;
-    CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
-    YUVImage::YUVFormat yuvFormat;
-    if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
-        yuvFormat = YUVImage::YUV420SemiPlanar;
-    } else {
-        CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar);
-        yuvFormat = YUVImage::YUV420Planar;
-    }
-
-    // allocate memory for cropped image and setup a canvas using it.
-    sp<IMemory> croppedImageMemory = allocateIMemory(
-            YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
-    YUVImage yuvImageCropped(yuvFormat,
-            mVideoWidth, mVideoHeight,
-            (uint8_t *)croppedImageMemory->pointer());
-    YUVCanvas yuvCanvasCrop(yuvImageCropped);
-
-    YUVImage yuvImageSource(yuvFormat,
-            mPictureWidth, mPictureHeight,
-            (uint8_t *)source_data->pointer());
-    yuvCanvasCrop.CopyImageRect(
-            Rect(mCropRectStartX, mCropRectStartY,
-                mCropRectStartX + mVideoWidth,
-                mCropRectStartY + mVideoHeight),
-            0, 0,
-            yuvImageSource);
-
-    return croppedImageMemory;
-}
-
-void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
-    if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
-        // takePicture will complete after this callback, so restart preview.
-        restartPreview();
-        return;
-    }
-    if (msgType != CAMERA_MSG_RAW_IMAGE) {
-        return;
-    }
-
-    LOGV("dataCallback for timelapse still frame");
-    CHECK_EQ(true, mUseStillCameraForTimeLapse);
-
-    int64_t timestampUs;
-    if (mNumFramesReceived == 0) {
-        timestampUs = mStartTimeUs;
-    } else {
-        timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-    }
-
-    if (mNeedCropping) {
-        sp<IMemory> croppedImageData = cropYUVImage(data);
-        dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
-    } else {
-        sp<IMemory> dataCopy = createIMemoryCopy(data);
-        dataCallbackTimestamp(timestampUs, msgType, dataCopy);
-    }
-}
-
 bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
+    LOGV("skipCurrentFrame");
     if (mSkipCurrentFrame) {
         mSkipCurrentFrame = false;
         return true;
@@ -468,72 +237,58 @@
 }
 
 bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
-    if (!mUseStillCameraForTimeLapse) {
-        if (mLastTimeLapseFrameRealTimestampUs == 0) {
-            // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
-            // to current time (timestampUs) and save frame data.
-            LOGV("dataCallbackTimestamp timelapse: initial frame");
+    LOGV("skipFrameAndModifyTimeStamp");
+    if (mLastTimeLapseFrameRealTimestampUs == 0) {
+        // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
+        // to current time (timestampUs) and save frame data.
+        LOGV("dataCallbackTimestamp timelapse: initial frame");
 
-            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        return false;
+    }
+
+    {
+        Mutex::Autolock autoLock(mQuickStopLock);
+
+        // mForceRead may be set to true by startQuickReadReturns(). In that
+        // case don't skip this frame.
+        if (mForceRead) {
+            LOGV("dataCallbackTimestamp timelapse: forced read");
+            mForceRead = false;
+            *timestampUs =
+                mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
             return false;
         }
+    }
 
-        {
-            Mutex::Autolock autoLock(mQuickStopLock);
+    // Workaround to bypass the first 2 input frames for skipping.
+    // The first 2 output frames from the encoder are: decoder specific info and
+    // the compressed video frame data for the first input video frame.
+    if (mNumFramesEncoded >= 1 && *timestampUs <
+        (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
+        // Skip all frames from last encoded frame until
+        // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+        // Tell the camera to release its recording frame and return.
+        LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
+        return true;
+    } else {
+        // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
+        // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
+        // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
+        // of the last encoded frame's time stamp.
+        LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
 
-            // mForceRead may be set to true by startQuickReadReturns(). In that
-            // case don't skip this frame.
-            if (mForceRead) {
-                LOGV("dataCallbackTimestamp timelapse: forced read");
-                mForceRead = false;
-                *timestampUs =
-                    mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-                return false;
-            }
-        }
-
-        // Workaround to bypass the first 2 input frames for skipping.
-        // The first 2 output frames from the encoder are: decoder specific info and
-        // the compressed video frame data for the first input video frame.
-        if (mNumFramesEncoded >= 1 && *timestampUs <
-                (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
-            // Skip all frames from last encoded frame until
-            // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
-            // Tell the camera to release its recording frame and return.
-            LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
-            return true;
-        } else {
-            // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
-            // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
-            // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
-            // of the last encoded frame's time stamp.
-            LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
-
-            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
-            *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-            return false;
-        }
+        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+        return false;
     }
     return false;
 }
 
 void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
             const sp<IMemory> &data) {
-    if (!mUseStillCameraForTimeLapse) {
-        mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
-    } else {
-        Mutex::Autolock autoLock(mCameraIdleLock);
-        // If we are using the still camera and stop() has been called, it may
-        // be waiting for the camera to get idle. In that case return
-        // immediately. Calling CameraSource::dataCallbackTimestamp() will lead
-        // to a deadlock since it tries to access CameraSource::mLock which in
-        // this case is held by CameraSource::stop() currently waiting for the
-        // camera to get idle. And camera will not get idle until this call
-        // returns.
-        if (mStopWaitingForIdleCamera) {
-            return;
-        }
-    }
+    LOGV("dataCallbackTimestamp");
+    mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
     CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
 }
 
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp
index b7c8e0c..1f7ee25 100644
--- a/media/libstagefright/ESDS.cpp
+++ b/media/libstagefright/ESDS.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ESDS"
+#include <utils/Log.h>
+
 #include "include/ESDS.h"
 
 #include <string.h>
@@ -87,6 +91,8 @@
     }
     while (more);
 
+    LOGV("tag=0x%02x data_size=%d", *tag, *data_size);
+
     if (*data_size > size) {
         return ERROR_MALFORMED;
     }
@@ -146,8 +152,20 @@
     if (OCRstreamFlag) {
         offset += 2;
         size -= 2;
+
+        if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
+                && offset - 2 < size
+                && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
+            // Content found "in the wild" had OCRstreamFlag set but was
+            // missing OCR_ES_Id, the decoder config descriptor immediately
+            // followed instead.
+            offset -= 2;
+            size += 2;
+
+            LOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
+        }
     }
-    
+
     if (offset >= size) {
         return ERROR_MALFORMED;
     }
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 0d24551..f9d8501 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -24,10 +24,11 @@
 #include "include/ChromiumHTTPDataSource.h"
 #endif
 
-#include "include/NuHTTPDataSource.h"
-
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
+
 #include <cutils/properties.h>
+#include <cutils/qtaguid.h>
 
 namespace android {
 
@@ -44,14 +45,12 @@
 // static
 sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
 #if CHROMIUM_AVAILABLE
-    char value[PROPERTY_VALUE_MAX];
-    if (!property_get("media.stagefright.use-chromium", value, NULL)
-            || (strcasecmp("false", value) && strcmp("0", value))) {
         return new ChromiumHTTPDataSource(flags);
-    } else
 #endif
     {
-        return new NuHTTPDataSource(flags);
+        TRESPASS();
+
+        return NULL;
     }
 }
 
@@ -135,4 +134,10 @@
     return true;
 }
 
+// static
+void HTTPBase::RegisterSocketUser(int s, uid_t uid) {
+    static const uint32_t kTag = 0xdeadbeef;
+    set_qtaguid(s, kTag, uid);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
deleted file mode 100644
index d526ebd..0000000
--- a/media/libstagefright/HTTPStream.cpp
+++ /dev/null
@@ -1,623 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "HTTPStream"
-#include <utils/Log.h>
-
-#include "include/HTTPStream.h"
-
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-#include <openssl/ssl.h>
-
-namespace android {
-
-// static
-const char *HTTPStream::kStatusKey = ":status:";  // MUST be lowercase.
-
-HTTPStream::HTTPStream()
-    : mState(READY),
-      mUIDValid(false),
-      mSocket(-1),
-      mSSLContext(NULL),
-      mSSL(NULL) {
-}
-
-HTTPStream::~HTTPStream() {
-    disconnect();
-
-    if (mSSLContext != NULL) {
-        SSL_CTX_free((SSL_CTX *)mSSLContext);
-        mSSLContext = NULL;
-    }
-}
-
-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);
-    if (flags == -1) {
-        return false;
-    }
-
-    if (blocking) {
-        flags &= ~O_NONBLOCK;
-    } else {
-        flags |= O_NONBLOCK;
-    }
-
-    return fcntl(s, F_SETFL, flags) != -1;
-}
-
-static status_t MyConnect(
-        int s, const struct sockaddr *addr, socklen_t addrlen) {
-    status_t result = UNKNOWN_ERROR;
-
-    MakeSocketBlocking(s, false);
-
-    if (connect(s, addr, addrlen) == 0) {
-        result = OK;
-    } else if (errno != EINPROGRESS) {
-        result = -errno;
-    } else {
-        for (;;) {
-            fd_set rs, ws;
-            FD_ZERO(&rs);
-            FD_ZERO(&ws);
-            FD_SET(s, &rs);
-            FD_SET(s, &ws);
-
-            struct timeval tv;
-            tv.tv_sec = 0;
-            tv.tv_usec = 100000ll;
-
-            int nfds = ::select(s + 1, &rs, &ws, NULL, &tv);
-
-            if (nfds < 0) {
-                if (errno == EINTR) {
-                    continue;
-                }
-
-                result = -errno;
-                break;
-            }
-
-            if (FD_ISSET(s, &ws) && !FD_ISSET(s, &rs)) {
-                result = OK;
-                break;
-            }
-
-            if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
-                // Get the pending error.
-                int error = 0;
-                socklen_t errorLen = sizeof(error);
-                if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errorLen) == -1) {
-                    // Couldn't get the real error, so report why not.
-                    result = -errno;
-                } else {
-                    result = -error;
-                }
-                break;
-            }
-
-            // Timeout expired. Try again.
-        }
-    }
-
-    MakeSocketBlocking(s, true);
-
-    return result;
-}
-
-// Apparently under out linux closing a socket descriptor from one thread
-// will not unblock a pending send/recv on that socket on another thread.
-static ssize_t MySendReceive(
-        int s, void *data, size_t size, int flags, bool sendData) {
-    ssize_t result = 0;
-
-    if (s < 0) {
-        return -1;
-    }
-    while (size > 0) {
-        fd_set rs, ws, es;
-        FD_ZERO(&rs);
-        FD_ZERO(&ws);
-        FD_ZERO(&es);
-        FD_SET(s, sendData ? &ws : &rs);
-        FD_SET(s, &es);
-
-        struct timeval tv;
-        tv.tv_sec = 0;
-        tv.tv_usec = 100000ll;
-
-        int nfds = ::select(
-                s + 1,
-                sendData ? NULL : &rs,
-                sendData ? &ws : NULL,
-                &es,
-                &tv);
-
-        if (nfds < 0) {
-            if (errno == EINTR) {
-                continue;
-            }
-
-            result = -errno;
-            break;
-        } else if (nfds == 0) {
-            // timeout
-
-            continue;
-        }
-
-        CHECK_EQ(nfds, 1);
-
-        ssize_t nbytes =
-            sendData ? send(s, data, size, flags) : recv(s, data, size, flags);
-
-        if (nbytes < 0) {
-            if (errno == EINTR) {
-                continue;
-            }
-
-            result = -errno;
-            break;
-        } else if (nbytes == 0) {
-            result = 0;
-            break;
-        }
-
-        data = (uint8_t *)data + nbytes;
-        size -= nbytes;
-
-        result = nbytes;
-        break;
-    }
-
-    return result;
-}
-
-static ssize_t MySend(int s, const void *data, size_t size, int flags) {
-    return MySendReceive(
-            s, const_cast<void *>(data), size, flags, true /* sendData */);
-}
-
-static ssize_t MyReceive(int s, void *data, size_t size, int flags) {
-    return MySendReceive(s, data, size, flags, false /* sendData */);
-}
-
-status_t HTTPStream::connect(const char *server, int port, bool https) {
-    if (port < 0) {
-        port = https ? 443 : 80;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-
-    status_t err = OK;
-
-    if (mState == CONNECTED) {
-        return ERROR_ALREADY_CONNECTED;
-    }
-
-    if (port < 0 || port > (int) USHRT_MAX) {
-        return UNKNOWN_ERROR;
-    }
-
-    char service[sizeof("65536")];
-    sprintf(service, "%d", port);
-    struct addrinfo hints, *ai;
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
-    hints.ai_socktype = SOCK_STREAM;
-
-    int ret = getaddrinfo(server, service, &hints, &ai);
-    if (ret) {
-        return ERROR_UNKNOWN_HOST;
-    }
-
-    CHECK_EQ(mSocket, -1);
-
-    mState = CONNECTING;
-    status_t res = -1;
-    struct addrinfo *tmp;
-    for (tmp = ai; tmp; tmp = tmp->ai_next) {
-        mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
-        if (mSocket < 0) {
-            continue;
-        }
-
-        if (mUIDValid) {
-            RegisterSocketUser(mSocket, mUID);
-        }
-
-        setReceiveTimeout(30);  // Time out reads after 30 secs by default.
-
-        int s = mSocket;
-
-        mLock.unlock();
-
-        res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen);
-
-        mLock.lock();
-
-        if (mState != CONNECTING) {
-            close(s);
-            freeaddrinfo(ai);
-            return UNKNOWN_ERROR;
-        }
-
-        if (res == OK) {
-            break;
-        }
-
-        close(s);
-    }
-
-    freeaddrinfo(ai);
-
-    if (res != OK) {
-        close(mSocket);
-        mSocket = -1;
-
-        mState = READY;
-        return res;
-    }
-
-    if (https) {
-        CHECK(mSSL == NULL);
-
-        if (mSSLContext == NULL) {
-            SSL_library_init();
-
-            mSSLContext = SSL_CTX_new(TLSv1_client_method());
-
-            if (mSSLContext == NULL) {
-                LOGE("failed to create SSL context");
-                mState = READY;
-                return ERROR_IO;
-            }
-        }
-
-        mSSL = SSL_new((SSL_CTX *)mSSLContext);
-
-        if (mSSL == NULL) {
-            LOGE("failed to create SSL session");
-
-            mState = READY;
-            return ERROR_IO;
-        }
-
-        int res = SSL_set_fd((SSL *)mSSL, mSocket);
-
-        if (res == 1) {
-            res = SSL_connect((SSL *)mSSL);
-        }
-
-        if (res != 1) {
-            SSL_free((SSL *)mSSL);
-            mSSL = NULL;
-
-            LOGE("failed to connect over SSL");
-            mState = READY;
-
-            return ERROR_IO;
-        }
-    }
-
-    mState = CONNECTED;
-
-    return OK;
-}
-
-status_t HTTPStream::disconnect() {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mState != CONNECTED && mState != CONNECTING) {
-        return ERROR_NOT_CONNECTED;
-    }
-
-    if (mSSL != NULL) {
-        SSL_shutdown((SSL *)mSSL);
-
-        SSL_free((SSL *)mSSL);
-        mSSL = NULL;
-    }
-
-    CHECK(mSocket >= 0);
-    close(mSocket);
-    mSocket = -1;
-
-    mState = READY;
-
-    return OK;
-}
-
-status_t HTTPStream::send(const char *data, size_t size) {
-    if (mState != CONNECTED) {
-        return ERROR_NOT_CONNECTED;
-    }
-
-    while (size > 0) {
-        ssize_t n;
-        if (mSSL != NULL) {
-            n = SSL_write((SSL *)mSSL, data, size);
-
-            if (n < 0) {
-                n = -SSL_get_error((SSL *)mSSL, n);
-            }
-        } else {
-            n = MySend(mSocket, data, size, 0);
-        }
-
-        if (n < 0) {
-            disconnect();
-
-            return n;
-        } else if (n == 0) {
-            disconnect();
-
-            return ERROR_CONNECTION_LOST;
-        }
-
-        size -= (size_t)n;
-        data += (size_t)n;
-    }
-
-    return OK;
-}
-
-status_t HTTPStream::send(const char *data) {
-    return send(data, strlen(data));
-}
-
-// A certain application spawns a local webserver that sends invalid responses,
-// specifically it terminates header line with only a newline instead of the
-// CRLF (carriage-return followed by newline) required by the HTTP specs.
-// The workaround accepts both behaviours but could potentially break
-// legitimate responses that use a single newline to "fold" headers, which is
-// why it's not yet on by default.
-#define WORKAROUND_FOR_MISSING_CR       1
-
-status_t HTTPStream::receive_line(char *line, size_t size) {
-    if (mState != CONNECTED) {
-        return ERROR_NOT_CONNECTED;
-    }
-
-    bool saw_CR = false;
-    size_t length = 0;
-
-    for (;;) {
-        char c;
-        ssize_t n;
-        if (mSSL != NULL) {
-            n = SSL_read((SSL *)mSSL, &c, 1);
-
-            if (n < 0) {
-                n = -SSL_get_error((SSL *)mSSL, n);
-            }
-        } else {
-            n = MyReceive(mSocket, &c, 1, 0);
-        }
-
-        if (n < 0) {
-            disconnect();
-
-            return ERROR_IO;
-        } else if (n == 0) {
-            disconnect();
-
-            return ERROR_CONNECTION_LOST;
-        }
-
-#if WORKAROUND_FOR_MISSING_CR
-        if (c == '\n') {
-            // We have a complete line.
-
-            line[saw_CR ? length - 1 : length] = '\0';
-            return OK;
-        }
-#else
-        if (saw_CR &&  c == '\n') {
-            // We have a complete line.
-
-            line[length - 1] = '\0';
-            return OK;
-        }
-#endif
-
-        saw_CR = (c == '\r');
-
-        if (length + 1 >= size) {
-            return ERROR_MALFORMED;
-        }
-        line[length++] = c;
-    }
-}
-
-status_t HTTPStream::receive_header(int *http_status) {
-    *http_status = -1;
-    mHeaders.clear();
-
-    char line[2048];
-    status_t err = receive_line(line, sizeof(line));
-    if (err != OK) {
-        return err;
-    }
-
-    mHeaders.add(AString(kStatusKey), AString(line));
-
-    char *spacePos = strchr(line, ' ');
-    if (spacePos == NULL) {
-        // Malformed response?
-        return UNKNOWN_ERROR;
-    }
-
-    char *status_start = spacePos + 1;
-    char *status_end = status_start;
-    while (isdigit(*status_end)) {
-        ++status_end;
-    }
-
-    if (status_end == status_start) {
-        // Malformed response, status missing?
-        return UNKNOWN_ERROR;
-    }
-
-    memmove(line, status_start, status_end - status_start);
-    line[status_end - status_start] = '\0';
-
-    long tmp = strtol(line, NULL, 10);
-    if (tmp < 0 || tmp > 999) {
-        return UNKNOWN_ERROR;
-    }
-
-    *http_status = (int)tmp;
-
-    for (;;) {
-        err = receive_line(line, sizeof(line));
-        if (err != OK) {
-            return err;
-        }
-
-        if (*line == '\0') {
-            // Empty line signals the end of the header.
-            break;
-        }
-
-        // puts(line);
-
-        char *colonPos = strchr(line, ':');
-        if (colonPos == NULL) {
-            AString key = line;
-            key.tolower();
-
-            mHeaders.add(key, AString());
-        } else {
-            char *end_of_key = colonPos;
-            while (end_of_key > line && isspace(end_of_key[-1])) {
-                --end_of_key;
-            }
-
-            char *start_of_value = colonPos + 1;
-            while (isspace(*start_of_value)) {
-                ++start_of_value;
-            }
-
-            *end_of_key = '\0';
-
-            AString key = line;
-            key.tolower();
-
-            mHeaders.add(key, AString(start_of_value));
-        }
-    }
-
-    return OK;
-}
-
-ssize_t HTTPStream::receive(void *data, size_t size) {
-    size_t total = 0;
-    while (total < size) {
-        ssize_t n;
-        if (mSSL != NULL) {
-            n = SSL_read((SSL *)mSSL, (char *)data + total, size - total);
-
-            if (n < 0) {
-                n = -SSL_get_error((SSL *)mSSL, n);
-            }
-        } else {
-            n = MyReceive(mSocket, (char *)data + total, size - total, 0);
-        }
-
-        if (n < 0) {
-            LOGE("recv failed, errno = %d (%s)", (int)n, strerror(-n));
-
-            disconnect();
-            return (ssize_t)ERROR_IO;
-        } else if (n == 0) {
-            disconnect();
-
-            LOGE("recv failed, server is gone, total received: %d bytes",
-                 total);
-
-            return total == 0 ? (ssize_t)ERROR_CONNECTION_LOST : total;
-        }
-
-        total += (size_t)n;
-    }
-
-    return (ssize_t)total;
-}
-
-bool HTTPStream::find_header_value(const AString &key, AString *value) const {
-    AString key_lower = key;
-    key_lower.tolower();
-
-    ssize_t index = mHeaders.indexOfKey(key_lower);
-    if (index < 0) {
-        value->clear();
-        return false;
-    }
-
-    *value = mHeaders.valueAt(index);
-
-    return true;
-}
-
-void HTTPStream::setReceiveTimeout(int seconds) {
-    if (seconds < 0) {
-        // Disable the timeout.
-        seconds = 0;
-    }
-
-    struct timeval tv;
-    tv.tv_usec = 0;
-    tv.tv_sec = seconds;
-    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/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 77a6602..4edb613 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -185,7 +185,8 @@
       mFinalStatus(OK),
       mLastAccessPos(0),
       mFetching(true),
-      mLastFetchTimeUs(-1) {
+      mLastFetchTimeUs(-1),
+      mNumRetriesLeft(kMaxNumRetries) {
     mLooper->setName("NuCachedSource2");
     mLooper->registerHandler(mReflector);
     mLooper->start();
@@ -254,7 +255,27 @@
 void NuCachedSource2::fetchInternal() {
     LOGV("fetchInternal");
 
-    CHECK_EQ(mFinalStatus, (status_t)OK);
+    {
+        Mutex::Autolock autoLock(mLock);
+        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
+
+        if (mFinalStatus != OK) {
+            --mNumRetriesLeft;
+
+            status_t err =
+                mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
+
+            if (err == ERROR_UNSUPPORTED) {
+                mNumRetriesLeft = 0;
+                return;
+            } else if (err != OK) {
+                LOGI("The attempt to reconnect failed, %d retries remaining",
+                     mNumRetriesLeft);
+
+                return;
+            }
+        }
+    }
 
     PageCache::Page *page = mCache->acquirePage();
 
@@ -264,14 +285,23 @@
     Mutex::Autolock autoLock(mLock);
 
     if (n < 0) {
-        LOGE("source returned error %ld", n);
+        LOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft);
         mFinalStatus = n;
         mCache->releasePage(page);
     } else if (n == 0) {
         LOGI("ERROR_END_OF_STREAM");
+
+        mNumRetriesLeft = 0;
         mFinalStatus = ERROR_END_OF_STREAM;
+
         mCache->releasePage(page);
     } else {
+        if (mFinalStatus != OK) {
+            LOGI("retrying a previously failed read succeeded.");
+        }
+        mNumRetriesLeft = kMaxNumRetries;
+        mFinalStatus = OK;
+
         page->mSize = n;
         mCache->appendPage(page);
     }
@@ -280,7 +310,7 @@
 void NuCachedSource2::onFetch() {
     LOGV("onFetch");
 
-    if (mFinalStatus != OK) {
+    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
         LOGV("EOS reached, done prefetching for now");
         mFetching = false;
     }
@@ -308,8 +338,19 @@
         restartPrefetcherIfNecessary_l();
     }
 
-    (new AMessage(kWhatFetchMore, mReflector->id()))->post(
-            mFetching ? 0 : 100000ll);
+    int64_t delayUs;
+    if (mFetching) {
+        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+            // We failed this time and will try again in 3 seconds.
+            delayUs = 3000000ll;
+        } else {
+            delayUs = 0;
+        }
+    } else {
+        delayUs = 100000ll;
+    }
+
+    (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs);
 }
 
 void NuCachedSource2::onRead(const sp<AMessage> &msg) {
@@ -345,7 +386,7 @@
         bool ignoreLowWaterThreshold, bool force) {
     static const size_t kGrayArea = 1024 * 1024;
 
-    if (mFetching || mFinalStatus != OK) {
+    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
         return;
     }
 
@@ -427,6 +468,12 @@
 
 size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) {
     *finalStatus = mFinalStatus;
+
+    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+        // Pretend that everything is fine until we're out of retries.
+        *finalStatus = OK;
+    }
+
     off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
     if (mLastAccessPos < lastBytePosCached) {
         return lastBytePosCached - mLastAccessPos;
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
deleted file mode 100644
index 2949767..0000000
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ /dev/null
@@ -1,560 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "NuHTTPDataSource"
-#include <utils/Log.h>
-
-#include "include/NuHTTPDataSource.h"
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-static bool ParseSingleUnsignedLong(
-        const char *from, unsigned long *x) {
-    char *end;
-    *x = strtoul(from, &end, 10);
-
-    if (end == from || *end != '\0') {
-        return false;
-    }
-
-    return true;
-}
-
-static bool ParseURL(
-        const char *url, String8 *host, unsigned *port,
-        String8 *path, bool *https) {
-    host->setTo("");
-    *port = 0;
-    path->setTo("");
-
-    size_t hostStart;
-    if (!strncasecmp("http://", url, 7)) {
-        hostStart = 7;
-        *https = false;
-    } else if (!strncasecmp("https://", url, 8)) {
-        hostStart = 8;
-        *https = true;
-    } else {
-        return false;
-    }
-
-    const char *slashPos = strchr(&url[hostStart], '/');
-
-    if (slashPos == NULL) {
-        host->setTo(&url[hostStart]);
-        path->setTo("/");
-    } else {
-        host->setTo(&url[hostStart], slashPos - &url[hostStart]);
-        path->setTo(slashPos);
-    }
-
-    const char *colonPos = strchr(host->string(), ':');
-
-    if (colonPos != NULL) {
-        unsigned long x;
-        if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
-            return false;
-        }
-
-        *port = x;
-
-        size_t colonOffset = colonPos - host->string();
-        String8 tmp(host->string(), colonOffset);
-        *host = tmp;
-    } else {
-        *port = (*https) ? 443 : 80;
-    }
-
-    return true;
-}
-
-NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
-    : mFlags(flags),
-      mState(DISCONNECTED),
-      mPort(0),
-      mHTTPS(false),
-      mOffset(0),
-      mContentLength(0),
-      mContentLengthValid(false),
-      mHasChunkedTransferEncoding(false),
-      mChunkDataBytesLeft(0),
-      mDecryptHandle(NULL),
-      mDrmManagerClient(NULL) {
-}
-
-NuHTTPDataSource::~NuHTTPDataSource() {
-    if (mDecryptHandle != NULL) {
-        // To release mDecryptHandle
-        CHECK(mDrmManagerClient);
-        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
-        mDecryptHandle = NULL;
-    }
-
-    if (mDrmManagerClient != NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-}
-
-status_t NuHTTPDataSource::connect(
-        const char *uri,
-        const KeyedVector<String8, String8> *overrides,
-        off64_t offset) {
-    String8 headers;
-    MakeFullHeaders(overrides, &headers);
-
-    return connect(uri, headers, offset);
-}
-
-status_t NuHTTPDataSource::connect(
-        const char *uri,
-        const String8 &headers,
-        off64_t offset) {
-    String8 host, path;
-    unsigned port;
-
-    mUri = uri;
-    mContentType = String8("application/octet-stream");
-
-    bool https;
-    if (!ParseURL(uri, &host, &port, &path, &https)) {
-        return ERROR_MALFORMED;
-    }
-
-    uid_t uid;
-    if (getUID(&uid)) {
-        mHTTP.setUID(uid);
-    }
-
-    return connect(host, port, path, https, headers, offset);
-}
-
-static bool IsRedirectStatusCode(int httpStatus) {
-    return httpStatus == 301 || httpStatus == 302
-        || httpStatus == 303 || httpStatus == 307;
-}
-
-status_t NuHTTPDataSource::connect(
-        const char *host, unsigned port, const char *path,
-        bool https,
-        const String8 &headers,
-        off64_t offset) {
-    if (!(mFlags & kFlagIncognito)) {
-        LOGI("connect to %s:%u%s @%lld", host, port, path, offset);
-    } else {
-        LOGI("connect to <URL suppressed> @%lld", offset);
-    }
-
-    bool needsToReconnect = true;
-
-    if (mState == CONNECTED && host == mHost && port == mPort
-            && https == mHTTPS && offset == mOffset) {
-        if (mContentLengthValid && mOffset == mContentLength) {
-            LOGI("Didn't have to reconnect, old one's still good.");
-            needsToReconnect = false;
-        }
-    }
-
-    mHost = host;
-    mPort = port;
-    mPath = path;
-    mHTTPS = https;
-    mHeaders = headers;
-
-    status_t err = OK;
-
-    mState = CONNECTING;
-
-    if (needsToReconnect) {
-        mHTTP.disconnect();
-        err = mHTTP.connect(host, port, https);
-    }
-
-    if (err != OK) {
-        mState = DISCONNECTED;
-    } else if (mState != CONNECTING) {
-        err = UNKNOWN_ERROR;
-    } else {
-        mState = CONNECTED;
-
-        mOffset = offset;
-        mContentLength = 0;
-        mContentLengthValid = false;
-
-        String8 request("GET ");
-        request.append(mPath);
-        request.append(" HTTP/1.1\r\n");
-        request.append("Host: ");
-        request.append(mHost);
-        if (mPort != 80) {
-            request.append(StringPrintf(":%u", mPort).c_str());
-        }
-        request.append("\r\n");
-
-        if (offset != 0) {
-            char rangeHeader[128];
-            sprintf(rangeHeader, "Range: bytes=%lld-\r\n", offset);
-            request.append(rangeHeader);
-        }
-
-        request.append(mHeaders);
-        request.append("\r\n");
-
-        int httpStatus;
-        if ((err = mHTTP.send(request.string(), request.size())) != OK
-                || (err = mHTTP.receive_header(&httpStatus)) != OK) {
-            mHTTP.disconnect();
-            mState = DISCONNECTED;
-            return err;
-        }
-
-        if (IsRedirectStatusCode(httpStatus)) {
-            AString value;
-            CHECK(mHTTP.find_header_value("Location", &value));
-
-            mState = DISCONNECTED;
-
-            mHTTP.disconnect();
-
-            return connect(value.c_str(), headers, offset);
-        }
-
-        if (httpStatus < 200 || httpStatus >= 300) {
-            mState = DISCONNECTED;
-            mHTTP.disconnect();
-
-            return ERROR_IO;
-        }
-
-        mHasChunkedTransferEncoding = false;
-
-        {
-            AString value;
-            if (mHTTP.find_header_value("Transfer-Encoding", &value)) {
-                // We don't currently support any transfer encodings but
-                // chunked.
-
-                if (!strcasecmp(value.c_str(), "chunked")) {
-                    LOGI("Chunked transfer encoding applied.");
-                    mHasChunkedTransferEncoding = true;
-                    mChunkDataBytesLeft = 0;
-                } else {
-                    mState = DISCONNECTED;
-                    mHTTP.disconnect();
-
-                    LOGE("We don't support '%s' transfer encoding.", value.c_str());
-
-                    return ERROR_UNSUPPORTED;
-                }
-            }
-        }
-
-        {
-            AString value;
-            if (mHTTP.find_header_value("Content-Type", &value)) {
-                mContentType = String8(value.c_str());
-            } else {
-                mContentType = String8("application/octet-stream");
-            }
-        }
-
-        applyTimeoutResponse();
-
-        if (offset == 0) {
-            AString value;
-            unsigned long x;
-            if (mHTTP.find_header_value(AString("Content-Length"), &value)
-                    && ParseSingleUnsignedLong(value.c_str(), &x)) {
-                mContentLength = (off64_t)x;
-                mContentLengthValid = true;
-            } else {
-                LOGW("Server did not give us the content length!");
-            }
-        } else {
-            if (httpStatus != 206 /* Partial Content */) {
-                // We requested a range but the server didn't support that.
-                LOGE("We requested a range but the server didn't "
-                     "support that.");
-                return ERROR_UNSUPPORTED;
-            }
-
-            AString value;
-            unsigned long x;
-            if (mHTTP.find_header_value(AString("Content-Range"), &value)) {
-                const char *slashPos = strchr(value.c_str(), '/');
-                if (slashPos != NULL
-                        && ParseSingleUnsignedLong(slashPos + 1, &x)) {
-                    mContentLength = x;
-                    mContentLengthValid = true;
-                }
-            }
-        }
-    }
-
-    return err;
-}
-
-void NuHTTPDataSource::disconnect() {
-    if (mState == CONNECTING || mState == CONNECTED) {
-        mHTTP.disconnect();
-    }
-    mState = DISCONNECTED;
-}
-
-status_t NuHTTPDataSource::initCheck() const {
-    return mState == CONNECTED ? OK : NO_INIT;
-}
-
-ssize_t NuHTTPDataSource::internalRead(void *data, size_t size) {
-    if (!mHasChunkedTransferEncoding) {
-        return mHTTP.receive(data, size);
-    }
-
-    if (mChunkDataBytesLeft < 0) {
-        return 0;
-    } else if (mChunkDataBytesLeft == 0) {
-        char line[1024];
-        status_t err = mHTTP.receive_line(line, sizeof(line));
-
-        if (err != OK) {
-            return err;
-        }
-
-        LOGV("line = '%s'", line);
-
-        char *end;
-        unsigned long n = strtoul(line, &end, 16);
-
-        if (end == line || (*end != ';' && *end != '\0')) {
-            LOGE("malformed HTTP chunk '%s'", line);
-            return ERROR_MALFORMED;
-        }
-
-        mChunkDataBytesLeft = n;
-        LOGV("chunk data size = %lu", n);
-
-        if (mChunkDataBytesLeft == 0) {
-            mChunkDataBytesLeft = -1;
-            return 0;
-        }
-
-        // fall through
-    }
-
-    if (size > (size_t)mChunkDataBytesLeft) {
-        size = mChunkDataBytesLeft;
-    }
-
-    ssize_t n = mHTTP.receive(data, size);
-
-    if (n < 0) {
-        return n;
-    }
-
-    mChunkDataBytesLeft -= (size_t)n;
-
-    if (mChunkDataBytesLeft == 0) {
-        char line[1024];
-        status_t err = mHTTP.receive_line(line, sizeof(line));
-
-        if (err != OK) {
-            return err;
-        }
-
-        if (line[0] != '\0') {
-            LOGE("missing HTTP chunk terminator.");
-            return ERROR_MALFORMED;
-        }
-    }
-
-    return n;
-}
-
-ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
-    LOGV("readAt offset %ld, size %d", offset, size);
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (offset != mOffset) {
-        String8 host = mHost;
-        String8 path = mPath;
-        String8 headers = mHeaders;
-        status_t err = connect(host, mPort, path, mHTTPS, headers, offset);
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    if (mContentLengthValid) {
-        size_t avail =
-            (offset >= mContentLength) ? 0 : mContentLength - offset;
-
-        if (size > avail) {
-            size = avail;
-        }
-    }
-
-    size_t numBytesRead = 0;
-    while (numBytesRead < size) {
-        int64_t startTimeUs = ALooper::GetNowUs();
-
-        ssize_t n =
-            internalRead((uint8_t *)data + numBytesRead, size - numBytesRead);
-
-        if (n < 0) {
-            if (numBytesRead == 0 || mContentLengthValid) {
-                return n;
-            }
-
-            // If there was an error we want to at least return the data
-            // we've already successfully read. The next call to read will
-            // then return the error.
-            n = 0;
-        }
-
-        int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
-        addBandwidthMeasurement(n, delayUs);
-
-        numBytesRead += (size_t)n;
-
-        if (n == 0) {
-            if (mContentLengthValid) {
-                // We know the content length and made sure not to read beyond
-                // it and yet the server closed the connection on us.
-                return ERROR_IO;
-            }
-
-            break;
-        }
-    }
-
-    mOffset += numBytesRead;
-
-    return numBytesRead;
-}
-
-status_t NuHTTPDataSource::getSize(off64_t *size) {
-    *size = 0;
-
-    if (mState != CONNECTED) {
-        return ERROR_IO;
-    }
-
-    if (mContentLengthValid) {
-        *size = mContentLength;
-        return OK;
-    }
-
-    return ERROR_UNSUPPORTED;
-}
-
-uint32_t NuHTTPDataSource::flags() {
-    return kWantsPrefetching | kIsHTTPBasedSource;
-}
-
-// static
-void NuHTTPDataSource::MakeFullHeaders(
-        const KeyedVector<String8, String8> *overrides, String8 *headers) {
-    headers->setTo("");
-
-    headers->append("User-Agent: stagefright/1.1 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.build.version.release", value, "Unknown");
-    headers->append(value);
-    headers->append(")\r\n");
-
-    if (overrides == NULL) {
-        return;
-    }
-
-    for (size_t i = 0; i < overrides->size(); ++i) {
-        String8 line;
-        line.append(overrides->keyAt(i));
-        line.append(": ");
-        line.append(overrides->valueAt(i));
-        line.append("\r\n");
-
-        headers->append(line);
-    }
-}
-
-void NuHTTPDataSource::applyTimeoutResponse() {
-    AString timeout;
-    if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) {
-        const char *s = timeout.c_str();
-        char *end;
-        long tmp = strtol(s, &end, 10);
-        if (end == s || *end != '\0') {
-            LOGW("Illegal X-SocketTimeout value given.");
-            return;
-        }
-
-        LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
-        mHTTP.setReceiveTimeout(tmp);
-    }
-}
-
-sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
-    if (mDrmManagerClient == NULL) {
-        mDrmManagerClient = new DrmManagerClient();
-    }
-
-    if (mDrmManagerClient == NULL) {
-        return NULL;
-    }
-
-    if (mDecryptHandle == NULL) {
-        /* Note if redirect occurs, mUri is the redirect uri instead of the
-         * original one
-         */
-        mDecryptHandle = mDrmManagerClient->openDecryptSession(mUri);
-    }
-
-    if (mDecryptHandle == NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-
-    return mDecryptHandle;
-}
-
-void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
-    handle = mDecryptHandle;
-
-    *client = mDrmManagerClient;
-}
-
-String8 NuHTTPDataSource::getUri() {
-    return mUri;
-}
-
-String8 NuHTTPDataSource::getMIMEType() const {
-    return mContentType;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3b05752..ac73351 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -18,20 +18,11 @@
 #define LOG_TAG "OMXCodec"
 #include <utils/Log.h>
 
-#include "include/AACDecoder.h"
 #include "include/AACEncoder.h"
-#include "include/AMRNBDecoder.h"
 #include "include/AMRNBEncoder.h"
-#include "include/AMRWBDecoder.h"
 #include "include/AMRWBEncoder.h"
-#include "include/AVCDecoder.h"
 #include "include/AVCEncoder.h"
-#include "include/G711Decoder.h"
-#include "include/M4vH263Decoder.h"
 #include "include/M4vH263Encoder.h"
-#include "include/MP3Decoder.h"
-#include "include/VorbisDecoder.h"
-#include "include/VPXDecoder.h"
 
 #include "include/ESDS.h"
 
@@ -53,14 +44,14 @@
 #include <OMX_Audio.h>
 #include <OMX_Component.h>
 
-#if HAVE_SOFTWARE_DECODERS
-#include "include/ThreadedSource.h"
-#endif
-
 #include "include/avc_utils.h"
 
 namespace android {
 
+// Treat time out as an error if we have not received any output
+// buffers after 3 seconds.
+const static int64_t kBufferFilledEventTimeOutUs = 3000000000LL;
+
 struct CodecInfo {
     const char *mime;
     const char *codec;
@@ -79,24 +70,6 @@
 FACTORY_CREATE_ENCODER(AVCEncoder)
 FACTORY_CREATE_ENCODER(M4vH263Encoder)
 
-#if HAVE_SOFTWARE_DECODERS
-
-#define FACTORY_CREATE(name) \
-static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
-    return new name(source); \
-}
-
-FACTORY_CREATE(AMRNBDecoder)
-FACTORY_CREATE(AMRWBDecoder)
-FACTORY_CREATE(AACDecoder)
-FACTORY_CREATE(AVCDecoder)
-FACTORY_CREATE(G711Decoder)
-FACTORY_CREATE(MP3Decoder)
-FACTORY_CREATE(M4vH263Decoder)
-FACTORY_CREATE(VorbisDecoder)
-FACTORY_CREATE(VPXDecoder)
-#endif
-
 static sp<MediaSource> InstantiateSoftwareEncoder(
         const char *name, const sp<MediaSource> &source,
         const sp<MetaData> &meta) {
@@ -122,40 +95,6 @@
     return NULL;
 }
 
-static sp<MediaSource> InstantiateSoftwareCodec(
-        const char *name, const sp<MediaSource> &source) {
-#if HAVE_SOFTWARE_DECODERS
-    struct FactoryInfo {
-        const char *name;
-        sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
-    };
-
-    static const FactoryInfo kFactoryInfo[] = {
-        FACTORY_REF(AMRNBDecoder)
-        FACTORY_REF(AMRWBDecoder)
-        FACTORY_REF(AACDecoder)
-        FACTORY_REF(AVCDecoder)
-        FACTORY_REF(G711Decoder)
-        FACTORY_REF(MP3Decoder)
-        FACTORY_REF(M4vH263Decoder)
-        FACTORY_REF(VorbisDecoder)
-        FACTORY_REF(VPXDecoder)
-    };
-    for (size_t i = 0;
-         i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
-        if (!strcmp(name, kFactoryInfo[i].name)) {
-            if (!strcmp(name, "VPXDecoder")) {
-                return new ThreadedSource(
-                        (*kFactoryInfo[i].CreateFunc)(source));
-            }
-            return (*kFactoryInfo[i].CreateFunc)(source);
-        }
-    }
-#endif
-
-    return NULL;
-}
-
 #undef FACTORY_REF
 #undef FACTORY_CREATE
 
@@ -163,23 +102,17 @@
     { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
 //    { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
     { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
 //    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
 //    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
 //    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
 //    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
     { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
     { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
@@ -187,14 +120,12 @@
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
-    { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
-    { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
@@ -203,11 +134,8 @@
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.h264.decoder" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" },
-    { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
     { MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
-    { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
     { MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
-    { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" },
 };
 
@@ -518,14 +446,15 @@
     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
         componentName = matchingCodecs[i].string();
 
-        sp<MediaSource> softwareCodec = createEncoder?
-            InstantiateSoftwareEncoder(componentName, source, meta):
-            InstantiateSoftwareCodec(componentName, source);
+        if (createEncoder) {
+            sp<MediaSource> softwareCodec =
+                InstantiateSoftwareEncoder(componentName, source, meta);
 
-        if (softwareCodec != NULL) {
-            LOGV("Successfully allocated software codec '%s'", componentName);
+            if (softwareCodec != NULL) {
+                LOGV("Successfully allocated software codec '%s'", componentName);
 
-            return softwareCodec;
+                return softwareCodec;
+            }
         }
 
         LOGV("Attempting to allocate OMX node '%s'", componentName);
@@ -1840,6 +1769,13 @@
         return err;
     }
 
+    err = native_window_set_scaling_mode(mNativeWindow.get(),
+            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+    if (err != OK) {
+        return err;
+    }
+
     err = native_window_set_buffers_geometry(
             mNativeWindow.get(),
             def.format.video.nFrameWidth,
@@ -3259,6 +3195,16 @@
     mBufferFilled.signal();
 }
 
+status_t OMXCodec::waitForBufferFilled_l() {
+    status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutUs);
+    if (err != OK) {
+        LOGE("Timed out waiting for buffers from video encoder: %d/%d",
+            countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+            countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
+    }
+    return err;
+}
+
 void OMXCodec::setRawAudioFormat(
         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
 
@@ -3614,7 +3560,7 @@
 }
 
 status_t OMXCodec::stop() {
-    CODEC_LOGI("stop mState=%d", mState);
+    CODEC_LOGV("stop mState=%d", mState);
 
     Mutex::Autolock autoLock(mLock);
 
@@ -3676,7 +3622,6 @@
         mLeftOverBuffer = NULL;
     }
 
-    CODEC_LOGI("stopping video source");
     mSource->stop();
 
     CODEC_LOGI("stopped in state %d", mState);
@@ -3692,6 +3637,7 @@
 
 status_t OMXCodec::read(
         MediaBuffer **buffer, const ReadOptions *options) {
+    status_t err = OK;
     *buffer = NULL;
 
     Mutex::Autolock autoLock(mLock);
@@ -3732,7 +3678,9 @@
 
     if (seeking) {
         while (mState == RECONFIGURING) {
-            mBufferFilled.wait(mLock);
+            if ((err = waitForBufferFilled_l()) != OK) {
+                return err;
+            }
         }
 
         if (mState != EXECUTING) {
@@ -3763,19 +3711,15 @@
         }
 
         while (mSeekTimeUs >= 0) {
-            mBufferFilled.wait(mLock);
+            if ((err = waitForBufferFilled_l()) != OK) {
+                return err;
+            }
         }
     }
 
     while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
-        if (mIsEncoder) {
-            if (NO_ERROR != mBufferFilled.waitRelative(mLock, 3000000000LL)) {
-                LOGW("Timed out waiting for buffers from video encoder: %d/%d",
-                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
-                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
-            }
-        } else {
-            mBufferFilled.wait(mLock);
+        if ((err = waitForBufferFilled_l()) != OK) {
+            return err;
         }
     }
 
@@ -4406,36 +4350,26 @@
 
 status_t QueryCodecs(
         const sp<IOMX> &omx,
-        const char *mime, bool queryDecoders,
+        const char *mime, bool queryDecoders, bool hwCodecOnly,
         Vector<CodecCapabilities> *results) {
+    Vector<String8> matchingCodecs;
     results->clear();
 
-    for (int index = 0;; ++index) {
-        const char *componentName;
+    OMXCodec::findMatchingCodecs(mime,
+            !queryDecoders /*createEncoder*/,
+            NULL /*matchComponentName*/,
+            hwCodecOnly ? OMXCodec::kHardwareCodecsOnly : 0 /*flags*/,
+            &matchingCodecs);
 
-        if (!queryDecoders) {
-            componentName = GetCodec(
-                    kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
-                    mime, index);
-        } else {
-            componentName = GetCodec(
-                    kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
-                    mime, index);
-        }
-
-        if (!componentName) {
-            return OK;
-        }
+    for (size_t c = 0; c < matchingCodecs.size(); c++) {
+        const char *componentName = matchingCodecs.itemAt(c).string();
 
         if (strncmp(componentName, "OMX.", 4)) {
             // Not an OpenMax component but a software codec.
 
-#if HAVE_SOFTWARE_DECODERS
             results->push();
             CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
             caps->mComponentName = componentName;
-#endif
-
             continue;
         }
 
@@ -4490,6 +4424,15 @@
 
         CHECK_EQ(omx->freeNode(node), (status_t)OK);
     }
+
+    return OK;
+}
+
+status_t QueryCodecs(
+        const sp<IOMX> &omx,
+        const char *mimeType, bool queryDecoders,
+        Vector<CodecCapabilities> *results) {
+    return QueryCodecs(omx, mimeType, queryDecoders, false /*hwCodecOnly*/, results);
 }
 
 void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
deleted file mode 100644
index 783f2d0..0000000
--- a/media/libstagefright/ShoutcastSource.cpp
+++ /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.
- */
-
-#include "include/HTTPStream.h"
-
-#include <stdlib.h>
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/ShoutcastSource.h>
-
-namespace android {
-
-ShoutcastSource::ShoutcastSource(HTTPStream *http)
-    : mHttp(http),
-      mMetaDataOffset(0),
-      mBytesUntilMetaData(0),
-      mGroup(NULL),
-      mStarted(false) {
-    AString metaint;
-    if (mHttp->find_header_value("icy-metaint", &metaint)) {
-        char *end;
-        const char *start = metaint.c_str();
-        mMetaDataOffset = strtol(start, &end, 10);
-        CHECK(end > start && *end == '\0');
-        CHECK(mMetaDataOffset > 0);
-
-        mBytesUntilMetaData = mMetaDataOffset;
-    }
-}
-
-ShoutcastSource::~ShoutcastSource() {
-    if (mStarted) {
-        stop();
-    }
-
-    delete mHttp;
-    mHttp = NULL;
-}
-
-status_t ShoutcastSource::start(MetaData *) {
-    CHECK(!mStarted);
-
-    mGroup = new MediaBufferGroup;
-    mGroup->add_buffer(new MediaBuffer(4096));  // XXX
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t ShoutcastSource::stop() {
-    CHECK(mStarted);
-
-    delete mGroup;
-    mGroup = NULL;
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> ShoutcastSource::getFormat() {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
-    meta->setInt32(kKeySampleRate, 44100);
-    meta->setInt32(kKeyChannelCount, 2);  // XXX
-
-    return meta;
-}
-
-status_t ShoutcastSource::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    CHECK(mStarted);
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        return ERROR_UNSUPPORTED;
-    }
-
-    MediaBuffer *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
-    if (err != OK) {
-        return err;
-    }
-
-    *out = buffer;
-
-    size_t num_bytes = buffer->size();
-    if (mMetaDataOffset > 0 && num_bytes > mBytesUntilMetaData) {
-        num_bytes = mBytesUntilMetaData;
-    }
-
-    ssize_t n = mHttp->receive(buffer->data(), num_bytes);
-
-    if (n <= 0) {
-        return (status_t)n;
-    }
-
-    buffer->set_range(0, n);
-
-    mBytesUntilMetaData -= (size_t)n;
-
-    if (mBytesUntilMetaData == 0) {
-        unsigned char num_16_byte_blocks = 0;
-        n = mHttp->receive((char *)&num_16_byte_blocks, 1);
-        CHECK_EQ(n, 1);
-
-        char meta[255 * 16];
-        size_t meta_size = num_16_byte_blocks * 16;
-        size_t meta_length = 0;
-        while (meta_length < meta_size) {
-            n = mHttp->receive(&meta[meta_length], meta_size - meta_length);
-            if (n <= 0) {
-                return (status_t)n;
-            }
-
-            meta_length += (size_t) n;
-        }
-
-        while (meta_length > 0 && meta[meta_length - 1] == '\0') {
-            --meta_length;
-        }
-
-        if (meta_length > 0) {
-            // Technically we should probably attach this meta data to the
-            // next buffer. XXX
-            buffer->meta_data()->setData('shou', 'shou', meta, meta_length);
-        }
-
-        mBytesUntilMetaData = mMetaDataOffset;
-    }
-
-    return OK;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 89faff7..571e8be27 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -52,13 +52,13 @@
     return false;
 }
 
-static status_t HandleMIDI(
+static MediaScanResult HandleMIDI(
         const char *filename, MediaScannerClient *client) {
     // get the library configuration and do sanity check
     const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config();
     if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
         LOGE("EAS library/header mismatch\n");
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_ERROR;
     }
     EAS_I32 temp;
 
@@ -88,34 +88,41 @@
     }
 
     if (result != EAS_SUCCESS) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     char buffer[20];
     sprintf(buffer, "%ld", temp);
-    if (!client->addStringTag("duration", buffer)) return UNKNOWN_ERROR;
-
-    return OK;
+    status_t status = client->addStringTag("duration", buffer);
+    if (status) {
+        return MEDIA_SCAN_RESULT_ERROR;
+    }
+    return MEDIA_SCAN_RESULT_OK;
 }
 
-status_t StagefrightMediaScanner::processFile(
+MediaScanResult StagefrightMediaScanner::processFile(
         const char *path, const char *mimeType,
         MediaScannerClient &client) {
     LOGV("processFile '%s'.", path);
 
     client.setLocale(locale());
     client.beginFile();
+    MediaScanResult result = processFileInternal(path, mimeType, client);
+    client.endFile();
+    return result;
+}
 
+MediaScanResult StagefrightMediaScanner::processFileInternal(
+        const char *path, const char *mimeType,
+        MediaScannerClient &client) {
     const char *extension = strrchr(path, '.');
 
     if (!extension) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     if (!FileHasAcceptableExtension(extension)) {
-        client.endFile();
-
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     if (!strcasecmp(extension, ".mid")
@@ -127,53 +134,57 @@
             || !strcasecmp(extension, ".rtx")
             || !strcasecmp(extension, ".ota")
             || !strcasecmp(extension, ".mxmf")) {
-        status_t status = HandleMIDI(path, &client);
-        if (status != OK) {
-            return status;
+        return HandleMIDI(path, &client);
+    }
+
+    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+
+    status_t status = mRetriever->setDataSource(path);
+    if (status) {
+        return MEDIA_SCAN_RESULT_ERROR;
+    }
+
+    const char *value;
+    if ((value = mRetriever->extractMetadata(
+                    METADATA_KEY_MIMETYPE)) != NULL) {
+        status = client.setMimeType(value);
+        if (status) {
+            return MEDIA_SCAN_RESULT_ERROR;
         }
-    } else {
-        sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+    }
 
-         if (mRetriever->setDataSource(path) == OK) {
-            const char *value;
-            if ((value = mRetriever->extractMetadata(
-                            METADATA_KEY_MIMETYPE)) != NULL) {
-                client.setMimeType(value);
-            }
+    struct KeyMap {
+        const char *tag;
+        int key;
+    };
+    static const KeyMap kKeyMap[] = {
+        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
+        { "discnumber", METADATA_KEY_DISC_NUMBER },
+        { "album", METADATA_KEY_ALBUM },
+        { "artist", METADATA_KEY_ARTIST },
+        { "albumartist", METADATA_KEY_ALBUMARTIST },
+        { "composer", METADATA_KEY_COMPOSER },
+        { "genre", METADATA_KEY_GENRE },
+        { "title", METADATA_KEY_TITLE },
+        { "year", METADATA_KEY_YEAR },
+        { "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]);
 
-            struct KeyMap {
-                const char *tag;
-                int key;
-            };
-            static const KeyMap kKeyMap[] = {
-                { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
-                { "discnumber", METADATA_KEY_DISC_NUMBER },
-                { "album", METADATA_KEY_ALBUM },
-                { "artist", METADATA_KEY_ARTIST },
-                { "albumartist", METADATA_KEY_ALBUMARTIST },
-                { "composer", METADATA_KEY_COMPOSER },
-                { "genre", METADATA_KEY_GENRE },
-                { "title", METADATA_KEY_TITLE },
-                { "year", METADATA_KEY_YEAR },
-                { "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]);
-
-            for (size_t i = 0; i < kNumEntries; ++i) {
-                const char *value;
-                if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
-                    client.addStringTag(kKeyMap[i].tag, value);
-                }
+    for (size_t i = 0; i < kNumEntries; ++i) {
+        const char *value;
+        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
+            status = client.addStringTag(kKeyMap[i].tag, value);
+            if (status) {
+                return MEDIA_SCAN_RESULT_ERROR;
             }
         }
     }
 
-    client.endFile();
-
-    return OK;
+    return MEDIA_SCAN_RESULT_OK;
 }
 
 char *StagefrightMediaScanner::extractAlbumArt(int fd) {
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
new file mode 100644
index 0000000..3d8c56a
--- /dev/null
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -0,0 +1,792 @@
+/*
+ * 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 "SurfaceMediaSource"
+
+#include <media/stagefright/SurfaceMediaSource.h>
+#include <ui/GraphicBuffer.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/openmax/OMX_IVCommon.h>
+#include <media/stagefright/MetadataBufferType.h>
+
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+#include <OMX_Component.h>
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
+                mDefaultWidth(bufW),
+                mDefaultHeight(bufH),
+                mPixelFormat(0),
+                mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mClientBufferCount(0),
+                mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mCurrentSlot(INVALID_BUFFER_SLOT),
+                mCurrentTimestamp(0),
+                mSynchronousMode(true),
+                mConnectedApi(NO_CONNECTED_API),
+                mFrameRate(30),
+                mStarted(false)   {
+    LOGV("SurfaceMediaSource::SurfaceMediaSource");
+    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+}
+
+SurfaceMediaSource::~SurfaceMediaSource() {
+    LOGV("SurfaceMediaSource::~SurfaceMediaSource");
+    if (mStarted) {
+        stop();
+    }
+    freeAllBuffers();
+}
+
+size_t SurfaceMediaSource::getQueuedCount() const {
+    Mutex::Autolock lock(mMutex);
+    return mQueue.size();
+}
+
+status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) {
+    if (bufferCount > NUM_BUFFER_SLOTS)
+        return BAD_VALUE;
+
+    // special-case, nothing to do
+    if (bufferCount == mBufferCount)
+        return OK;
+
+    if (!mClientBufferCount &&
+        bufferCount >= mBufferCount) {
+        // easy, we just have more buffers
+        mBufferCount = bufferCount;
+        mServerBufferCount = bufferCount;
+        mDequeueCondition.signal();
+    } else {
+        // we're here because we're either
+        // - reducing the number of available buffers
+        // - or there is a client-buffer-count in effect
+
+        // less than 2 buffers is never allowed
+        if (bufferCount < 2)
+            return BAD_VALUE;
+
+        // when there is non client-buffer-count in effect, the client is not
+        // allowed to dequeue more than one buffer at a time,
+        // so the next time they dequeue a buffer, we know that they don't
+        // own one. the actual resizing will happen during the next
+        // dequeueBuffer.
+
+        mServerBufferCount = bufferCount;
+    }
+    return OK;
+}
+
+// Called from the consumer side
+status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
+    Mutex::Autolock lock(mMutex);
+    return setBufferCountServerLocked(bufferCount);
+}
+
+status_t SurfaceMediaSource::setBufferCount(int bufferCount) {
+    LOGV("SurfaceMediaSource::setBufferCount");
+    if (bufferCount > NUM_BUFFER_SLOTS) {
+        LOGE("setBufferCount: bufferCount is larger than the number of buffer slots");
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    // Error out if the user has dequeued buffers
+    for (int i = 0 ; i < mBufferCount ; i++) {
+        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
+            LOGE("setBufferCount: client owns some buffers");
+            return INVALID_OPERATION;
+        }
+    }
+
+    if (bufferCount == 0) {
+        const int minBufferSlots = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        mClientBufferCount = 0;
+        bufferCount = (mServerBufferCount >= minBufferSlots) ?
+                mServerBufferCount : minBufferSlots;
+        return setBufferCountServerLocked(bufferCount);
+    }
+
+    // We don't allow the client to set a buffer-count less than
+    // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
+    if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
+        return BAD_VALUE;
+    }
+
+    // here we're guaranteed that the client doesn't have dequeued buffers
+    // and will release all of its buffer references.
+    freeAllBuffers();
+    mBufferCount = bufferCount;
+    mClientBufferCount = bufferCount;
+    mCurrentSlot = INVALID_BUFFER_SLOT;
+    mQueue.clear();
+    mDequeueCondition.signal();
+    return OK;
+}
+
+status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    LOGV("SurfaceMediaSource::requestBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (slot < 0 || mBufferCount <= slot) {
+        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, slot);
+        return BAD_VALUE;
+    }
+    mSlots[slot].mRequestBufferCalled = true;
+    *buf = mSlots[slot].mGraphicBuffer;
+    return NO_ERROR;
+}
+
+status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
+                                            uint32_t format, uint32_t usage) {
+    LOGV("dequeueBuffer");
+
+
+    // Check for the buffer size- the client should just use the
+    // default width and height, and not try to set those.
+    // This is needed since
+    // the getFormat() returns mDefaultWidth/ Height for the OMX. It is
+    // queried by OMX in the beginning and not every time a frame comes.
+    // Not sure if there is  a way to update the
+    // frame size while recording. So as of now, the client side
+    // sets the default values via the constructor, and the encoder is
+    // setup to encode frames of that size
+    // The design might need to change in the future.
+    // TODO: Currently just uses mDefaultWidth/Height. In the future
+    // we might declare mHeight and mWidth and check against those here.
+    if ((w != 0) || (h != 0)) {
+        LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
+                mDefaultWidth, mDefaultHeight, w, h);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    status_t returnFlags(OK);
+
+    int found, foundSync;
+    int dequeuedCount = 0;
+    bool tryAgain = true;
+    while (tryAgain) {
+        // We need to wait for the FIFO to drain if the number of buffer
+        // needs to change.
+        //
+        // The condition "number of buffer needs to change" is true if
+        // - the client doesn't care about how many buffers there are
+        // - AND the actual number of buffer is different from what was
+        //   set in the last setBufferCountServer()
+        //                         - OR -
+        //   setBufferCountServer() was set to a value incompatible with
+        //   the synchronization mode (for instance because the sync mode
+        //   changed since)
+        //
+        // As long as this condition is true AND the FIFO is not empty, we
+        // wait on mDequeueCondition.
+
+        int minBufferCountNeeded = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // wait for the FIFO to drain
+            while (!mQueue.isEmpty()) {
+                LOGV("Waiting for the FIFO to drain");
+                mDequeueCondition.wait(mMutex);
+            }
+            // need to check again since the mode could have changed
+            // while we were waiting
+            minBufferCountNeeded = mSynchronousMode ?
+                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        }
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // here we're guaranteed that mQueue is empty
+            freeAllBuffers();
+            mBufferCount = mServerBufferCount;
+            if (mBufferCount < minBufferCountNeeded)
+                mBufferCount = minBufferCountNeeded;
+            mCurrentSlot = INVALID_BUFFER_SLOT;
+            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+        }
+
+        // look for a free buffer to give to the client
+        found = INVALID_BUFFER_SLOT;
+        foundSync = INVALID_BUFFER_SLOT;
+        dequeuedCount = 0;
+        for (int i = 0; i < mBufferCount; i++) {
+            const int state = mSlots[i].mBufferState;
+            if (state == BufferSlot::DEQUEUED) {
+                dequeuedCount++;
+                continue; // won't be continuing if could
+                // dequeue a non 'FREE' current slot like
+                // that in SurfaceTexture
+            }
+            // In case of Encoding, we do not deque the mCurrentSlot buffer
+            //  since we follow synchronous mode (unlike possibly in
+            //  SurfaceTexture that could be using the asynch mode
+            //  or has some mechanism in GL to be able to wait till the
+            //  currentslot is done using the data)
+            // Here, we have to wait for the MPEG4Writer(or equiv)
+            // to tell us when it's done using the current buffer
+            if (state == BufferSlot::FREE) {
+                foundSync = i;
+                // Unlike that in SurfaceTexture,
+                // We don't need to worry if it is the
+                // currentslot or not as it is in state FREE
+                found = i;
+                break;
+            }
+        }
+
+        // clients are not allowed to dequeue more than one buffer
+        // if they didn't set a buffer count.
+        if (!mClientBufferCount && dequeuedCount) {
+            return -EINVAL;
+        }
+
+        // See whether a buffer has been queued since the last setBufferCount so
+        // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
+        bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
+        if (bufferHasBeenQueued) {
+            // make sure the client is not trying to dequeue more buffers
+            // than allowed.
+            const int avail = mBufferCount - (dequeuedCount+1);
+            if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+                LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+                        dequeuedCount);
+                return -EBUSY;
+            }
+        }
+
+        // we're in synchronous mode and didn't find a buffer, we need to wait
+        // for for some buffers to be consumed
+        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+        if (tryAgain) {
+            LOGW("Waiting..In synchronous mode and no buffer to dQ");
+            mDequeueCondition.wait(mMutex);
+        }
+    }
+
+    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+        found = foundSync;
+    }
+
+    if (found == INVALID_BUFFER_SLOT) {
+        return -EBUSY;
+    }
+
+    const int buf = found;
+    *outBuf = found;
+
+    const bool useDefaultSize = !w && !h;
+    if (useDefaultSize) {
+        // use the default size
+        w = mDefaultWidth;
+        h = mDefaultHeight;
+    }
+
+    const bool updateFormat = (format != 0);
+    if (!updateFormat) {
+        // keep the current (or default) format
+        format = mPixelFormat;
+    }
+
+    // buffer is now in DEQUEUED (but can also be current at the same time,
+    // if we're in synchronous mode)
+    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+
+    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+    if ((buffer == NULL) ||
+        (uint32_t(buffer->width)  != w) ||
+        (uint32_t(buffer->height) != h) ||
+        (uint32_t(buffer->format) != format) ||
+        ((uint32_t(buffer->usage) & usage) != usage)) {
+            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+            status_t error;
+            sp<GraphicBuffer> graphicBuffer(
+                    mGraphicBufferAlloc->createGraphicBuffer(
+                                    w, h, format, usage, &error));
+            if (graphicBuffer == 0) {
+                LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+                return error;
+            }
+            if (updateFormat) {
+                mPixelFormat = format;
+            }
+            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mRequestBufferCalled = false;
+            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+    }
+    return returnFlags;
+}
+
+status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = OK;
+    if (!enabled) {
+        // going to asynchronous mode, drain the queue
+        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
+            mDequeueCondition.wait(mMutex);
+        }
+    }
+
+    if (mSynchronousMode != enabled) {
+        // - if we're going to asynchronous mode, the queue is guaranteed to be
+        // empty here
+        // - if the client set the number of buffers, we're guaranteed that
+        // we have at least 3 (because we don't allow less)
+        mSynchronousMode = enabled;
+        mDequeueCondition.signal();
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::connect(int api) {
+    LOGV("SurfaceMediaSource::connect");
+    Mutex::Autolock lock(mMutex);
+    status_t err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi != NO_CONNECTED_API) {
+                err = -EINVAL;
+            } else {
+                mConnectedApi = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::disconnect(int api) {
+    LOGV("SurfaceMediaSource::disconnect");
+    Mutex::Autolock lock(mMutex);
+    status_t err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi == api) {
+                mConnectedApi = NO_CONNECTED_API;
+            } else {
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
+        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+    LOGV("queueBuffer");
+
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || buf >= mBufferCount) {
+        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return -EINVAL;
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
+        return -EINVAL;
+    } else if (!mSlots[buf].mRequestBufferCalled) {
+        LOGE("queueBuffer: slot %d was enqueued without requesting a "
+                "buffer", buf);
+        return -EINVAL;
+    }
+
+    if (mSynchronousMode) {
+        // in synchronous mode we queue all buffers in a FIFO
+        mQueue.push_back(buf);
+        LOGV("Client queued buffer on slot: %d, Q size = %d",
+                                                buf, mQueue.size());
+    } else {
+        // in asynchronous mode we only keep the most recent buffer
+        if (mQueue.empty()) {
+            mQueue.push_back(buf);
+        } else {
+            Fifo::iterator front(mQueue.begin());
+            // buffer currently queued is freed
+            mSlots[*front].mBufferState = BufferSlot::FREE;
+            // and we record the new buffer index in the queued list
+            *front = buf;
+        }
+    }
+
+    mSlots[buf].mBufferState = BufferSlot::QUEUED;
+    mSlots[buf].mTimestamp = timestamp;
+    // TODO: (Confirm) Don't want to signal dequeue here.
+    // May be just in asynchronous mode?
+    // mDequeueCondition.signal();
+
+    // Once the queuing is done, we need to let the listener
+    // and signal the buffer consumer (encoder) know that a
+    // buffer is available
+    onFrameReceivedLocked();
+
+    *outWidth = mDefaultWidth;
+    *outHeight = mDefaultHeight;
+    *outTransform = 0;
+
+    return OK;
+}
+
+
+// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+// or listeners that a frame has been received
+// It is supposed to be called only from queuebuffer.
+// The buffer is NOT made available for dequeueing immediately. We need to
+// wait to hear from StageFrightRecorder to set the buffer FREE
+// Make sure this is called when the mutex is locked
+status_t SurfaceMediaSource::onFrameReceivedLocked() {
+    LOGV("On Frame Received");
+    // Signal the encoder that a new frame has arrived
+    mFrameAvailableCondition.signal();
+
+    // call back the listener
+    // TODO: The listener may not be needed in SurfaceMediaSource at all.
+    // This can be made a SurfaceTexture specific thing
+    sp<FrameAvailableListener> listener;
+    if (mSynchronousMode || mQueue.empty()) {
+        listener = mFrameAvailableListener;
+    }
+
+    if (listener != 0) {
+        listener->onFrameAvailable();
+    }
+    return OK;
+}
+
+
+void SurfaceMediaSource::cancelBuffer(int buf) {
+    LOGV("SurfaceMediaSource::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || buf >= mBufferCount) {
+        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return;
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
+        return;
+    }
+    mSlots[buf].mBufferState = BufferSlot::FREE;
+    mDequeueCondition.signal();
+}
+
+nsecs_t SurfaceMediaSource::getTimestamp() {
+    LOGV("SurfaceMediaSource::getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
+
+void SurfaceMediaSource::setFrameAvailableListener(
+        const sp<FrameAvailableListener>& listener) {
+    LOGV("SurfaceMediaSource::setFrameAvailableListener");
+    Mutex::Autolock lock(mMutex);
+    mFrameAvailableListener = listener;
+}
+
+void SurfaceMediaSource::freeAllBuffers() {
+    LOGV("freeAllBuffers");
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mGraphicBuffer = 0;
+        mSlots[i].mBufferState = BufferSlot::FREE;
+    }
+}
+
+sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentBuf;
+}
+
+int SurfaceMediaSource::query(int what, int* outValue)
+{
+    LOGV("query");
+    Mutex::Autolock lock(mMutex);
+    int value;
+    switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+        value = mDefaultWidth;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+            value = mCurrentBuf->width;
+        break;
+    case NATIVE_WINDOW_HEIGHT:
+        value = mDefaultHeight;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+            value = mCurrentBuf->height;
+        break;
+    case NATIVE_WINDOW_FORMAT:
+        value = mPixelFormat;
+        break;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+        value = mSynchronousMode ?
+                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+        break;
+    default:
+        return BAD_VALUE;
+    }
+    outValue[0] = value;
+    return NO_ERROR;
+}
+
+void SurfaceMediaSource::dump(String8& result) const
+{
+    char buffer[1024];
+    dump(result, "", buffer, 1024);
+}
+
+void SurfaceMediaSource::dump(String8& result, const char* prefix,
+        char* buffer, size_t SIZE) const
+{
+    Mutex::Autolock _l(mMutex);
+    snprintf(buffer, SIZE,
+            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+            "mPixelFormat=%d, \n",
+            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
+            mPixelFormat);
+    result.append(buffer);
+
+    String8 fifo;
+    int fifoSize = 0;
+    Fifo::const_iterator i(mQueue.begin());
+    while (i != mQueue.end()) {
+        snprintf(buffer, SIZE, "%02d ", *i++);
+        fifoSize++;
+        fifo.append(buffer);
+    }
+
+    result.append(buffer);
+
+    struct {
+        const char * operator()(int state) const {
+            switch (state) {
+                case BufferSlot::DEQUEUED: return "DEQUEUED";
+                case BufferSlot::QUEUED: return "QUEUED";
+                case BufferSlot::FREE: return "FREE";
+                default: return "Unknown";
+            }
+        }
+    } stateName;
+
+    for (int i = 0; i < mBufferCount; i++) {
+        const BufferSlot& slot(mSlots[i]);
+        snprintf(buffer, SIZE,
+                "%s%s[%02d] state=%-8s, "
+                "timestamp=%lld\n",
+                prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
+                slot.mTimestamp
+        );
+        result.append(buffer);
+    }
+}
+
+status_t SurfaceMediaSource::setFrameRate(int32_t fps)
+{
+    Mutex::Autolock lock(mMutex);
+    const int MAX_FRAME_RATE = 60;
+    if (fps < 0 || fps > MAX_FRAME_RATE) {
+        return BAD_VALUE;
+    }
+    mFrameRate = fps;
+    return OK;
+}
+
+bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
+    LOGV("isMetaDataStoredInVideoBuffers");
+    return true;
+}
+
+int32_t SurfaceMediaSource::getFrameRate( ) const {
+    Mutex::Autolock lock(mMutex);
+    return mFrameRate;
+}
+
+status_t SurfaceMediaSource::start(MetaData *params)
+{
+    LOGV("start");
+    Mutex::Autolock lock(mMutex);
+    CHECK(!mStarted);
+    mStarted = true;
+    return OK;
+}
+
+
+status_t SurfaceMediaSource::stop()
+{
+    LOGV("Stop");
+
+    Mutex::Autolock lock(mMutex);
+    // TODO: Add waiting on mFrameCompletedCondition here?
+    mStarted = false;
+    mFrameAvailableCondition.signal();
+
+    return OK;
+}
+
+sp<MetaData> SurfaceMediaSource::getFormat()
+{
+    LOGV("getFormat");
+    Mutex::Autolock autoLock(mMutex);
+    sp<MetaData> meta = new MetaData;
+
+    meta->setInt32(kKeyWidth, mDefaultWidth);
+    meta->setInt32(kKeyHeight, mDefaultHeight);
+    // The encoder format is set as an opaque colorformat
+    // The encoder will later find out the actual colorformat
+    // from the GL Frames itself.
+    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
+    meta->setInt32(kKeyStride, mDefaultWidth);
+    meta->setInt32(kKeySliceHeight, mDefaultHeight);
+    meta->setInt32(kKeyFrameRate, mFrameRate);
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+    return meta;
+}
+
+status_t SurfaceMediaSource::read( MediaBuffer **buffer,
+                                const ReadOptions *options)
+{
+    LOGV("Read. Size of queued buffer: %d", mQueue.size());
+    *buffer = NULL;
+
+    Mutex::Autolock autoLock(mMutex) ;
+    // If the recording has started and the queue is empty, then just
+    // wait here till the frames come in from the client side
+    while (mStarted && mQueue.empty()) {
+        LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
+        mFrameAvailableCondition.wait(mMutex);
+    }
+
+    // If the loop was exited as a result of stopping the recording,
+    // it is OK
+    if (!mStarted) {
+        return OK;
+    }
+
+    // Update the current buffer info
+    // TODO: mCurrentSlot can be made a bufferstate since there
+    // can be more than one "current" slots.
+    Fifo::iterator front(mQueue.begin());
+    mCurrentSlot = *front;
+    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
+    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
+
+    // Pass the data to the MediaBuffer. Pass in only the metadata
+    passMetadataBufferLocked(buffer);
+
+    (*buffer)->setObserver(this);
+    (*buffer)->add_ref();
+    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
+
+    return OK;
+}
+
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+    LOGV("passMetadataBuffer");
+    // MediaBuffer allocates and owns this data
+    MediaBuffer *tempBuffer =
+        new MediaBuffer(4 + sizeof(buffer_handle_t));
+    char *data = (char *)tempBuffer->data();
+    if (data == NULL) {
+        LOGE("Cannot allocate memory for passing buffer metadata!");
+        return;
+    }
+    OMX_U32 type = kMetadataBufferTypeGrallocSource;
+    memcpy(data, &type, 4);
+    memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+    *buffer = tempBuffer;
+}
+
+
+void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
+    LOGV("signalBufferReturned");
+
+    bool foundBuffer = false;
+    Mutex::Autolock autoLock(mMutex);
+
+    if (!mStarted) {
+        LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
+        return;
+    }
+
+    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
+        CHECK(mSlots[*it].mGraphicBuffer != NULL);
+        if (checkBufferMatchesSlot(*it, buffer)) {
+            mSlots[*it].mBufferState = BufferSlot::FREE;
+            mQueue.erase(it);
+            buffer->setObserver(0);
+            buffer->release();
+            mDequeueCondition.signal();
+            mFrameCompleteCondition.signal();
+            foundBuffer = true;
+            break;
+        }
+    }
+
+    if (!foundBuffer) {
+        CHECK_EQ(0, "signalBufferReturned: bogus buffer");
+    }
+}
+
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+    LOGV("Check if Buffer matches slot");
+    // need to convert to char* for pointer arithmetic and then
+    // copy the byte stream into our handle
+    buffer_handle_t bufferHandle ;
+    memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+    return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
+}
+
+
+} // end of namespace android
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
deleted file mode 100644
index 38c6e2d..0000000
--- a/media/libstagefright/ThreadedSource.cpp
+++ /dev/null
@@ -1,213 +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.
- */
-
-#define LOG_TAG "ThreadedSource"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "include/ThreadedSource.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const size_t kMaxQueueSize = 2;
-
-ThreadedSource::ThreadedSource(const sp<MediaSource> &source)
-    : mSource(source),
-      mReflector(new AHandlerReflector<ThreadedSource>(this)),
-      mLooper(new ALooper),
-      mStarted(false) {
-    mLooper->registerHandler(mReflector);
-}
-
-ThreadedSource::~ThreadedSource() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t ThreadedSource::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    status_t err = mSource->start(params);
-
-    if (err != OK) {
-        return err;
-    }
-
-    mFinalResult = OK;
-    mSeekTimeUs = -1;
-    mDecodePending = false;
-
-    Mutex::Autolock autoLock(mLock);
-    postDecodeMore_l();
-
-    CHECK_EQ(mLooper->start(), (status_t)OK);
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t ThreadedSource::stop() {
-    CHECK(mStarted);
-
-    CHECK_EQ(mLooper->stop(), (status_t)OK);
-
-    Mutex::Autolock autoLock(mLock);
-    clearQueue_l();
-
-    status_t err = mSource->stop();
-
-    mStarted = false;
-
-    return err;
-}
-
-sp<MetaData> ThreadedSource::getFormat() {
-    return mSource->getFormat();
-}
-
-status_t ThreadedSource::read(
-        MediaBuffer **buffer, const ReadOptions *options) {
-    *buffer = NULL;
-
-    Mutex::Autolock autoLock(mLock);
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode seekMode;
-    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
-        int32_t seekComplete = 0;
-
-        sp<AMessage> msg = new AMessage(kWhatSeek, mReflector->id());
-        msg->setInt64("timeUs", seekTimeUs);
-        msg->setInt32("mode", seekMode);
-        msg->setPointer("complete", &seekComplete);
-        msg->post();
-
-        while (!seekComplete) {
-            mCondition.wait(mLock);
-        }
-    }
-
-    while (mQueue.empty() && mFinalResult == OK) {
-        mCondition.wait(mLock);
-    }
-
-    if (!mQueue.empty()) {
-        *buffer = *mQueue.begin();
-        mQueue.erase(mQueue.begin());
-
-        if (mFinalResult == OK) {
-            postDecodeMore_l();
-        }
-
-        return OK;
-    }
-
-    return mFinalResult;
-}
-
-void ThreadedSource::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatSeek:
-        {
-            CHECK(msg->findInt64("timeUs", &mSeekTimeUs));
-            CHECK_GE(mSeekTimeUs, 0ll);
-
-            int32_t x;
-            CHECK(msg->findInt32("mode", &x));
-            mSeekMode = (ReadOptions::SeekMode)x;
-
-            int32_t *seekComplete;
-            CHECK(msg->findPointer("complete", (void **)&seekComplete));
-
-            Mutex::Autolock autoLock(mLock);
-            clearQueue_l();
-            mFinalResult = OK;
-
-            *seekComplete = 1;
-            mCondition.signal();
-
-            postDecodeMore_l();
-            break;
-        }
-
-        case kWhatDecodeMore:
-        {
-            {
-                Mutex::Autolock autoLock(mLock);
-                mDecodePending = false;
-
-                if (mQueue.size() == kMaxQueueSize) {
-                    break;
-                }
-            }
-
-            MediaBuffer *buffer;
-            ReadOptions options;
-            if (mSeekTimeUs >= 0) {
-                options.setSeekTo(mSeekTimeUs, mSeekMode);
-                mSeekTimeUs = -1ll;
-            }
-            status_t err = mSource->read(&buffer, &options);
-
-            Mutex::Autolock autoLock(mLock);
-
-            if (err != OK) {
-                mFinalResult = err;
-            } else {
-                mQueue.push_back(buffer);
-
-                if (mQueue.size() < kMaxQueueSize) {
-                    postDecodeMore_l();
-                }
-            }
-
-            mCondition.signal();
-            break;
-        }
-
-        default:
-            TRESPASS();
-            break;
-    }
-}
-
-void ThreadedSource::postDecodeMore_l() {
-    if (mDecodePending) {
-        return;
-    }
-
-    mDecodePending = true;
-    (new AMessage(kWhatDecodeMore, mReflector->id()))->post();
-}
-
-void ThreadedSource::clearQueue_l() {
-    while (!mQueue.empty()) {
-        MediaBuffer *buffer = *mQueue.begin();
-        mQueue.erase(mQueue.begin());
-
-        buffer->release();
-        buffer = NULL;
-    }
-}
-
-}  // namespace android
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index bf978d7..c406964 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -370,7 +370,9 @@
 
             int16_t *dst = (int16_t *)tmp->data();
             const uint8_t *src = (const uint8_t *)buffer->data();
-            while (n-- > 0) {
+            ssize_t numBytes = n;
+
+            while (numBytes-- > 0) {
                 *dst++ = ((int16_t)(*src) - 128) * 256;
                 ++src;
             }
diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp
index 0d0d6c2..2091381 100644
--- a/media/libstagefright/XINGSeeker.cpp
+++ b/media/libstagefright/XINGSeeker.cpp
@@ -24,8 +24,8 @@
 static bool parse_xing_header(
         const sp<DataSource> &source, off64_t first_frame_pos,
         int32_t *frame_number = NULL, int32_t *byte_number = NULL,
-        char *table_of_contents = NULL, int32_t *quality_indicator = NULL,
-        int64_t *duration = NULL);
+        unsigned char *table_of_contents = NULL,
+        int32_t *quality_indicator = NULL, int64_t *duration = NULL);
 
 // static
 sp<XINGSeeker> XINGSeeker::CreateFromSource(
@@ -94,7 +94,7 @@
 static bool parse_xing_header(
         const sp<DataSource> &source, off64_t first_frame_pos,
         int32_t *frame_number, int32_t *byte_number,
-        char *table_of_contents, int32_t *quality_indicator,
+        unsigned char *table_of_contents, int32_t *quality_indicator,
         int64_t *duration) {
     if (frame_number) {
         *frame_number = 0;
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 588a74d..07a9eb8 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -25,6 +25,8 @@
 
 #include "support.h"
 
+#include <cutils/properties.h> // for property_get
+
 namespace android {
 
 ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
@@ -111,7 +113,7 @@
     mState = DISCONNECTED;
     mCondition.broadcast();
 
-    mURI.clear();
+    // mURI.clear();
 
     mIOResult = err;
 
@@ -150,9 +152,19 @@
     Mutex::Autolock autoLock(mLock);
 
     if (mState != CONNECTED) {
-        return ERROR_NOT_CONNECTED;
+        return INVALID_OPERATION;
     }
 
+#if 0
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.disable-net", value, 0)
+            && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down.");
+        disconnect_l();
+        return ERROR_IO;
+    }
+#endif
+
     if (offset != mCurrentOffset) {
         AString tmp = mURI;
         KeyedVector<String8, String8> tmpHeaders = mHeaders;
@@ -236,7 +248,7 @@
     CHECK_EQ((int)mState, (int)DISCONNECTING);
 
     mState = DISCONNECTED;
-    mURI.clear();
+    // mURI.clear();
 
     mCondition.broadcast();
 
@@ -299,5 +311,21 @@
     }
 }
 
+status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mURI.empty()) {
+        return INVALID_OPERATION;
+    }
+
+    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting...");
+    status_t err = connect_l(mURI.c_str(), &mHeaders, offset);
+    if (err != OK) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err);
+    }
+
+    return err;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index f4b3668..eb10ab7 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -25,6 +25,7 @@
 #include "android/net/android_network_library_impl.h"
 #include "base/threading/thread.h"
 #include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
 #include "net/base/host_resolver.h"
 #include "net/base/ssl_config_service.h"
 #include "net/http/http_auth_handler_factory.h"
@@ -140,6 +141,8 @@
             network_delegate(),
             net_log(),
             NULL));  // backend_factory
+
+    set_cookie_store(new net::CookieMonster(NULL, NULL));
 }
 
 const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
deleted file mode 100644
index d2e3eaa..0000000
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ /dev/null
@@ -1,335 +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 "AACDecoder.h"
-#define LOG_TAG "AACDecoder"
-
-#include "../../include/ESDS.h"
-
-#include "pvmp4audiodecoder_api.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-AACDecoder::AACDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mConfig(new tPVMP4AudioDecoderExternal),
-      mDecoderBuf(NULL),
-      mAnchorTimeUs(0),
-      mNumSamplesOutput(0),
-      mInputBuffer(NULL) {
-
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t sampleRate;
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
-    mMeta = new MetaData;
-    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-
-    // We'll always output stereo, regardless of how many channels are
-    // present in the input due to decoder limitations.
-    mMeta->setInt32(kKeyChannelCount, 2);
-    mMeta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        mMeta->setInt64(kKeyDuration, durationUs);
-    }
-    mMeta->setCString(kKeyDecoderComponent, "AACDecoder");
-
-    mInitCheck = initCheck();
-}
-
-status_t AACDecoder::initCheck() {
-    memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
-    mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
-    mConfig->aacPlusEnabled = 1;
-
-    // The software decoder doesn't properly support mono output on
-    // AACplus files. Always output stereo.
-    mConfig->desiredChannels = 2;
-
-    UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
-    mDecoderBuf = malloc(memRequirements);
-
-    status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
-    if (err != MP4AUDEC_SUCCESS) {
-        LOGE("Failed to initialize MP4 audio decoder");
-        return UNKNOWN_ERROR;
-    }
-
-    uint32_t type;
-    const void *data;
-    size_t size;
-    sp<MetaData> meta = mSource->getFormat();
-    if (meta->findData(kKeyESDS, &type, &data, &size)) {
-        ESDS esds((const char *)data, size);
-        CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
-        const void *codec_specific_data;
-        size_t codec_specific_data_size;
-        esds.getCodecSpecificInfo(
-                &codec_specific_data, &codec_specific_data_size);
-
-        mConfig->pInputBuffer = (UChar *)codec_specific_data;
-        mConfig->inputBufferCurrentLength = codec_specific_data_size;
-        mConfig->inputBufferMaxLength = 0;
-
-        if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
-                != MP4AUDEC_SUCCESS) {
-            return ERROR_UNSUPPORTED;
-        }
-    }
-    return OK;
-}
-
-AACDecoder::~AACDecoder() {
-    if (mStarted) {
-        stop();
-    }
-
-    delete mConfig;
-    mConfig = NULL;
-}
-
-status_t AACDecoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(new MediaBuffer(4096 * 2));
-
-    mSource->start();
-
-    mAnchorTimeUs = 0;
-    mNumSamplesOutput = 0;
-    mStarted = true;
-    mNumDecodedBuffers = 0;
-    mUpsamplingFactor = 2;
-
-    return OK;
-}
-
-status_t AACDecoder::stop() {
-    CHECK(mStarted);
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    free(mDecoderBuf);
-    mDecoderBuf = NULL;
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> AACDecoder::getFormat() {
-    return mMeta;
-}
-
-status_t AACDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        CHECK(seekTimeUs >= 0);
-
-        mNumSamplesOutput = 0;
-
-        if (mInputBuffer) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-
-        // Make sure that the next buffer output does not still
-        // depend on fragments from the last one decoded.
-        PVMP4AudioDecoderResetBuffer(mDecoderBuf);
-    } else {
-        seekTimeUs = -1;
-    }
-
-    if (mInputBuffer == NULL) {
-        err = mSource->read(&mInputBuffer, options);
-
-        if (err != OK) {
-            return err;
-        }
-
-        int64_t timeUs;
-        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
-            mAnchorTimeUs = timeUs;
-            mNumSamplesOutput = 0;
-        } else {
-            // We must have a new timestamp after seeking.
-            CHECK(seekTimeUs < 0);
-        }
-    }
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
-
-    mConfig->pInputBuffer =
-        (UChar *)mInputBuffer->data() + mInputBuffer->range_offset();
-
-    mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
-    mConfig->inputBufferMaxLength = 0;
-    mConfig->inputBufferUsedLength = 0;
-    mConfig->remainderBits = 0;
-
-    mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
-    mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
-    mConfig->repositionFlag = false;
-
-    Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
-
-    /*
-     * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
-     * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
-     * rate system and the sampling rate in the final output is actually
-     * doubled compared with the core AAC decoder sampling rate.
-     *
-     * Explicit signalling is done by explicitly defining SBR audio object
-     * type in the bitstream. Implicit signalling is done by embedding
-     * SBR content in AAC extension payload specific to SBR, and hence
-     * requires an AAC decoder to perform pre-checks on actual audio frames.
-     *
-     * Thus, we could not say for sure whether a stream is
-     * AAC+/eAAC+ until the first data frame is decoded.
-     */
-    if (++mNumDecodedBuffers <= 2) {
-        LOGV("audio/extended audio object type: %d + %d",
-            mConfig->audioObjectType, mConfig->extendedAudioObjectType);
-        LOGV("aac+ upsampling factor: %d desired channels: %d",
-            mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
-
-        CHECK(mNumDecodedBuffers > 0);
-
-        if (decoderErr != MP4AUDEC_SUCCESS) {
-            // If decoding fails this early, the fields in mConfig may
-            // not be valid and we cannot recover.
-
-            LOGE("Unable to decode aac content, decoder returned error %d",
-                 decoderErr);
-
-            buffer->release();
-            buffer = NULL;
-
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
-            return ERROR_UNSUPPORTED;
-        }
-
-        if (mNumDecodedBuffers == 1) {
-            mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
-            // Check on the sampling rate to see whether it is changed.
-            int32_t sampleRate;
-            CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
-            if (mConfig->samplingRate != sampleRate) {
-                mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
-                LOGW("Sample rate was %d Hz, but now is %d Hz",
-                        sampleRate, mConfig->samplingRate);
-                buffer->release();
-                mInputBuffer->release();
-                mInputBuffer = NULL;
-                return INFO_FORMAT_CHANGED;
-            }
-        } else {  // mNumDecodedBuffers == 2
-            if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
-                mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
-                if (mUpsamplingFactor == 2) {
-                    // The stream turns out to be not aacPlus mode anyway
-                    LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
-                        mConfig->extendedAudioObjectType);
-                    mConfig->aacPlusEnabled = 0;
-                }
-            } else {
-                if (mUpsamplingFactor == 1) {
-                    // aacPlus mode does not buy us anything, but to cause
-                    // 1. CPU load to increase, and
-                    // 2. a half speed of decoding
-                    LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
-                    mConfig->aacPlusEnabled = 0;
-                }
-            }
-        }
-    }
-
-    size_t numOutBytes =
-        mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
-    if (mUpsamplingFactor == 2) {
-        if (mConfig->desiredChannels == 1) {
-            memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
-        }
-        numOutBytes *= 2;
-    }
-
-    if (decoderErr != MP4AUDEC_SUCCESS) {
-        LOGW("AAC decoder returned error %d, substituting silence", decoderErr);
-
-        memset(buffer->data(), 0, numOutBytes);
-
-        // Discard input buffer.
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-
-        // fall through
-    }
-
-    buffer->set_range(0, numOutBytes);
-
-    if (mInputBuffer != NULL) {
-        mInputBuffer->set_range(
-                mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
-                mInputBuffer->range_length() - mConfig->inputBufferUsedLength);
-
-        if (mInputBuffer->range_length() == 0) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-    }
-
-    buffer->meta_data()->setInt64(
-            kKeyTime,
-            mAnchorTimeUs
-                + (mNumSamplesOutput * 1000000) / mConfig->samplingRate);
-
-    mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor;
-
-    *out = buffer;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 359a2ec..20c7bc0 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -143,7 +143,6 @@
  	unpack_idx.cpp \
  	window_tables_fxp.cpp \
  	pvmp4setaudioconfig.cpp \
-        AACDecoder.cpp \
 
 LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= -DOSCL_UNUSED_ARG=
 
diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
index dd0b9b4..8853efc 100644
--- a/media/libstagefright/codecs/aacenc/src/bit_cnt.c
+++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
@@ -496,7 +496,7 @@
 {
 
   Word32 i, t0, t1, t2, t3, t00, t01;
-  Word16 codeWord, codeLength;
+  UWord16 codeWord, codeLength;
   Word16 sign, signLength;
 
    
diff --git a/media/libstagefright/codecs/aacenc/src/memalign.c b/media/libstagefright/codecs/aacenc/src/memalign.c
index 7d203527..44dd4ba 100644
--- a/media/libstagefright/codecs/aacenc/src/memalign.c
+++ b/media/libstagefright/codecs/aacenc/src/memalign.c
@@ -23,6 +23,11 @@
 
 
 #include	"memalign.h"
+#ifdef _MSC_VER
+#include	<stddef.h>
+#else
+#include	<stdint.h>
+#endif
 
 /*****************************************************************************
 *
@@ -66,8 +71,8 @@
 		pMemop->Set(CodecID, tmp, 0, size + alignment);
 
 		mem_ptr =
-			(unsigned char *) ((unsigned int) (tmp + alignment - 1) &
-					(~((unsigned int) (alignment - 1))));
+			(unsigned char *) ((intptr_t) (tmp + alignment - 1) &
+					(~((intptr_t) (alignment - 1))));
 
 		if (mem_ptr == tmp)
 			mem_ptr += alignment;
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
deleted file mode 100644
index a11d46b..0000000
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ /dev/null
@@ -1,208 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AMRNBDecoder"
-#include <utils/Log.h>
-
-#include "AMRNBDecoder.h"
-
-#include "gsmamr_dec.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 160;
-static const int32_t kSampleRate = 8000;
-
-AMRNBDecoder::AMRNBDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mState(NULL),
-      mAnchorTimeUs(0),
-      mNumSamplesOutput(0),
-      mInputBuffer(NULL) {
-}
-
-AMRNBDecoder::~AMRNBDecoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t AMRNBDecoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(
-            new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t)));
-
-    CHECK_EQ(GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"), 0);
-
-    mSource->start();
-
-    mAnchorTimeUs = 0;
-    mNumSamplesOutput = 0;
-    mStarted = true;
-
-    return OK;
-}
-
-status_t AMRNBDecoder::stop() {
-    CHECK(mStarted);
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    GSMDecodeFrameExit(&mState);
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> AMRNBDecoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t numChannels;
-    int32_t sampleRate;
-
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
-    CHECK_EQ(numChannels, 1);
-
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-    CHECK_EQ(sampleRate, kSampleRate);
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeyChannelCount, numChannels);
-    meta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "AMRNBDecoder");
-
-    return meta;
-}
-
-status_t AMRNBDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        CHECK(seekTimeUs >= 0);
-
-        mNumSamplesOutput = 0;
-
-        if (mInputBuffer) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-    } else {
-        seekTimeUs = -1;
-    }
-
-    if (mInputBuffer == NULL) {
-        err = mSource->read(&mInputBuffer, options);
-
-        if (err != OK) {
-            return err;
-        }
-
-        int64_t timeUs;
-        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
-            mAnchorTimeUs = timeUs;
-            mNumSamplesOutput = 0;
-        } else {
-            // We must have a new timestamp after seeking.
-            CHECK(seekTimeUs < 0);
-        }
-    }
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
-    const uint8_t *inputPtr =
-        (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
-    int32_t numBytesRead =
-        AMRDecode(mState,
-          (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
-          (UWord8 *)&inputPtr[1],
-          static_cast<int16_t *>(buffer->data()),
-          MIME_IETF);
-
-    if (numBytesRead == -1 ) {
-        LOGE("PV AMR decoder AMRDecode() call failed");
-        buffer->release();
-        buffer = NULL;
-        return ERROR_MALFORMED;
-    }
-    ++numBytesRead;  // Include the frame type header byte.
-
-    buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
-
-    if (static_cast<size_t>(numBytesRead) > mInputBuffer->range_length()) {
-        // This is bad, should never have happened, but did. Abort now.
-
-        buffer->release();
-        buffer = NULL;
-
-        return ERROR_MALFORMED;
-    }
-
-    mInputBuffer->set_range(
-            mInputBuffer->range_offset() + numBytesRead,
-            mInputBuffer->range_length() - numBytesRead);
-
-    if (mInputBuffer->range_length() == 0) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    buffer->meta_data()->setInt64(
-            kKeyTime,
-            mAnchorTimeUs
-                + (mNumSamplesOutput * 1000000) / kSampleRate);
-
-    mNumSamplesOutput += kNumSamplesPerFrame;
-
-    *out = buffer;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 5862abc..23a22ef 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        AMRNBDecoder.cpp \
  	src/a_refl.cpp \
  	src/agc.cpp \
  	src/amrdecode.cpp \
diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
deleted file mode 100644
index 5b111ef..0000000
--- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
+++ /dev/null
@@ -1,225 +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 "AMRWBDecoder.h"
-
-#include "pvamrwbdecoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 320;
-static const int32_t kSampleRate = 16000;
-
-AMRWBDecoder::AMRWBDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mState(NULL),
-      mDecoderBuf(NULL),
-      mDecoderCookie(NULL),
-      mAnchorTimeUs(0),
-      mNumSamplesOutput(0),
-      mInputBuffer(NULL) {
-}
-
-AMRWBDecoder::~AMRWBDecoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t AMRWBDecoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(
-            new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t)));
-
-    int32_t memReq = pvDecoder_AmrWbMemRequirements();
-    mDecoderBuf = malloc(memReq);
-
-    pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie);
-
-    mSource->start();
-
-    mAnchorTimeUs = 0;
-    mNumSamplesOutput = 0;
-    mStarted = true;
-
-    return OK;
-}
-
-status_t AMRWBDecoder::stop() {
-    CHECK(mStarted);
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    free(mDecoderBuf);
-    mDecoderBuf = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> AMRWBDecoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t numChannels;
-    int32_t sampleRate;
-
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
-    CHECK_EQ(numChannels, 1);
-
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-    CHECK_EQ(sampleRate, kSampleRate);
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeyChannelCount, numChannels);
-    meta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "AMRWBDecoder");
-
-    return meta;
-}
-
-static size_t getFrameSize(unsigned FT) {
-    static const size_t kFrameSizeWB[9] = {
-        132, 177, 253, 285, 317, 365, 397, 461, 477
-    };
-
-    size_t frameSize = kFrameSizeWB[FT];
-
-    // Round up bits to bytes and add 1 for the header byte.
-    frameSize = (frameSize + 7) / 8 + 1;
-
-    return frameSize;
-}
-
-status_t AMRWBDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode seekMode;
-    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
-        CHECK(seekTimeUs >= 0);
-
-        mNumSamplesOutput = 0;
-
-        if (mInputBuffer) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-    } else {
-        seekTimeUs = -1;
-    }
-
-    if (mInputBuffer == NULL) {
-        err = mSource->read(&mInputBuffer, options);
-
-        if (err != OK) {
-            return err;
-        }
-
-        int64_t timeUs;
-        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
-            mAnchorTimeUs = timeUs;
-            mNumSamplesOutput = 0;
-        } else {
-            // We must have a new timestamp after seeking.
-            CHECK(seekTimeUs < 0);
-        }
-    }
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
-    const uint8_t *inputPtr =
-        (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
-    int16 mode = ((inputPtr[0] >> 3) & 0x0f);
-    size_t frameSize = getFrameSize(mode);
-    CHECK(mInputBuffer->range_length() >= frameSize);
-
-    int16 frameType;
-    RX_State_wb rx_state;
-    mime_unsorting(
-            const_cast<uint8_t *>(&inputPtr[1]),
-            mInputSampleBuffer,
-            &frameType, &mode, 1, &rx_state);
-
-    int16_t *outPtr = (int16_t *)buffer->data();
-
-    int16_t numSamplesOutput;
-    pvDecoder_AmrWb(
-            mode, mInputSampleBuffer,
-            outPtr,
-            &numSamplesOutput,
-            mDecoderBuf, frameType, mDecoderCookie);
-
-    CHECK_EQ(numSamplesOutput, kNumSamplesPerFrame);
-
-    for (int i = 0; i < kNumSamplesPerFrame; ++i) {
-        /* Delete the 2 LSBs (14-bit output) */
-        outPtr[i] &= 0xfffC;
-    }
-
-    buffer->set_range(0, numSamplesOutput * sizeof(int16_t));
-
-    mInputBuffer->set_range(
-            mInputBuffer->range_offset() + frameSize,
-            mInputBuffer->range_length() - frameSize);
-
-    if (mInputBuffer->range_length() == 0) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    buffer->meta_data()->setInt64(
-            kKeyTime,
-            mAnchorTimeUs
-                + (mNumSamplesOutput * 1000000) / kSampleRate);
-
-    mNumSamplesOutput += kNumSamplesPerFrame;
-
-    *out = buffer;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index ab591d7..c9e1c25 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        AMRWBDecoder.cpp \
 	src/agc2_amr_wb.cpp \
  	src/band_pass_6k_7k.cpp \
  	src/dec_acelp_2p_in_64.cpp \
diff --git a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
deleted file mode 100644
index dd7c26d..0000000
--- a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- ** Copyright 2003-2010, VisualOn, Inc.
- **
- ** 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.
- */
-/*******************************************************************************
-	File:		cmnMemory.c
-
-	Content:	sample code for memory operator implementation
-
-*******************************************************************************/
-#include "cmnMemory.h"
-
-#include <malloc.h>
-#if defined LINUX
-#include <string.h>
-#endif
-
-//VO_MEM_OPERATOR		g_memOP;
-
-VO_U32 cmnMemAlloc (VO_S32 uID,  VO_MEM_INFO * pMemInfo)
-{
-	if (!pMemInfo)
-		return VO_ERR_INVALID_ARG;
-
-	pMemInfo->VBuffer = malloc (pMemInfo->Size);
-	return 0;
-}
-
-VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem)
-{
-	free (pMem);
-	return 0;
-}
-
-VO_U32	cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize)
-{
-	memset (pBuff, uValue, uSize);
-	return 0;
-}
-
-VO_U32	cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
-{
-	memcpy (pDest, pSource, uSize);
-	return 0;
-}
-
-VO_U32	cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize)
-{
-	return 0;
-}
-
-VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize)
-{
-	return memcmp(pBuffer1, pBuffer2, uSize);
-}
-
-VO_U32	cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
-{
-	memmove (pDest, pSource, uSize);
-	return 0;
-}
-
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
deleted file mode 100644
index 490129f..0000000
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ /dev/null
@@ -1,622 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AVCDecoder"
-#include <utils/Log.h>
-
-#include "AVCDecoder.h"
-
-#include "avcdec_api.h"
-#include "avcdec_int.h"
-
-#include <OMX_Component.h>
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/hexdump.h>
-
-namespace android {
-
-static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
-
-static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
-    return reinterpret_cast<int32_t>(malloc(size));
-}
-
-static void Free(void *userData, int32_t ptr) {
-    free(reinterpret_cast<void *>(ptr));
-}
-
-AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mHandle(new tagAVCHandle),
-      mInputBuffer(NULL),
-      mAnchorTimeUs(0),
-      mNumSamplesOutput(0),
-      mPendingSeekTimeUs(-1),
-      mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
-      mTargetTimeUs(-1),
-      mSPSSeen(false),
-      mPPSSeen(false) {
-    memset(mHandle, 0, sizeof(tagAVCHandle));
-    mHandle->AVCObject = NULL;
-    mHandle->userData = this;
-    mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper;
-    mHandle->CBAVC_FrameBind = BindFrameWrapper;
-    mHandle->CBAVC_FrameUnbind = UnbindFrame;
-    mHandle->CBAVC_Malloc = Malloc;
-    mHandle->CBAVC_Free = Free;
-
-    mFormat = new MetaData;
-    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
-    int32_t width, height;
-    CHECK(mSource->getFormat()->findInt32(kKeyWidth, &width));
-    CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height));
-    mFormat->setInt32(kKeyWidth, width);
-    mFormat->setInt32(kKeyHeight, height);
-    mFormat->setRect(kKeyCropRect, 0, 0, width - 1, height - 1);
-    mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
-    mFormat->setCString(kKeyDecoderComponent, "AVCDecoder");
-
-    int64_t durationUs;
-    if (mSource->getFormat()->findInt64(kKeyDuration, &durationUs)) {
-        mFormat->setInt64(kKeyDuration, durationUs);
-    }
-}
-
-AVCDecoder::~AVCDecoder() {
-    if (mStarted) {
-        stop();
-    }
-
-    PVAVCCleanUpDecoder(mHandle);
-
-    delete mHandle;
-    mHandle = NULL;
-}
-
-status_t AVCDecoder::start(MetaData *) {
-    CHECK(!mStarted);
-
-    uint32_t type;
-    const void *data;
-    size_t size;
-    sp<MetaData> meta = mSource->getFormat();
-    if (meta->findData(kKeyAVCC, &type, &data, &size)) {
-        // Parse the AVCDecoderConfigurationRecord
-
-        const uint8_t *ptr = (const uint8_t *)data;
-
-        CHECK(size >= 7);
-        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
-        uint8_t profile = ptr[1];
-        uint8_t level = ptr[3];
-
-        // There is decodable content out there that fails the following
-        // assertion, let's be lenient for now...
-        // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
-
-        size_t lengthSize = 1 + (ptr[4] & 3);
-
-        // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
-        // violates it...
-        // CHECK((ptr[5] >> 5) == 7);  // reserved
-
-        size_t numSeqParameterSets = ptr[5] & 31;
-
-        ptr += 6;
-        size -= 6;
-
-        for (size_t i = 0; i < numSeqParameterSets; ++i) {
-            CHECK(size >= 2);
-            size_t length = U16_AT(ptr);
-
-            ptr += 2;
-            size -= 2;
-
-            CHECK(size >= length);
-
-            addCodecSpecificData(ptr, length);
-
-            ptr += length;
-            size -= length;
-        }
-
-        CHECK(size >= 1);
-        size_t numPictureParameterSets = *ptr;
-        ++ptr;
-        --size;
-
-        for (size_t i = 0; i < numPictureParameterSets; ++i) {
-            CHECK(size >= 2);
-            size_t length = U16_AT(ptr);
-
-            ptr += 2;
-            size -= 2;
-
-            CHECK(size >= length);
-
-            addCodecSpecificData(ptr, length);
-
-            ptr += length;
-            size -= length;
-        }
-    }
-
-    mSource->start();
-
-    mAnchorTimeUs = 0;
-    mNumSamplesOutput = 0;
-    mPendingSeekTimeUs = -1;
-    mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
-    mTargetTimeUs = -1;
-    mSPSSeen = false;
-    mPPSSeen = false;
-    mStarted = true;
-
-    return OK;
-}
-
-void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
-    MediaBuffer *buffer = new MediaBuffer(size + 4);
-    memcpy(buffer->data(), kStartCode, 4);
-    memcpy((uint8_t *)buffer->data() + 4, data, size);
-    buffer->set_range(0, size + 4);
-
-    mCodecSpecificData.push(buffer);
-}
-
-status_t AVCDecoder::stop() {
-    CHECK(mStarted);
-
-    for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
-        (*mCodecSpecificData.editItemAt(i)).release();
-    }
-    mCodecSpecificData.clear();
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    mSource->stop();
-
-    releaseFrames();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> AVCDecoder::getFormat() {
-    return mFormat;
-}
-
-static void findNALFragment(
-        const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
-    const uint8_t *data =
-        (const uint8_t *)buffer->data() + buffer->range_offset();
-
-    size_t size = buffer->range_length();
-
-    CHECK(size >= 4);
-    CHECK(!memcmp(kStartCode, data, 4));
-
-    size_t offset = 4;
-    while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
-        ++offset;
-    }
-
-    *fragPtr = &data[4];
-    if (offset + 3 >= size) {
-        *fragSize = size - 4;
-    } else {
-        *fragSize = offset - 4;
-    }
-}
-
-MediaBuffer *AVCDecoder::drainOutputBuffer() {
-    int32_t index;
-    int32_t Release;
-    AVCFrameIO Output;
-    Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-    AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
-    if (status != AVCDEC_SUCCESS) {
-        LOGV("PVAVCDecGetOutput returned error %d", status);
-        return NULL;
-    }
-
-    CHECK(index >= 0);
-    CHECK(index < (int32_t)mFrames.size());
-
-    MediaBuffer *mbuf = mFrames.editItemAt(index);
-
-    bool skipFrame = false;
-
-    if (mTargetTimeUs >= 0) {
-        int64_t timeUs;
-        CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
-        CHECK(timeUs <= mTargetTimeUs);
-
-        if (timeUs < mTargetTimeUs) {
-            // We're still waiting for the frame with the matching
-            // timestamp and we won't return the current one.
-            skipFrame = true;
-
-            LOGV("skipping frame at %lld us", timeUs);
-        } else {
-            LOGV("found target frame at %lld us", timeUs);
-
-            mTargetTimeUs = -1;
-        }
-    }
-
-    if (!skipFrame) {
-        mbuf->set_range(0, mbuf->size());
-        mbuf->add_ref();
-
-        return mbuf;
-    }
-
-    return new MediaBuffer(0);
-}
-
-status_t AVCDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
-
-        CHECK(seekTimeUs >= 0);
-        mPendingSeekTimeUs = seekTimeUs;
-        mPendingSeekMode = mode;
-
-        if (mInputBuffer) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-
-        PVAVCDecReset(mHandle);
-    }
-
-    if (mInputBuffer == NULL) {
-        LOGV("fetching new input buffer.");
-
-        bool seeking = false;
-
-        if (!mCodecSpecificData.isEmpty()) {
-            mInputBuffer = mCodecSpecificData.editItemAt(0);
-            mCodecSpecificData.removeAt(0);
-        } else {
-            for (;;) {
-                if (mPendingSeekTimeUs >= 0) {
-                    LOGV("reading data from timestamp %lld (%.2f secs)",
-                         mPendingSeekTimeUs, mPendingSeekTimeUs / 1E6);
-                }
-
-                ReadOptions seekOptions;
-                if (mPendingSeekTimeUs >= 0) {
-                    seeking = true;
-
-                    seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode);
-                    mPendingSeekTimeUs = -1;
-                }
-                status_t err = mSource->read(&mInputBuffer, &seekOptions);
-                seekOptions.clearSeekTo();
-
-                if (err != OK) {
-                    *out = drainOutputBuffer();
-                    return (*out == NULL)  ? err : (status_t)OK;
-                }
-
-                if (mInputBuffer->range_length() > 0) {
-                    break;
-                }
-
-                mInputBuffer->release();
-                mInputBuffer = NULL;
-            }
-        }
-
-        if (seeking) {
-            int64_t targetTimeUs;
-            if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
-                    && targetTimeUs >= 0) {
-                mTargetTimeUs = targetTimeUs;
-            } else {
-                mTargetTimeUs = -1;
-            }
-        }
-    }
-
-    const uint8_t *fragPtr;
-    size_t fragSize;
-    findNALFragment(mInputBuffer, &fragPtr, &fragSize);
-
-    bool releaseFragment = true;
-    status_t err = UNKNOWN_ERROR;
-
-    int nalType;
-    int nalRefIdc;
-    AVCDec_Status res =
-        PVAVCDecGetNALType(
-                const_cast<uint8_t *>(fragPtr), fragSize,
-                &nalType, &nalRefIdc);
-
-    if (res != AVCDEC_SUCCESS) {
-        LOGV("cannot determine nal type");
-    } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS
-                || (mSPSSeen && mPPSSeen)) {
-        switch (nalType) {
-            case AVC_NALTYPE_SPS:
-            {
-                mSPSSeen = true;
-
-                res = PVAVCDecSeqParamSet(
-                        mHandle, const_cast<uint8_t *>(fragPtr),
-                        fragSize);
-
-                if (res != AVCDEC_SUCCESS) {
-                    LOGV("PVAVCDecSeqParamSet returned error %d", res);
-                    break;
-                }
-
-                AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
-
-                int32_t width =
-                    (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
-
-                int32_t height =
-                    (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
-
-                int32_t crop_left, crop_right, crop_top, crop_bottom;
-                if (pDecVid->seqParams[0]->frame_cropping_flag)
-                {
-                    crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
-                    crop_right =
-                        width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
-
-                    if (pDecVid->seqParams[0]->frame_mbs_only_flag)
-                    {
-                        crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
-                        crop_bottom =
-                            height -
-                            (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
-                    }
-                    else
-                    {
-                        crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
-                        crop_bottom =
-                            height -
-                            (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
-                    }
-                } else {
-                    crop_bottom = height - 1;
-                    crop_right = width - 1;
-                    crop_top = crop_left = 0;
-                }
-
-                int32_t prevCropLeft, prevCropTop;
-                int32_t prevCropRight, prevCropBottom;
-                if (!mFormat->findRect(
-                            kKeyCropRect,
-                            &prevCropLeft, &prevCropTop,
-                            &prevCropRight, &prevCropBottom)) {
-                    prevCropLeft = prevCropTop = 0;
-                    prevCropRight = width - 1;
-                    prevCropBottom = height - 1;
-                }
-
-                int32_t oldWidth, oldHeight;
-                CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
-                CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));
-
-                if (oldWidth != width || oldHeight != height
-                        || prevCropLeft != crop_left
-                        || prevCropTop != crop_top
-                        || prevCropRight != crop_right
-                        || prevCropBottom != crop_bottom) {
-                    mFormat->setRect(
-                            kKeyCropRect,
-                            crop_left, crop_top, crop_right, crop_bottom);
-
-                    mFormat->setInt32(kKeyWidth, width);
-                    mFormat->setInt32(kKeyHeight, height);
-
-                    err = INFO_FORMAT_CHANGED;
-                } else {
-                    *out = new MediaBuffer(0);
-                    err = OK;
-                }
-                break;
-            }
-
-            case AVC_NALTYPE_PPS:
-            {
-                mPPSSeen = true;
-
-                res = PVAVCDecPicParamSet(
-                        mHandle, const_cast<uint8_t *>(fragPtr),
-                        fragSize);
-
-                if (res != AVCDEC_SUCCESS) {
-                    LOGV("PVAVCDecPicParamSet returned error %d", res);
-                    break;
-                }
-
-                *out = new MediaBuffer(0);
-
-                err = OK;
-                break;
-            }
-
-            case AVC_NALTYPE_SLICE:
-            case AVC_NALTYPE_IDR:
-            {
-                res = PVAVCDecodeSlice(
-                        mHandle, const_cast<uint8_t *>(fragPtr),
-                        fragSize);
-
-                if (res == AVCDEC_PICTURE_OUTPUT_READY) {
-                    MediaBuffer *mbuf = drainOutputBuffer();
-                    if (mbuf == NULL) {
-                        break;
-                    }
-
-                    *out = mbuf;
-
-                    // Do _not_ release input buffer yet.
-
-                    releaseFragment = false;
-                    err = OK;
-                    break;
-                }
-
-                if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
-                    *out = new MediaBuffer(0);
-
-                    err = OK;
-                } else {
-                    LOGV("PVAVCDecodeSlice returned error %d", res);
-                }
-                break;
-            }
-
-            case AVC_NALTYPE_SEI:
-            {
-                res = PVAVCDecSEI(
-                        mHandle, const_cast<uint8_t *>(fragPtr),
-                        fragSize);
-
-                if (res != AVCDEC_SUCCESS) {
-                    break;
-                }
-
-                *out = new MediaBuffer(0);
-
-                err = OK;
-                break;
-            }
-
-            case AVC_NALTYPE_AUD:
-            case AVC_NALTYPE_FILL:
-            case AVC_NALTYPE_EOSEQ:
-            {
-                *out = new MediaBuffer(0);
-
-                err = OK;
-                break;
-            }
-
-            default:
-            {
-                LOGE("Should not be here, unknown nalType %d", nalType);
-
-                err = ERROR_MALFORMED;
-                break;
-            }
-        }
-    } else {
-        // We haven't seen SPS or PPS yet.
-
-        *out = new MediaBuffer(0);
-        err = OK;
-    }
-
-    if (releaseFragment) {
-        size_t offset = mInputBuffer->range_offset();
-        if (fragSize + 4 == mInputBuffer->range_length()) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        } else {
-            mInputBuffer->set_range(
-                    offset + fragSize + 4,
-                    mInputBuffer->range_length() - fragSize - 4);
-        }
-    }
-
-    return err;
-}
-
-// static
-int32_t AVCDecoder::ActivateSPSWrapper(
-        void *userData, unsigned int sizeInMbs, unsigned int numBuffers) {
-    return static_cast<AVCDecoder *>(userData)->activateSPS(sizeInMbs, numBuffers);
-}
-
-// static
-int32_t AVCDecoder::BindFrameWrapper(
-        void *userData, int32_t index, uint8_t **yuv) {
-    return static_cast<AVCDecoder *>(userData)->bindFrame(index, yuv);
-}
-
-// static
-void AVCDecoder::UnbindFrame(void *userData, int32_t index) {
-}
-
-int32_t AVCDecoder::activateSPS(
-        unsigned int sizeInMbs, unsigned int numBuffers) {
-    CHECK(mFrames.isEmpty());
-
-    size_t frameSize = (sizeInMbs << 7) * 3;
-    for (unsigned int i = 0; i < numBuffers; ++i) {
-        MediaBuffer *buffer = new MediaBuffer(frameSize);
-        buffer->setObserver(this);
-
-        mFrames.push(buffer);
-    }
-
-    return 1;
-}
-
-int32_t AVCDecoder::bindFrame(int32_t index, uint8_t **yuv) {
-    CHECK(index >= 0);
-    CHECK(index < (int32_t)mFrames.size());
-
-    CHECK(mInputBuffer != NULL);
-    int64_t timeUs;
-    CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-    mFrames[index]->meta_data()->setInt64(kKeyTime, timeUs);
-
-    *yuv = (uint8_t *)mFrames[index]->data();
-
-    return 1;
-}
-
-void AVCDecoder::releaseFrames() {
-    for (size_t i = 0; i < mFrames.size(); ++i) {
-        MediaBuffer *buffer = mFrames.editItemAt(i);
-
-        buffer->setObserver(NULL);
-        buffer->release();
-    }
-    mFrames.clear();
-}
-
-void AVCDecoder::signalBufferReturned(MediaBuffer *buffer) {
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/avc/dec/Android.mk b/media/libstagefright/codecs/avc/dec/Android.mk
deleted file mode 100644
index 4d4533b..0000000
--- a/media/libstagefright/codecs/avc/dec/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-        AVCDecoder.cpp \
-        src/avcdec_api.cpp \
-        src/avc_bitstream.cpp \
-        src/header.cpp \
-        src/itrans.cpp \
-        src/pred_inter.cpp \
-        src/pred_intra.cpp \
-        src/residual.cpp \
-        src/slice.cpp \
-        src/vlc.cpp
-
-LOCAL_MODULE := libstagefright_avcdec
-
-LOCAL_C_INCLUDES := \
-        $(LOCAL_PATH)/src \
-        $(LOCAL_PATH)/include \
-        $(LOCAL_PATH)/../common/include \
-        $(TOP)/frameworks/base/media/libstagefright/include \
-        frameworks/base/include/media/stagefright/openmax \
-
-LOCAL_CFLAGS := -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-        SoftAVC.cpp
-
-LOCAL_C_INCLUDES := \
-        $(LOCAL_PATH)/src \
-        $(LOCAL_PATH)/include \
-        $(LOCAL_PATH)/../common/include \
-        frameworks/base/media/libstagefright/include \
-        frameworks/base/include/media/stagefright/openmax \
-
-LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
-
-LOCAL_STATIC_LIBRARIES := \
-        libstagefright_avcdec
-
-LOCAL_SHARED_LIBRARIES := \
-        libstagefright_avc_common \
-        libstagefright libstagefright_omx libstagefright_foundation libutils
-
-LOCAL_MODULE := libstagefright_soft_avcdec
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libstagefright/codecs/avc/dec/SoftAVC.cpp b/media/libstagefright/codecs/avc/dec/SoftAVC.cpp
deleted file mode 100644
index 9f141ac..0000000
--- a/media/libstagefright/codecs/avc/dec/SoftAVC.cpp
+++ /dev/null
@@ -1,690 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SoftAVC"
-#include <utils/Log.h>
-
-#include "SoftAVC.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include "avcdec_api.h"
-#include "avcdec_int.h"
-
-namespace android {
-
-static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
-
-template<class T>
-static void InitOMXParams(T *params) {
-    params->nSize = sizeof(T);
-    params->nVersion.s.nVersionMajor = 1;
-    params->nVersion.s.nVersionMinor = 0;
-    params->nVersion.s.nRevision = 0;
-    params->nVersion.s.nStep = 0;
-}
-
-static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
-    return reinterpret_cast<int32_t>(malloc(size));
-}
-
-static void Free(void *userData, int32_t ptr) {
-    free(reinterpret_cast<void *>(ptr));
-}
-
-SoftAVC::SoftAVC(
-        const char *name,
-        const OMX_CALLBACKTYPE *callbacks,
-        OMX_PTR appData,
-        OMX_COMPONENTTYPE **component)
-    : SimpleSoftOMXComponent(name, callbacks, appData, component),
-      mHandle(new tagAVCHandle),
-      mInputBufferCount(0),
-      mWidth(160),
-      mHeight(120),
-      mCropLeft(0),
-      mCropTop(0),
-      mCropRight(mWidth - 1),
-      mCropBottom(mHeight - 1),
-      mSPSSeen(false),
-      mPPSSeen(false),
-      mCurrentTimeUs(-1),
-      mEOSStatus(INPUT_DATA_AVAILABLE),
-      mOutputPortSettingsChange(NONE) {
-    initPorts();
-    CHECK_EQ(initDecoder(), (status_t)OK);
-}
-
-SoftAVC::~SoftAVC() {
-    PVAVCCleanUpDecoder(mHandle);
-
-    delete mHandle;
-    mHandle = NULL;
-}
-
-void SoftAVC::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-
-    def.nPortIndex = 0;
-    def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumInputBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 8192;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 1;
-
-    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
-    def.format.video.pNativeRender = NULL;
-    def.format.video.nFrameWidth = mWidth;
-    def.format.video.nFrameHeight = mHeight;
-    def.format.video.nStride = def.format.video.nFrameWidth;
-    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
-    def.format.video.nBitrate = 0;
-    def.format.video.xFramerate = 0;
-    def.format.video.bFlagErrorConcealment = OMX_FALSE;
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
-    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    def.format.video.pNativeWindow = NULL;
-
-    addPort(def);
-
-    def.nPortIndex = 1;
-    def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumOutputBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
-
-    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
-    def.format.video.pNativeRender = NULL;
-    def.format.video.nFrameWidth = mWidth;
-    def.format.video.nFrameHeight = mHeight;
-    def.format.video.nStride = def.format.video.nFrameWidth;
-    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
-    def.format.video.nBitrate = 0;
-    def.format.video.xFramerate = 0;
-    def.format.video.bFlagErrorConcealment = OMX_FALSE;
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
-    def.format.video.pNativeWindow = NULL;
-
-    def.nBufferSize =
-        (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
-
-    addPort(def);
-}
-
-status_t SoftAVC::initDecoder() {
-    memset(mHandle, 0, sizeof(tagAVCHandle));
-    mHandle->AVCObject = NULL;
-    mHandle->userData = this;
-    mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper;
-    mHandle->CBAVC_FrameBind = BindFrameWrapper;
-    mHandle->CBAVC_FrameUnbind = UnbindFrame;
-    mHandle->CBAVC_Malloc = Malloc;
-    mHandle->CBAVC_Free = Free;
-
-    return OK;
-}
-
-OMX_ERRORTYPE SoftAVC::internalGetParameter(
-        OMX_INDEXTYPE index, OMX_PTR params) {
-    switch (index) {
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex != 0) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-                formatParams->xFramerate = 0;
-            } else {
-                CHECK_EQ(formatParams->nPortIndex, 1u);
-
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                formatParams->xFramerate = 0;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, params);
-    }
-}
-
-OMX_ERRORTYPE SoftAVC::internalSetParameter(
-        OMX_INDEXTYPE index, const OMX_PTR params) {
-    switch (index) {
-        case OMX_IndexParamStandardComponentRole:
-        {
-            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
-                (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
-            if (strncmp((const char *)roleParams->cRole,
-                        "video_decoder.avc",
-                        OMX_MAX_STRINGNAME_SIZE - 1)) {
-                return OMX_ErrorUndefined;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex != 0) {
-                return OMX_ErrorNoMore;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, params);
-    }
-}
-
-OMX_ERRORTYPE SoftAVC::getConfig(
-        OMX_INDEXTYPE index, OMX_PTR params) {
-    switch (index) {
-        case OMX_IndexConfigCommonOutputCrop:
-        {
-            OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
-
-            if (rectParams->nPortIndex != 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            rectParams->nLeft = mCropLeft;
-            rectParams->nTop = mCropTop;
-            rectParams->nWidth = mCropRight - mCropLeft + 1;
-            rectParams->nHeight = mCropBottom - mCropTop + 1;
-
-            return OMX_ErrorNone;
-        }
-
-        default:
-            return OMX_ErrorUnsupportedIndex;
-    }
-}
-
-static void findNALFragment(
-        const OMX_BUFFERHEADERTYPE *inHeader,
-        const uint8_t **fragPtr, size_t *fragSize) {
-    const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
-
-    size_t size = inHeader->nFilledLen;
-
-    CHECK(size >= 4);
-    CHECK(!memcmp(kStartCode, data, 4));
-
-    size_t offset = 4;
-    while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
-        ++offset;
-    }
-
-    *fragPtr = &data[4];
-    if (offset + 3 >= size) {
-        *fragSize = size - 4;
-    } else {
-        *fragSize = offset - 4;
-    }
-}
-
-void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
-    if (mOutputPortSettingsChange != NONE) {
-        return;
-    }
-
-    List<BufferInfo *> &inQueue = getPortQueue(0);
-    List<BufferInfo *> &outQueue = getPortQueue(1);
-
-    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
-        return;
-    }
-
-    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
-            && outQueue.size() == kNumOutputBuffers) {
-        if (mEOSStatus == INPUT_EOS_SEEN) {
-            OMX_BUFFERHEADERTYPE *outHeader;
-            if (drainOutputBuffer(&outHeader)) {
-                List<BufferInfo *>::iterator it = outQueue.begin();
-                while ((*it)->mHeader != outHeader) {
-                    ++it;
-                }
-
-                BufferInfo *outInfo = *it;
-                outInfo->mOwnedByUs = false;
-                outQueue.erase(it);
-                outInfo = NULL;
-
-                notifyFillBufferDone(outHeader);
-                outHeader = NULL;
-                return;
-            }
-
-            BufferInfo *outInfo = *outQueue.begin();
-            outHeader = outInfo->mHeader;
-
-            outHeader->nOffset = 0;
-            outHeader->nFilledLen = 0;
-            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
-            outHeader->nTimeStamp = 0;
-
-            outQueue.erase(outQueue.begin());
-            outInfo->mOwnedByUs = false;
-            notifyFillBufferDone(outHeader);
-
-            mEOSStatus = OUTPUT_FRAMES_FLUSHED;
-            return;
-        }
-
-        BufferInfo *inInfo = *inQueue.begin();
-        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
-
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
-            inQueue.erase(inQueue.begin());
-            inInfo->mOwnedByUs = false;
-            notifyEmptyBufferDone(inHeader);
-
-            mEOSStatus = INPUT_EOS_SEEN;
-            continue;
-        }
-
-        mCurrentTimeUs = inHeader->nTimeStamp;
-
-        const uint8_t *fragPtr;
-        size_t fragSize;
-        findNALFragment(inHeader, &fragPtr, &fragSize);
-
-        bool releaseFragment;
-        OMX_BUFFERHEADERTYPE *outHeader;
-        status_t err = decodeFragment(
-                fragPtr, fragSize,
-                &releaseFragment, &outHeader);
-
-        if (releaseFragment) {
-            CHECK_GE(inHeader->nFilledLen, fragSize + 4);
-
-            inHeader->nOffset += fragSize + 4;
-            inHeader->nFilledLen -= fragSize + 4;
-
-            if (inHeader->nFilledLen == 0) {
-                inInfo->mOwnedByUs = false;
-                inQueue.erase(inQueue.begin());
-                inInfo = NULL;
-                notifyEmptyBufferDone(inHeader);
-                inHeader = NULL;
-            }
-        }
-
-        if (outHeader != NULL) {
-            List<BufferInfo *>::iterator it = outQueue.begin();
-            while ((*it)->mHeader != outHeader) {
-                ++it;
-            }
-
-            BufferInfo *outInfo = *it;
-            outInfo->mOwnedByUs = false;
-            outQueue.erase(it);
-            outInfo = NULL;
-
-            notifyFillBufferDone(outHeader);
-            outHeader = NULL;
-            return;
-        }
-
-        if (err == INFO_FORMAT_CHANGED) {
-            return;
-        }
-
-        if (err != OK) {
-            notify(OMX_EventError, OMX_ErrorUndefined, err, NULL);
-            return;
-        }
-    }
-}
-
-status_t SoftAVC::decodeFragment(
-        const uint8_t *fragPtr, size_t fragSize,
-        bool *releaseFragment,
-        OMX_BUFFERHEADERTYPE **outHeader) {
-    *releaseFragment = true;
-    *outHeader = NULL;
-
-    int nalType;
-    int nalRefIdc;
-    AVCDec_Status res =
-        PVAVCDecGetNALType(
-                const_cast<uint8_t *>(fragPtr), fragSize,
-                &nalType, &nalRefIdc);
-
-    if (res != AVCDEC_SUCCESS) {
-        LOGV("cannot determine nal type");
-        return ERROR_MALFORMED;
-    }
-
-    if (nalType != AVC_NALTYPE_SPS && nalType != AVC_NALTYPE_PPS
-            && (!mSPSSeen || !mPPSSeen)) {
-        // We haven't seen SPS or PPS yet.
-        return OK;
-    }
-
-    switch (nalType) {
-        case AVC_NALTYPE_SPS:
-        {
-            mSPSSeen = true;
-
-            res = PVAVCDecSeqParamSet(
-                    mHandle, const_cast<uint8_t *>(fragPtr),
-                    fragSize);
-
-            if (res != AVCDEC_SUCCESS) {
-                return ERROR_MALFORMED;
-            }
-
-            AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
-
-            int32_t width =
-                (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
-
-            int32_t height =
-                (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
-
-            int32_t crop_left, crop_right, crop_top, crop_bottom;
-            if (pDecVid->seqParams[0]->frame_cropping_flag)
-            {
-                crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
-                crop_right =
-                    width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
-
-                if (pDecVid->seqParams[0]->frame_mbs_only_flag)
-                {
-                    crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
-                    crop_bottom =
-                        height -
-                        (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
-                }
-                else
-                {
-                    crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
-                    crop_bottom =
-                        height -
-                        (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
-                }
-            } else {
-                crop_bottom = height - 1;
-                crop_right = width - 1;
-                crop_top = crop_left = 0;
-            }
-
-            status_t err = OK;
-
-            if (mWidth != width || mHeight != height) {
-                mWidth = width;
-                mHeight = height;
-
-                updatePortDefinitions();
-
-                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
-                mOutputPortSettingsChange = AWAITING_DISABLED;
-
-                err = INFO_FORMAT_CHANGED;
-            }
-
-            if (mCropLeft != crop_left
-                    || mCropTop != crop_top
-                    || mCropRight != crop_right
-                    || mCropBottom != crop_bottom) {
-                mCropLeft = crop_left;
-                mCropTop = crop_top;
-                mCropRight = crop_right;
-                mCropBottom = crop_bottom;
-
-                notify(OMX_EventPortSettingsChanged,
-                       1,
-                       OMX_IndexConfigCommonOutputCrop,
-                       NULL);
-            }
-
-            return err;
-        }
-
-        case AVC_NALTYPE_PPS:
-        {
-            mPPSSeen = true;
-
-            res = PVAVCDecPicParamSet(
-                    mHandle, const_cast<uint8_t *>(fragPtr),
-                    fragSize);
-
-            if (res != AVCDEC_SUCCESS) {
-                LOGV("PVAVCDecPicParamSet returned error %d", res);
-                return ERROR_MALFORMED;
-            }
-
-            return OK;
-        }
-
-        case AVC_NALTYPE_SLICE:
-        case AVC_NALTYPE_IDR:
-        {
-            res = PVAVCDecodeSlice(
-                    mHandle, const_cast<uint8_t *>(fragPtr),
-                    fragSize);
-
-            if (res == AVCDEC_PICTURE_OUTPUT_READY) {
-                *releaseFragment = false;
-
-                if (!drainOutputBuffer(outHeader)) {
-                    return UNKNOWN_ERROR;
-                }
-
-                return OK;
-            }
-
-            if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
-                return OK;
-            } else {
-                LOGV("PVAVCDecodeSlice returned error %d", res);
-                return ERROR_MALFORMED;
-            }
-        }
-
-        case AVC_NALTYPE_SEI:
-        {
-            res = PVAVCDecSEI(
-                    mHandle, const_cast<uint8_t *>(fragPtr),
-                    fragSize);
-
-            if (res != AVCDEC_SUCCESS) {
-                return ERROR_MALFORMED;
-            }
-
-            return OK;
-        }
-
-        case AVC_NALTYPE_AUD:
-        case AVC_NALTYPE_FILL:
-        case AVC_NALTYPE_EOSEQ:
-        {
-            return OK;
-        }
-
-        default:
-        {
-            LOGE("Should not be here, unknown nalType %d", nalType);
-
-            return ERROR_MALFORMED;
-        }
-    }
-
-    return OK;
-}
-
-bool SoftAVC::drainOutputBuffer(OMX_BUFFERHEADERTYPE **outHeader) {
-    int32_t index;
-    int32_t Release;
-    AVCFrameIO Output;
-    Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-    AVCDec_Status status =
-        PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
-    if (status != AVCDEC_SUCCESS) {
-        return false;
-    }
-
-    PortInfo *port = editPortInfo(1);
-    CHECK_GE(index, 0);
-    CHECK_LT((size_t)index, port->mBuffers.size());
-    CHECK(port->mBuffers.editItemAt(index).mOwnedByUs);
-
-    *outHeader = port->mBuffers.editItemAt(index).mHeader;
-    (*outHeader)->nOffset = 0;
-    (*outHeader)->nFilledLen = port->mDef.nBufferSize;
-    (*outHeader)->nFlags = 0;
-
-    return true;
-}
-
-void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
-    if (portIndex == 0) {
-        PVAVCDecReset(mHandle);
-
-        mEOSStatus = INPUT_DATA_AVAILABLE;
-    }
-}
-
-void SoftAVC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
-    if (portIndex != 1) {
-        return;
-    }
-
-    switch (mOutputPortSettingsChange) {
-        case NONE:
-            break;
-
-        case AWAITING_DISABLED:
-        {
-            CHECK(!enabled);
-            mOutputPortSettingsChange = AWAITING_ENABLED;
-            break;
-        }
-
-        default:
-        {
-            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
-            CHECK(enabled);
-            mOutputPortSettingsChange = NONE;
-            break;
-        }
-    }
-}
-
-void SoftAVC::updatePortDefinitions() {
-    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
-    def->format.video.nFrameWidth = mWidth;
-    def->format.video.nFrameHeight = mHeight;
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-
-    def = &editPortInfo(1)->mDef;
-    def->format.video.nFrameWidth = mWidth;
-    def->format.video.nFrameHeight = mHeight;
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-
-    def->nBufferSize =
-        (def->format.video.nFrameWidth
-            * def->format.video.nFrameHeight * 3) / 2;
-}
-
-// static
-int32_t SoftAVC::ActivateSPSWrapper(
-        void *userData, unsigned int sizeInMbs, unsigned int numBuffers) {
-    return static_cast<SoftAVC *>(userData)->activateSPS(sizeInMbs, numBuffers);
-}
-
-// static
-int32_t SoftAVC::BindFrameWrapper(
-        void *userData, int32_t index, uint8_t **yuv) {
-    return static_cast<SoftAVC *>(userData)->bindFrame(index, yuv);
-}
-
-// static
-void SoftAVC::UnbindFrame(void *userData, int32_t index) {
-}
-
-int32_t SoftAVC::activateSPS(
-        unsigned int sizeInMbs, unsigned int numBuffers) {
-    PortInfo *port = editPortInfo(1);
-    CHECK_GE(port->mBuffers.size(), numBuffers);
-    CHECK_GE(port->mDef.nBufferSize, (sizeInMbs << 7) * 3);
-
-    return 1;
-}
-
-int32_t SoftAVC::bindFrame(int32_t index, uint8_t **yuv) {
-    PortInfo *port = editPortInfo(1);
-
-    CHECK_GE(index, 0);
-    CHECK_LT((size_t)index, port->mBuffers.size());
-
-    BufferInfo *outBuffer =
-        &port->mBuffers.editItemAt(index);
-
-    CHECK(outBuffer->mOwnedByUs);
-
-    outBuffer->mHeader->nTimeStamp = mCurrentTimeUs;
-    *yuv = outBuffer->mHeader->pBuffer;
-
-    return 1;
-}
-
-}  // namespace android
-
-android::SoftOMXComponent *createSoftOMXComponent(
-        const char *name, const OMX_CALLBACKTYPE *callbacks,
-        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
-    return new android::SoftAVC(name, callbacks, appData, component);
-}
diff --git a/media/libstagefright/codecs/avc/dec/SoftAVC.h b/media/libstagefright/codecs/avc/dec/SoftAVC.h
deleted file mode 100644
index 1594b4d..0000000
--- a/media/libstagefright/codecs/avc/dec/SoftAVC.h
+++ /dev/null
@@ -1,109 +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.
- */
-
-#ifndef SOFT_AVC_H_
-
-#define SOFT_AVC_H_
-
-#include "SimpleSoftOMXComponent.h"
-
-struct tagAVCHandle;
-
-namespace android {
-
-struct SoftAVC : public SimpleSoftOMXComponent {
-    SoftAVC(const char *name,
-            const OMX_CALLBACKTYPE *callbacks,
-            OMX_PTR appData,
-            OMX_COMPONENTTYPE **component);
-
-protected:
-    virtual ~SoftAVC();
-
-    virtual OMX_ERRORTYPE internalGetParameter(
-            OMX_INDEXTYPE index, OMX_PTR params);
-
-    virtual OMX_ERRORTYPE internalSetParameter(
-            OMX_INDEXTYPE index, const OMX_PTR params);
-
-    virtual OMX_ERRORTYPE getConfig(OMX_INDEXTYPE index, OMX_PTR params);
-
-    virtual void onQueueFilled(OMX_U32 portIndex);
-    virtual void onPortFlushCompleted(OMX_U32 portIndex);
-    virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
-
-private:
-    enum {
-        kNumInputBuffers  = 4,
-        kNumOutputBuffers = 18,
-    };
-
-    enum EOSStatus {
-        INPUT_DATA_AVAILABLE,
-        INPUT_EOS_SEEN,
-        OUTPUT_FRAMES_FLUSHED,
-    };
-
-    tagAVCHandle *mHandle;
-
-    size_t mInputBufferCount;
-
-    int32_t mWidth, mHeight;
-    int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
-
-    bool mSPSSeen, mPPSSeen;
-
-    int64_t mCurrentTimeUs;
-
-    EOSStatus mEOSStatus;
-
-    enum {
-        NONE,
-        AWAITING_DISABLED,
-        AWAITING_ENABLED
-    } mOutputPortSettingsChange;
-
-    void initPorts();
-    status_t initDecoder();
-
-    status_t decodeFragment(
-            const uint8_t *fragPtr, size_t fragSize,
-            bool *releaseFrames,
-            OMX_BUFFERHEADERTYPE **outHeader);
-
-    void updatePortDefinitions();
-    bool drainOutputBuffer(OMX_BUFFERHEADERTYPE **outHeader);
-
-    static int32_t ActivateSPSWrapper(
-            void *userData, unsigned int sizeInMbs, unsigned int numBuffers);
-
-    static int32_t BindFrameWrapper(
-            void *userData, int32_t index, uint8_t **yuv);
-
-    static void UnbindFrame(void *userData, int32_t index);
-
-    int32_t activateSPS(
-            unsigned int sizeInMbs, unsigned int numBuffers);
-
-    int32_t bindFrame(int32_t index, uint8_t **yuv);
-
-    DISALLOW_EVIL_CONSTRUCTORS(SoftAVC);
-};
-
-}  // namespace android
-
-#endif  // SOFT_AVC_H_
-
diff --git a/media/libstagefright/codecs/avc/dec/include/avcdec_api.h b/media/libstagefright/codecs/avc/dec/include/avcdec_api.h
deleted file mode 100644
index f6a14b7..0000000
--- a/media/libstagefright/codecs/avc/dec/include/avcdec_api.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/**
-This file contains application function interfaces to the AVC decoder library
-and necessary type defitionitions and enumerations.
-@publishedAll
-*/
-
-#ifndef _AVCDEC_API_H_
-#define _AVCDEC_API_H_
-
-#include "avcapi_common.h"
-
-/**
- This enumeration is used for the status returned from the library interface.
-*/
-typedef enum
-{
-    /**
-    The followings are fail with details. Their values are negative.
-    */
-    AVCDEC_NO_DATA = -4,
-    AVCDEC_PACKET_LOSS = -3,
-    /**
-    Fail information
-    */
-    AVCDEC_NO_BUFFER = -2, /* no output picture buffer available */
-    AVCDEC_MEMORY_FAIL = -1, /* memory allocation failed */
-    AVCDEC_FAIL = 0,
-    /**
-    Generic success value
-    */
-    AVCDEC_SUCCESS = 1,
-    AVCDEC_PICTURE_OUTPUT_READY = 2,
-    AVCDEC_PICTURE_READY = 3,
-
-    /**
-    The followings are success with warnings. Their values are positive integers.
-    */
-    AVCDEC_NO_NEXT_SC = 4,
-    AVCDEC_REDUNDANT_FRAME = 5,
-    AVCDEC_CONCEALED_FRAME = 6  /* detect and conceal the error */
-} AVCDec_Status;
-
-
-/**
-This structure contains sequence parameters information.
-*/
-typedef struct tagAVCDecSPSInfo
-{
-    int FrameWidth;
-    int FrameHeight;
-    uint frame_only_flag;
-    int  frame_crop_left;
-    int  frame_crop_right;
-    int  frame_crop_top;
-    int  frame_crop_bottom;
-
-} AVCDecSPSInfo;
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-    /** THE FOLLOWINGS ARE APIS */
-    /**
-    This function parses one NAL unit from byte stream format input according to Annex B.
-    \param "bitstream"  "Pointer to the bitstream buffer."
-    \param "nal_unit"   "Point to pointer and the location of the start of the first NAL unit
-                         found in bitstream."
-    \param "size"       "As input, the pointer to the size of bitstream in bytes. As output,
-                         the value is changed to be the size of the found NAL unit."
-    \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL if no first start code is found, AVCDEC_NO_NEX_SC if
-            the first start code is found, but the second start code is missing (potential partial NAL)."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit, int *size);
-
-    /**
-    This function sniffs the nal_unit_type such that users can call corresponding APIs.
-    \param "bitstream"  "Pointer to the beginning of a NAL unit (start with forbidden_zero_bit, etc.)."
-    \param "size"       "size of the bitstream (NumBytesInNALunit + 1)."
-    \param "nal_unit_type" "Pointer to the return value of nal unit type."
-    \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL otherwise."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetNALType(uint8 *bitstream, int size, int *nal_type, int *nal_ref_idc);
-
-    /**
-    This function decodes the sequence parameters set, initializes related parameters and
-    allocates memory (reference frames list), must also be compliant with Annex A.
-    It is equivalent to decode VOL header of MPEG4.
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    \param "nal_unit"   "Pointer to the buffer containing single NAL unit.
-                        The content will change due to EBSP-to-RBSP conversion."
-    \param "nal_size"       "size of the bitstream NumBytesInNALunit."
-    \return "AVCDEC_SUCCESS if success,
-            AVCDEC_FAIL if profile and level is not supported,
-            AVCDEC_MEMORY_FAIL if memory allocations return null."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecSeqParamSet(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
-
-    /**
-    This function returns sequence parameters such as dimension and field flag of the most recently
-    decoded SPS. More can be added later or grouped together into a structure. This API can be called
-    after PVAVCInitSequence. If no sequence parameter has been decoded yet, it will return AVCDEC_FAIL.
-
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    \param "seqInfo"    "Pointer to the AVCDecSeqParamInfo structure."
-    \return "AVCDEC_SUCCESS if success and AVCDEC_FAIL if fail."
-    \note "This API can be combined with PVAVCInitSequence if wanted to be consistent with m4vdec lib."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetSeqInfo(AVCHandle *avcHandle, AVCDecSPSInfo *seqInfo);
-
-    /**
-    This function decodes the picture parameters set and initializes related parameters. Note thate
-    the PPS may not be present for every picture.
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    \param "nal_unit"   "Pointer to the buffer containing single NAL unit.
-                        The content will change due to EBSP-to-RBSP conversion."
-    \param "nal_size"       "size of the bitstream NumBytesInNALunit."
-    \return "AVCDEC_SUCCESS if success, AVCDEC_FAIL if profile and level is not supported."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecPicParamSet(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
-
-    /**
-    This function decodes one NAL unit of bitstream. The type of nal unit is one of the
-    followings, 1, 5. (for now, no data partitioning, type 2,3,4).
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    \param "nal_unit"   "Pointer to the buffer containing a single or partial NAL unit.
-                        The content will change due to EBSP-to-RBSP conversion."
-    \param "buf_size"   "Size of the buffer (less than or equal nal_size)."
-    \param "nal_size"   "size of the current NAL unit NumBytesInNALunit."
-    \return "AVCDEC_PICTURE_READY for success and an output is ready,
-            AVCDEC_SUCCESS for success but no output is ready,
-            AVCDEC_PACKET_LOSS is GetData returns AVCDEC_PACKET_LOSS,
-            AVCDEC_FAIL if syntax error is detected,
-            AVCDEC_MEMORY_FAIL if memory is corrupted.
-            AVCDEC_NO_PICTURE if no frame memory to write to (users need to get output and/or return picture).
-            AVCDEC_REDUNDANT_PICTURE if error has been detected in the primary picture and redundant picture is available,
-            AVCDEC_CONCEALED_PICTURE if error has been detected and decoder has concealed it."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecSEI(AVCHandle *avcHandle, uint8 *nal_unit, int nal_size);
-
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecodeSlice(AVCHandle *avcHandle, uint8 *buffer, int buf_size);
-
-    /**
-    Check the availability of the decoded picture in decoding order (frame_num).
-    The AVCFrameIO also provide displaying order information such that the application
-    can re-order the frame for display. A picture can be retrieved only once.
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    \param "output"      "Pointer to the AVCOutput structure. Note that decoder library will
-                        not re-used the pixel memory in this structure until it has been returned
-                        thru PVAVCReleaseOutput API."
-    \return "AVCDEC_SUCCESS for success, AVCDEC_FAIL if no picture is available to be displayed,
-            AVCDEC_PICTURE_READY if there is another picture to be displayed."
-    */
-    OSCL_IMPORT_REF AVCDec_Status PVAVCDecGetOutput(AVCHandle *avcHandle, int *indx, int *release_flag, AVCFrameIO *output);
-
-    /**
-    This function resets the decoder and expects to see the next IDR slice.
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    */
-    OSCL_IMPORT_REF void    PVAVCDecReset(AVCHandle *avcHandle);
-
-    /**
-    This function performs clean up operation including memory deallocation.
-    \param "avcHandle"  "Handle to the AVC decoder library object."
-    */
-    OSCL_IMPORT_REF void    PVAVCCleanUpDecoder(AVCHandle *avcHandle);
-//AVCDec_Status EBSPtoRBSP(uint8 *nal_unit,int *size);
-
-
-
-    /** CALLBACK FUNCTION TO BE IMPLEMENTED BY APPLICATION */
-    /** In AVCHandle structure, userData is a pointer to an object with the following
-        member functions.
-    */
-    AVCDec_Status CBAVCDec_GetData(uint32 *userData, unsigned char **buffer, unsigned int *size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _AVCDEC_API_H_ */
-
diff --git a/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h b/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h
deleted file mode 100644
index 6b196de..0000000
--- a/media/libstagefright/codecs/avc/dec/include/pvavcdecoder.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 PVAVCDECODER_H_INCLUDED
-#define PVAVCDECODER_H_INCLUDED
-
-#ifndef PVAVCDECODERINTERFACE_H_INCLUDED
-#include "pvavcdecoderinterface.h"
-#endif
-
-// AVC video decoder
-class PVAVCDecoder : public PVAVCDecoderInterface
-{
-    public:
-        virtual ~PVAVCDecoder();
-        static  PVAVCDecoder* New(void);
-        virtual bool    InitAVCDecoder(FunctionType_SPS, FunctionType_Alloc, FunctionType_Unbind,
-                                       FunctionType_Malloc, FunctionType_Free, void *);
-        virtual void    CleanUpAVCDecoder(void);
-        virtual void    ResetAVCDecoder(void);
-        virtual int32   DecodeSPS(uint8 *bitstream, int32 buffer_size);
-        virtual int32   DecodePPS(uint8 *bitstream, int32 buffer_size);
-        virtual int32   DecodeAVCSlice(uint8 *bitstream, int32 *buffer_size);
-        virtual bool    GetDecOutput(int *indx, int *release);
-        virtual void    GetVideoDimensions(int32 *width, int32 *height, int32 *top, int32 *left, int32 *bottom, int32 *right);
-        int     AVC_Malloc(int32 size, int attribute);
-        void    AVC_Free(int mem);
-
-    private:
-        PVAVCDecoder();
-        bool Construct(void);
-        void *iAVCHandle;
-};
-
-#endif
diff --git a/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h b/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h
deleted file mode 100644
index 027212d..0000000
--- a/media/libstagefright/codecs/avc/dec/include/pvavcdecoderinterface.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 PVAVCDECODERINTERFACE_H_INCLUDED
-#define PVAVCDECODERINTERFACE_H_INCLUDED
-
-typedef void (*FunctionType_Unbind)(void *, int);
-typedef int (*FunctionType_Alloc)(void *, int, uint8 **);
-typedef int (*FunctionType_SPS)(void *, uint, uint);
-typedef int (*FunctionType_Malloc)(void *, int32, int);
-typedef void(*FunctionType_Free)(void *, int);
-
-
-// PVAVCDecoderInterface pure virtual interface class
-class PVAVCDecoderInterface
-{
-    public:
-        virtual ~PVAVCDecoderInterface() {};
-        virtual bool    InitAVCDecoder(FunctionType_SPS, FunctionType_Alloc, FunctionType_Unbind,
-                                       FunctionType_Malloc, FunctionType_Free, void *) = 0;
-        virtual void    CleanUpAVCDecoder(void) = 0;
-        virtual void    ResetAVCDecoder(void) = 0;
-        virtual int32   DecodeSPS(uint8 *bitstream, int32 buffer_size) = 0;
-        virtual int32   DecodePPS(uint8 *bitstream, int32 buffer_size) = 0;
-        virtual int32   DecodeAVCSlice(uint8 *bitstream, int32 *buffer_size) = 0;
-        virtual bool    GetDecOutput(int *indx, int *release) = 0;
-        virtual void    GetVideoDimensions(int32 *width, int32 *height, int32 *top, int32 *left, int32 *bottom, int32 *right) = 0;
-//  virtual int     AVC_Malloc(int32 size, int attribute);
-//  virtual void    AVC_Free(int mem);
-};
-
-#endif // PVAVCDECODERINTERFACE_H_INCLUDED
-
-
diff --git a/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp b/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp
deleted file mode 100644
index 270b664..0000000
--- a/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avcdec_bitstream.h"
-
-/* Swapping may not be needed anymore since we read one byte at a time and perform
-EBSP to RBSP conversion in bitstream. */
-#ifdef LITTLE_ENDIAN
-#if (WORD_SIZE==32)  /* this can be replaced with assembly instructions */
-#define SWAP_BYTES(x) ((((x)&0xFF)<<24) | (((x)&0xFF00)<<8) | (((x)&0xFF0000)>>8) | (((x)&0xFF000000)>>24))
-#else  /* for 16-bit */
-#define SWAP_BYTES(x) ((((x)&0xFF)<<8) | (((x)&0xFF00)>>8))
-#endif
-#else
-#define SWAP_BYTES(x) (x)
-#endif
-
-
-/* array for trailing bit pattern as function of number of bits */
-/* the first one is unused. */
-const static uint8 trailing_bits[9] = {0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
-
-/* ======================================================================== */
-/*  Function : BitstreamInit()                                              */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Populate bitstream structure with bitstream buffer and size  */
-/*             it also initializes internal data                            */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if failed.              */
-/*  Modified :                                                              */
-/* ======================================================================== */
-/* |--------|--------|----~~~~~-----|---------|---------|---------|
-   ^                                          ^read_pos           ^data_end_pos
-   bitstreamBuffer                  <--------->
-                                    current_word
-
-   |xxxxxxxxxxxxx----|  = current_word 32 or 16 bits
-    <------------>
-     bit_left
- ======================================================================== */
-
-
-/* ======================================================================== */
-/*  Function : BitstreamNextWord()                                          */
-/*  Date     : 12/4/2003                                                    */
-/*  Purpose  : Read up to machine word.                                     */
-/*  In/out   :                                                              */
-/*  Return   : Next word with emulation prevention code removed. Everything
-    in the bitstream structure got modified except current_word             */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-AVCDec_Status BitstreamInit(AVCDecBitstream *stream, uint8 *buffer, int size)
-{
-    EBSPtoRBSP(buffer, &size);
-
-    stream->incnt = 0;
-    stream->incnt_next = 0;
-    stream->bitcnt = 0;
-    stream->curr_word = stream->next_word = 0;
-    stream->read_pos = 0;
-
-    stream->bitstreamBuffer = buffer;
-
-    stream->data_end_pos = size;
-
-    stream->nal_size = size;
-
-    return AVCDEC_SUCCESS;
-}
-/* ======================================================================== */
-/*  Function : AVC_BitstreamFillCache()                                         */
-/*  Date     : 1/1/2005                                                     */
-/*  Purpose  : Read up to machine word.                                     */
-/*  In/out   :                                                              */
-/*  Return   : Read in 4 bytes of input data                                */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-AVCDec_Status AVC_BitstreamFillCache(AVCDecBitstream *stream)
-{
-    uint8 *bitstreamBuffer = stream->bitstreamBuffer;
-    uint8 *v;
-    int num_bits, i;
-
-    stream->curr_word |= (stream->next_word >> stream->incnt);   // stream->incnt cannot be 32
-    stream->next_word <<= (31 - stream->incnt);
-    stream->next_word <<= 1;
-    num_bits = stream->incnt_next + stream->incnt;
-    if (num_bits >= 32)
-    {
-        stream->incnt_next -= (32 - stream->incnt);
-        stream->incnt = 32;
-        return AVCDEC_SUCCESS;
-    }
-    /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */
-    v = bitstreamBuffer + stream->read_pos;
-
-    if (stream->read_pos > stream->data_end_pos - 4)
-    {
-        if (stream->data_end_pos <= stream->read_pos)
-        {
-            stream->incnt = num_bits;
-            stream->incnt_next = 0;
-            return AVCDEC_SUCCESS;
-        }
-
-        stream->next_word = 0;
-
-        for (i = 0; i < stream->data_end_pos - stream->read_pos; i++)
-        {
-            stream->next_word |= (v[i] << ((3 - i) << 3));
-        }
-
-        stream->read_pos = stream->data_end_pos;
-        stream->curr_word |= (stream->next_word >> num_bits); // this is safe
-
-        stream->next_word <<= (31 - num_bits);
-        stream->next_word <<= 1;
-        num_bits = i << 3;
-        stream->incnt += stream->incnt_next;
-        stream->incnt_next = num_bits - (32 - stream->incnt);
-        if (stream->incnt_next < 0)
-        {
-            stream->incnt +=  num_bits;
-            stream->incnt_next = 0;
-        }
-        else
-        {
-            stream->incnt = 32;
-        }
-        return AVCDEC_SUCCESS;
-    }
-
-    stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
-    stream->read_pos += 4;
-
-    stream->curr_word |= (stream->next_word >> num_bits); // this is safe
-    stream->next_word <<= (31 - num_bits);
-    stream->next_word <<= 1;
-    stream->incnt_next += stream->incnt;
-    stream->incnt = 32;
-    return AVCDEC_SUCCESS;
-
-}
-/* ======================================================================== */
-/*  Function : BitstreamReadBits()                                          */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Read up to machine word.                                     */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits   */
-/*              is greater than the word-size, AVCDEC_PACKET_LOSS or        */
-/*              AVCDEC_NO_DATA if callback to get data fails.               */
-/*  Modified :                                                              */
-/* ======================================================================== */
-AVCDec_Status BitstreamReadBits(AVCDecBitstream *stream, int nBits, uint *code)
-{
-    if (stream->incnt < nBits)
-    {
-        /* frame-based decoding */
-        AVC_BitstreamFillCache(stream);
-    }
-    *code = stream->curr_word >> (32 - nBits);
-    BitstreamFlushBits(stream, nBits);
-    return AVCDEC_SUCCESS;
-}
-
-
-
-/* ======================================================================== */
-/*  Function : BitstreamShowBits()                                          */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Show up to machine word without advancing the pointer.       */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits   */
-/*              is greater than the word-size, AVCDEC_NO_DATA if it needs   */
-/*              to callback to get data.                                    */
-/*  Modified :                                                              */
-/* ======================================================================== */
-AVCDec_Status BitstreamShowBits(AVCDecBitstream *stream, int nBits, uint *code)
-{
-    if (stream->incnt < nBits)
-    {
-        /* frame-based decoding */
-        AVC_BitstreamFillCache(stream);
-    }
-
-    *code = stream->curr_word >> (32 - nBits);
-
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : BitstreamRead1Bit()                                          */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Read 1 bit from the bitstream.                               */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits   */
-/*              is greater than the word-size, AVCDEC_PACKET_LOSS or        */
-/*              AVCDEC_NO_DATA if callback to get data fails.               */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-AVCDec_Status BitstreamRead1Bit(AVCDecBitstream *stream, uint *code)
-{
-    if (stream->incnt < 1)
-    {
-        /* frame-based decoding */
-        AVC_BitstreamFillCache(stream);
-    }
-    *code = stream->curr_word >> 31;
-    BitstreamFlushBits(stream, 1);
-    return AVCDEC_SUCCESS;
-}
-
-
-
-AVCDec_Status BitstreamByteAlign(AVCDecBitstream  *stream)
-{
-    uint n_stuffed;
-
-    n_stuffed = (8 - (stream->bitcnt & 0x7)) & 0x7; /*  07/05/01 */
-
-    stream->bitcnt += n_stuffed;
-    stream->incnt -= n_stuffed;
-
-    if (stream->incnt < 0)
-    {
-        stream->bitcnt += stream->incnt;
-        stream->incnt = 0;
-    }
-    stream->curr_word <<= n_stuffed;
-    return AVCDEC_SUCCESS;
-}
-
-/* check whether there are more RBSP data. */
-/* ignore the emulation prevention code, assume it has been taken out. */
-bool more_rbsp_data(AVCDecBitstream *stream)
-{
-    int total_bit_left;
-    uint code;
-
-    if (stream->read_pos >= stream->nal_size)
-    {
-        total_bit_left = stream->incnt_next + stream->incnt;
-        if (total_bit_left <= 0)
-        {
-            return FALSE;
-        }
-        else if (total_bit_left <= 8)
-        {
-            BitstreamShowBits(stream, total_bit_left, &code);
-            if (code == trailing_bits[total_bit_left])
-            {
-                return FALSE;
-            }
-        }
-    }
-
-    return TRUE;
-}
-
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp b/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
deleted file mode 100644
index 0a75f17..0000000
--- a/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
+++ /dev/null
@@ -1,1036 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/**
-This file contains application function interfaces to the AVC decoder library.
-@publishedAll
-*/
-
-#include <string.h>
-
-#include "avcdec_api.h"
-#include "avcdec_lib.h"
-#include "avcdec_bitstream.h"
-
-/* ======================================================================== */
-/*  Function : EBSPtoRBSP()                                                 */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Convert EBSP to RBSP and overwrite it.                       */
-/*             Assuming that forbidden_zero, nal_ref_idc and nal_unit_type  */
-/*          (first byte), has been taken out of the nal_unit.               */
-/*  In/out   :                                                              */
-/*  Return   :                                                              */
-/*  Modified :                                                              */
-/* ======================================================================== */
-/**
-@pseudocode "
-    NumBytesInRBSP = 0;
-    for(i=0:i< *size; i++){
-        if(i+2 < *size && next_bits(24)==0x000003){
-            rbsp_byte[NumBytesInRBSP++];
-            rbsp_byte[NumBytesInRBSP++];
-            i+=2;
-            emulation_prevention_three_byte (0x03)
-        }
-        else
-            rbsp_byte[NumBytesInRBSP++];
-    }"
-*/
-AVCDec_Status EBSPtoRBSP(uint8 *nal_unit, int *size)
-{
-    int i, j;
-    int count = 0;
-
-    /* This code is based on EBSPtoRBSP of JM */
-    j = 0;
-
-    for (i = 0; i < *size; i++)
-    {
-        if (count == 2 && nal_unit[i] == 0x03)
-        {
-            i++;
-            count = 0;
-        }
-        nal_unit[j] = nal_unit[i];
-        if (nal_unit[i] == 0x00)
-            count++;
-        else
-            count = 0;
-        j++;
-    }
-
-    *size = j;
-
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCAnnexBGetNALUnit()                                      */
-/*  Date     : 11/3/2003                                                    */
-/*  Purpose  : Parse a NAL from byte stream format.                         */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail.                 */
-/*  Modified :                                                              */
-/* ======================================================================== */
-/**
-@pseudocode "
-    byte_stream_nal_unit(NumBytesInNalunit){
-    while(next_bits(24) != 0x000001)
-        zero_byte
-    if(more_data_in_byte_stream()){
-        start_code_prefix_one_3bytes // equal 0x000001
-        nal_unit(NumBytesInNALunit)
-    }
-   }"
-*/
-OSCL_EXPORT_REF AVCDec_Status PVAVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit,
-        int *size)
-{
-    int i, j, FoundStartCode = 0;
-    int end;
-
-    i = 0;
-    while (bitstream[i] == 0 && i < *size)
-    {
-        i++;
-    }
-    if (i >= *size)
-    {
-        *nal_unit = bitstream;
-        return AVCDEC_FAIL; /* cannot find any start_code_prefix. */
-    }
-    else if (bitstream[i] != 0x1)
-    {
-        i = -1;  /* start_code_prefix is not at the beginning, continue */
-    }
-
-    i++;
-    *nal_unit = bitstream + i; /* point to the beginning of the NAL unit */
-
-    j = end = i;
-    while (!FoundStartCode)
-    {
-        while ((j + 1 < *size) && (bitstream[j] != 0 || bitstream[j+1] != 0))  /* see 2 consecutive zero bytes */
-        {
-            j++;
-        }
-        end = j;   /* stop and check for start code */
-        while (j + 2 < *size && bitstream[j+2] == 0) /* keep reading for zero byte */
-        {
-            j++;
-        }
-        if (j + 2 >= *size)
-        {
-            *size -= i;
-            return AVCDEC_NO_NEXT_SC;  /* cannot find the second start_code_prefix */
-        }
-        if (bitstream[j+2] == 0x1)
-        {
-            FoundStartCode = 1;
-        }
-        else
-        {
-            /* could be emulation code 0x3 */
-            j += 2; /* continue the search */
-        }
-    }
-
-    *size = end - i;
-
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCGetNALType()                                            */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Sniff NAL type from the bitstream                            */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail.                 */
-/*  Modified :                                                              */
-/* ======================================================================== */
-OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetNALType(uint8 *bitstream, int size,
-        int *nal_type, int *nal_ref_idc)
-{
-    int forbidden_zero_bit;
-    if (size > 0)
-    {
-        forbidden_zero_bit = bitstream[0] >> 7;
-        if (forbidden_zero_bit != 0)
-            return AVCDEC_FAIL;
-        *nal_ref_idc = (bitstream[0] & 0x60) >> 5;
-        *nal_type = bitstream[0] & 0x1F;
-        return AVCDEC_SUCCESS;
-    }
-
-    return AVCDEC_FAIL;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCDecSeqParamSet()                                        */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Initialize sequence, memory allocation if necessary.         */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail.                 */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-OSCL_EXPORT_REF AVCDec_Status   PVAVCDecSeqParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
-        int nal_size)
-{
-    AVCDec_Status status;
-    AVCDecObject *decvid;
-    AVCCommonObj *video;
-    AVCDecBitstream *bitstream;
-    void *userData = avcHandle->userData;
-    bool  first_seq = FALSE;
-    int i;
-
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCDecSeqParamSet", -1, -1);
-
-    if (avcHandle->AVCObject == NULL)
-    {
-        first_seq = TRUE;
-
-        //avcHandle->memory_usage = 0;
-        /* allocate AVCDecObject */
-        avcHandle->AVCObject = (void*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecObject), 0/*DEFAULT_ATTR*/);
-        if (avcHandle->AVCObject == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-
-        decvid = (AVCDecObject*) avcHandle->AVCObject;
-
-        memset(decvid, 0, sizeof(AVCDecObject));
-
-        decvid->common = (AVCCommonObj*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCCommonObj), 0);
-        if (decvid->common == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-
-        video = decvid->common;
-        memset(video, 0, sizeof(AVCCommonObj));
-
-        video->seq_parameter_set_id = 9999; /* set it to some illegal value */
-
-        decvid->bitstream = (AVCDecBitstream *) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecBitstream), 1/*DEFAULT_ATTR*/);
-        if (decvid->bitstream == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-
-        decvid->bitstream->userData = avcHandle->userData; /* callback for more data */
-        decvid->avcHandle = avcHandle;
-        decvid->debugEnable = avcHandle->debugEnable;
-    }
-
-    decvid = (AVCDecObject*) avcHandle->AVCObject;
-    video = decvid->common;
-    bitstream = decvid->bitstream;
-
-    /* check if we can reuse the memory without re-allocating it. */
-    /* always check if(first_seq==TRUE) */
-
-    /* Conversion from EBSP to RBSP */
-    video->forbidden_bit = nal_unit[0] >> 7;
-    if (video->forbidden_bit) return AVCDEC_FAIL;
-    video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
-    video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
-
-    if (video->nal_unit_type != AVC_NALTYPE_SPS) /* not a SPS NAL */
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* Initialize bitstream structure*/
-    BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
-
-    /* if first_seq == TRUE, allocate the following memory  */
-    if (first_seq == TRUE)
-    {
-        video->currSeqParams = NULL; /* initialize it to NULL */
-        video->currPicParams = NULL;
-
-        /* There are 32 pointers to sequence param set, seqParams.
-                There are 255 pointers to picture param set, picParams.*/
-        for (i = 0; i < 32; i++)
-            decvid->seqParams[i] = NULL;
-
-        for (i = 0; i < 256; i++)
-            decvid->picParams[i] = NULL;
-
-        video->MbToSliceGroupMap = NULL;
-
-        video->mem_mgr_ctrl_eq_5 = FALSE;
-        video->newPic = TRUE;
-        video->newSlice = TRUE;
-        video->currPic = NULL;
-        video->currFS = NULL;
-        video->prevRefPic = NULL;
-
-        video->mbNum = 0; // MC_Conceal
-        /*  Allocate sliceHdr. */
-
-        video->sliceHdr = (AVCSliceHeader*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSliceHeader), 5/*DEFAULT_ATTR*/);
-        if (video->sliceHdr == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-
-        video->decPicBuf = (AVCDecPicBuffer*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecPicBuffer), 3/*DEFAULT_ATTR*/);
-        if (video->decPicBuf == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-        memset(video->decPicBuf, 0, sizeof(AVCDecPicBuffer));
-    }
-
-    /* Decode SPS, allocate video->seqParams[i] and assign video->currSeqParams */
-    status = DecodeSPS(decvid, bitstream);
-
-    if (status != AVCDEC_SUCCESS)
-    {
-        return status;
-    }
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCDecGetSeqInfo()                                         */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Get sequence parameter info. after SPS NAL is decoded.       */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail.                 */
-/*  Modified :                                                              */
-/*  12/20/03:  change input argument, use structure instead.                */
-/* ======================================================================== */
-
-OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetSeqInfo(AVCHandle *avcHandle, AVCDecSPSInfo *seqInfo)
-{
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    int PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs;
-
-    if (decvid == NULL || decvid->seqParams[0] == NULL)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    video = decvid->common;
-
-    PicWidthInMbs = decvid->seqParams[0]->pic_width_in_mbs_minus1 + 1;
-    PicHeightInMapUnits = decvid->seqParams[0]->pic_height_in_map_units_minus1 + 1 ;
-    FrameHeightInMbs = (2 - decvid->seqParams[0]->frame_mbs_only_flag) * PicHeightInMapUnits ;
-
-    seqInfo->FrameWidth = PicWidthInMbs << 4;
-    seqInfo->FrameHeight = FrameHeightInMbs << 4;
-
-    seqInfo->frame_only_flag = decvid->seqParams[0]->frame_mbs_only_flag;
-
-    if (decvid->seqParams[0]->frame_cropping_flag)
-    {
-        seqInfo->frame_crop_left = 2 * decvid->seqParams[0]->frame_crop_left_offset;
-        seqInfo->frame_crop_right = seqInfo->FrameWidth - (2 * decvid->seqParams[0]->frame_crop_right_offset + 1);
-
-        if (seqInfo->frame_only_flag)
-        {
-            seqInfo->frame_crop_top = 2 * decvid->seqParams[0]->frame_crop_top_offset;
-            seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (2 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
-            /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
-            such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/2, respectively. */
-        }
-        else
-        {
-            seqInfo->frame_crop_top = 4 * decvid->seqParams[0]->frame_crop_top_offset;
-            seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (4 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
-            /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
-            such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/4, respectively. */
-        }
-    }
-    else  /* no cropping flag, just give the first and last pixel */
-    {
-        seqInfo->frame_crop_bottom = seqInfo->FrameHeight - 1;
-        seqInfo->frame_crop_right = seqInfo->FrameWidth - 1;
-        seqInfo->frame_crop_top = seqInfo->frame_crop_left = 0;
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCDecPicParamSet()                                        */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Initialize picture                                           */
-/*             create reference picture list.                               */
-/*  In/out   :                                                              */
-/*  Return   : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail.                 */
-/*  Modified :                                                              */
-/* ======================================================================== */
-/**
-Since PPS doesn't contain much data, most of the picture initialization will
-be done after decoding the slice header in PVAVCDecodeSlice. */
-OSCL_EXPORT_REF AVCDec_Status   PVAVCDecPicParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
-        int nal_size)
-{
-    AVCDec_Status status;
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    AVCDecBitstream *bitstream;
-
-    if (decvid == NULL)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    video = decvid->common;
-    bitstream = decvid->bitstream;
-    /* 1. Convert EBSP to RBSP. Create bitstream structure */
-    video->forbidden_bit = nal_unit[0] >> 7;
-    video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
-    video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
-
-    if (video->nal_unit_type != AVC_NALTYPE_PPS) /* not a PPS NAL */
-    {
-        return AVCDEC_FAIL;
-    }
-
-
-    /* 2. Initialize bitstream structure*/
-    BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
-
-    /* 2. Decode pic_parameter_set_rbsp syntax. Allocate video->picParams[i] and assign to currPicParams */
-    status = DecodePPS(decvid, video, bitstream);
-    if (status != AVCDEC_SUCCESS)
-    {
-        return status;
-    }
-
-    video->SliceGroupChangeRate = video->currPicParams->slice_group_change_rate_minus1 + 1 ;
-
-    return AVCDEC_SUCCESS;
-}
-
-OSCL_EXPORT_REF AVCDec_Status   PVAVCDecSEI(AVCHandle *avcHandle, uint8 *nal_unit,
-        int nal_size)
-{
-    OSCL_UNUSED_ARG(avcHandle);
-    OSCL_UNUSED_ARG(nal_unit);
-    OSCL_UNUSED_ARG(nal_size);
-
-    return AVCDEC_SUCCESS;
-}
-/* ======================================================================== */
-/*  Function : PVAVCDecodeSlice()                                           */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Decode one NAL unit.                                         */
-/*  In/out   :                                                              */
-/*  Return   : See enum AVCDec_Status for return values.                    */
-/*  Modified :                                                              */
-/* ======================================================================== */
-OSCL_EXPORT_REF AVCDec_Status PVAVCDecodeSlice(AVCHandle *avcHandle, uint8 *buffer,
-        int buf_size)
-{
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    AVCDecBitstream *bitstream;
-    AVCDec_Status status;
-
-    if (decvid == NULL)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    video = decvid->common;
-    bitstream = decvid->bitstream;
-
-    if (video->mem_mgr_ctrl_eq_5)
-    {
-        return AVCDEC_PICTURE_OUTPUT_READY;      // to flushout frame buffers
-    }
-
-    if (video->newSlice)
-    {
-        /* 2. Check NAL type  */
-        if (buffer == NULL)
-        {
-            return AVCDEC_FAIL;
-        }
-        video->prev_nal_unit_type = video->nal_unit_type;
-        video->forbidden_bit = buffer[0] >> 7;
-        video->nal_ref_idc = (buffer[0] & 0x60) >> 5;
-        video->nal_unit_type = (AVCNalUnitType)(buffer[0] & 0x1F);
-
-
-        if (video->nal_unit_type == AVC_NALTYPE_AUD)
-        {
-            return AVCDEC_SUCCESS;
-        }
-
-        if (video->nal_unit_type != AVC_NALTYPE_SLICE &&
-                video->nal_unit_type != AVC_NALTYPE_IDR)
-        {
-            return AVCDEC_FAIL; /* not supported */
-        }
-
-
-
-        if (video->nal_unit_type >= 2 && video->nal_unit_type <= 4)
-        {
-            return AVCDEC_FAIL; /* not supported */
-        }
-        else
-        {
-            video->slice_data_partitioning = FALSE;
-        }
-
-        video->newSlice = FALSE;
-        /*  Initialize bitstream structure*/
-        BitstreamInit(bitstream, buffer + 1, buf_size - 1);
-
-
-        /* 2.1 Decode Slice Header (separate function)*/
-        status = DecodeSliceHeader(decvid, video, bitstream);
-        if (status != AVCDEC_SUCCESS)
-        {
-            video->newSlice = TRUE;
-            return status;
-        }
-
-        if (video->sliceHdr->frame_num != video->prevFrameNum || (video->sliceHdr->first_mb_in_slice < (uint)video->mbNum && video->currSeqParams->constrained_set1_flag == 1))
-        {
-            video->newPic = TRUE;
-            if (video->numMBs > 0)
-            {
-                // Conceal missing MBs of previously decoded frame
-                ConcealSlice(decvid, video->PicSizeInMbs - video->numMBs, video->PicSizeInMbs);  // Conceal
-                video->numMBs = 0;
-
-                //              DeblockPicture(video);   // No need to deblock
-
-                /* 3.2 Decoded frame reference marking. */
-                /* 3.3 Put the decoded picture in output buffers */
-                /* set video->mem_mge_ctrl_eq_5 */
-                AVCNalUnitType temp = video->nal_unit_type;
-                video->nal_unit_type = video->prev_nal_unit_type;
-                StorePictureInDPB(avcHandle, video);
-                video->nal_unit_type = temp;
-                video->mbNum = 0; // MC_Conceal
-                return AVCDEC_PICTURE_OUTPUT_READY;
-            }
-        }
-
-        if (video->nal_unit_type == AVC_NALTYPE_IDR)
-        {
-            video->prevFrameNum = 0;
-            video->PrevRefFrameNum = 0;
-        }
-
-        if (!video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
-        {   /* no gaps allowed, frame_num has to increase by one only */
-            /*          if(sliceHdr->frame_num != (video->PrevRefFrameNum + 1)%video->MaxFrameNum) */
-            if (video->sliceHdr->frame_num != video->PrevRefFrameNum && video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
-            {
-                // Conceal missing MBs of previously decoded frame
-                video->numMBs = 0;
-                video->newPic = TRUE;
-                video->prevFrameNum++; // FIX
-                video->PrevRefFrameNum++;
-                AVCNalUnitType temp = video->nal_unit_type;
-                video->nal_unit_type = AVC_NALTYPE_SLICE; //video->prev_nal_unit_type;
-                status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
-                if (status != AVCDEC_SUCCESS)
-                {
-                    return status;
-                }
-                video->currFS->IsOutputted = 0x01;
-                video->currFS->IsReference = 3;
-                video->currFS->IsLongTerm = 0;
-
-                DecodePOC(video);
-                /* find an empty memory from DPB and assigned to currPic */
-                DPBInitPic(video, video->PrevRefFrameNum % video->MaxFrameNum);
-                RefListInit(video);
-                ConcealSlice(decvid, 0, video->PicSizeInMbs);  // Conceal
-                video->currFS->IsOutputted |= 0x02;
-                //conceal frame
-                /* 3.2 Decoded frame reference marking. */
-                /* 3.3 Put the decoded picture in output buffers */
-                /* set video->mem_mge_ctrl_eq_5 */
-                video->mbNum = 0; // Conceal
-                StorePictureInDPB(avcHandle, video);
-                video->nal_unit_type = temp;
-
-                return AVCDEC_PICTURE_OUTPUT_READY;
-            }
-        }
-    }
-
-    if (video->newPic == TRUE)
-    {
-        status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
-        if (status != AVCDEC_SUCCESS)
-        {
-            return status;
-        }
-    }
-
-    video->newSlice = TRUE;
-
-    /* function pointer setting at slice-level */
-    // OPTIMIZE
-    decvid->residual_block = &residual_block_cavlc;
-
-    /* derive picture order count */
-    if (video->newPic == TRUE)
-    {
-        video->numMBs = video->PicSizeInMbs;
-
-        if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
-        {
-            if (video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
-            {
-                status = fill_frame_num_gap(avcHandle, video);
-                if (status != AVCDEC_SUCCESS)
-                {
-                    video->numMBs = 0;
-                    return status;
-                }
-
-                status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
-                if (status != AVCDEC_SUCCESS)
-                {
-                    video->numMBs = 0;
-                    return status;
-                }
-
-
-            }
-        }
-        /* if there's gap in the frame_num, we have to fill in the gap with
-            imaginary frames that won't get used for short-term ref. */
-        /* see fill_frame_num_gap() in JM */
-
-
-        DecodePOC(video);
-        /* find an empty memory from DPB and assigned to currPic */
-        DPBInitPic(video, video->CurrPicNum);
-
-        video->currPic->isReference = TRUE;  // FIX
-
-        if (video->nal_ref_idc == 0)
-        {
-            video->currPic->isReference = FALSE;
-            video->currFS->IsOutputted |= 0x02;     /* The MASK 0x02 means not needed for reference, or returned */
-            /* node need to check for freeing of this buffer */
-        }
-
-        FMOInit(video);
-
-        if (video->currPic->isReference)
-        {
-            video->PrevRefFrameNum = video->sliceHdr->frame_num;
-        }
-
-
-        video->prevFrameNum = video->sliceHdr->frame_num;
-    }
-
-    video->newPic = FALSE;
-
-
-    /* Initialize refListIdx for this picture */
-    RefListInit(video);
-
-    /* Re-order the reference list according to the ref_pic_list_reordering() */
-    status = (AVCDec_Status)ReOrderList(video);
-    if (status != AVCDEC_SUCCESS)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* 2.2 Decode Slice. */
-    status = (AVCDec_Status)DecodeSlice(decvid);
-
-    video->slice_id++;  //  slice
-
-    if (status == AVCDEC_PICTURE_READY)
-    {
-        /* 3. Check complete picture */
-#ifndef MB_BASED_DEBLOCK
-        /* 3.1 Deblock */
-        DeblockPicture(video);
-#endif
-        /* 3.2 Decoded frame reference marking. */
-        /* 3.3 Put the decoded picture in output buffers */
-        /* set video->mem_mge_ctrl_eq_5 */
-        status = (AVCDec_Status)StorePictureInDPB(avcHandle, video);          // CHECK check the retunr status
-        if (status != AVCDEC_SUCCESS)
-        {
-            return AVCDEC_FAIL;
-        }
-
-        if (video->mem_mgr_ctrl_eq_5)
-        {
-            video->PrevRefFrameNum = 0;
-            video->prevFrameNum = 0;
-            video->prevPicOrderCntMsb = 0;
-            video->prevPicOrderCntLsb = video->TopFieldOrderCnt;
-            video->prevFrameNumOffset = 0;
-        }
-        else
-        {
-            video->prevPicOrderCntMsb = video->PicOrderCntMsb;
-            video->prevPicOrderCntLsb = video->sliceHdr->pic_order_cnt_lsb;
-            video->prevFrameNumOffset = video->FrameNumOffset;
-        }
-
-        return AVCDEC_PICTURE_READY;
-    }
-    else if (status != AVCDEC_SUCCESS)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/* ======================================================================== */
-/*  Function : PVAVCDecGetOutput()                                          */
-/*  Date     : 11/3/2003                                                    */
-/*  Purpose  : Get the next picture according to PicOrderCnt.               */
-/*  In/out   :                                                              */
-/*  Return   : AVCFrameIO structure                                         */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetOutput(AVCHandle *avcHandle, int *indx, int *release, AVCFrameIO *output)
-{
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    AVCDecPicBuffer *dpb;
-    AVCFrameStore *oldestFrame = NULL;
-    int i, first = 1;
-    int count_frame = 0;
-    int index = 0;
-    int min_poc = 0;
-
-    if (decvid == NULL)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    video = decvid->common;
-    dpb = video->decPicBuf;
-
-    if (dpb->num_fs == 0)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* search for the oldest frame_num in dpb */
-    /* extension to field decoding, we have to search for every top_field/bottom_field within
-    each frame in the dpb. This code only works for frame based.*/
-
-    if (video->mem_mgr_ctrl_eq_5 == FALSE)
-    {
-        for (i = 0; i < dpb->num_fs; i++)
-        {
-            if ((dpb->fs[i]->IsOutputted & 0x01) == 0)
-            {
-                count_frame++;
-                if (first)
-                {
-                    min_poc = dpb->fs[i]->PicOrderCnt;
-                    first = 0;
-                    oldestFrame = dpb->fs[i];
-                    index = i;
-                }
-                if (dpb->fs[i]->PicOrderCnt < min_poc)
-                {
-                    min_poc = dpb->fs[i]->PicOrderCnt;
-                    oldestFrame = dpb->fs[i];
-                    index = i;
-                }
-            }
-        }
-    }
-    else
-    {
-        for (i = 0; i < dpb->num_fs; i++)
-        {
-            if ((dpb->fs[i]->IsOutputted & 0x01) == 0 && dpb->fs[i] != video->currFS)
-            {
-                count_frame++;
-                if (first)
-                {
-                    min_poc = dpb->fs[i]->PicOrderCnt;
-                    first = 0;
-                    oldestFrame = dpb->fs[i];
-                    index = i;
-                }
-                if (dpb->fs[i]->PicOrderCnt < min_poc)
-                {
-                    min_poc = dpb->fs[i]->PicOrderCnt;
-                    oldestFrame = dpb->fs[i];
-                    index = i;
-                }
-            }
-        }
-
-        if (count_frame < 2 && video->nal_unit_type != AVC_NALTYPE_IDR)
-        {
-            video->mem_mgr_ctrl_eq_5 = FALSE;  // FIX
-        }
-        else if (count_frame < 1 && video->nal_unit_type == AVC_NALTYPE_IDR)
-        {
-            for (i = 0; i < dpb->num_fs; i++)
-            {
-                if (dpb->fs[i] == video->currFS && (dpb->fs[i]->IsOutputted & 0x01) == 0)
-                {
-                    oldestFrame = dpb->fs[i];
-                    index = i;
-                    break;
-                }
-            }
-            video->mem_mgr_ctrl_eq_5 = FALSE;
-        }
-    }
-
-    if (oldestFrame == NULL)
-    {
-
-        /*      Check for Mem_mgmt_operation_5 based forced output */
-        for (i = 0; i < dpb->num_fs; i++)
-        {
-            /* looking for the one not used or not reference and has been outputted */
-            if (dpb->fs[i]->IsReference == 0 && dpb->fs[i]->IsOutputted == 3)
-            {
-                break;
-            }
-        }
-        if (i < dpb->num_fs)
-        {
-            /* there are frames available for decoding */
-            return AVCDEC_FAIL; /* no frame to be outputted */
-        }
-
-
-        /* no free frame available, we have to release one to continue decoding */
-        int MinIdx = 0;
-        int32 MinFrameNumWrap = 0x7FFFFFFF;
-
-        for (i = 0; i < dpb->num_fs; i++)
-        {
-            if (dpb->fs[i]->IsReference && !dpb->fs[i]->IsLongTerm)
-            {
-                if (dpb->fs[i]->FrameNumWrap < MinFrameNumWrap)
-                {
-                    MinFrameNumWrap = dpb->fs[i]->FrameNumWrap;
-                    MinIdx = i;
-                }
-            }
-        }
-        /* mark the frame with smallest PicOrderCnt to be unused for reference */
-        dpb->fs[MinIdx]->IsReference = 0;
-        dpb->fs[MinIdx]->IsLongTerm = 0;
-        dpb->fs[MinIdx]->frame.isReference = FALSE;
-        dpb->fs[MinIdx]->frame.isLongTerm = FALSE;
-        dpb->fs[MinIdx]->IsOutputted |= 0x02;
-#ifdef PV_MEMORY_POOL
-        if (dpb->fs[MinIdx]->IsOutputted == 3)
-        {
-            avcHandle->CBAVC_FrameUnbind(avcHandle->userData, MinIdx);
-        }
-#endif
-        return AVCDEC_FAIL;
-    }
-    /* MASK 0x01 means the frame is outputted (for display). A frame gets freed when it is
-    outputted (0x01) and not needed for reference (0x02)   */
-    oldestFrame->IsOutputted |= 0x01;
-
-    if (oldestFrame->IsOutputted == 3)
-    {
-        *release = 1; /* flag to release the buffer */
-    }
-    else
-    {
-        *release = 0;
-    }
-    /* do not release buffer here, release it after it is sent to the sink node */
-
-    output->YCbCr[0] = oldestFrame->frame.Sl;
-    output->YCbCr[1] = oldestFrame->frame.Scb;
-    output->YCbCr[2] = oldestFrame->frame.Scr;
-    output->height = oldestFrame->frame.height;
-    output->pitch = oldestFrame->frame.width;
-    output->disp_order = oldestFrame->PicOrderCnt;
-    output->coding_order = oldestFrame->FrameNum;
-    output->id = (uint32) oldestFrame->base_dpb; /* use the pointer as the id */
-    *indx = index;
-
-
-
-    return AVCDEC_SUCCESS;
-}
-
-
-/* ======================================================================== */
-/*  Function : PVAVCDecReset()                                              */
-/*  Date     : 03/04/2004                                                   */
-/*  Purpose  : Reset decoder, prepare it for a new IDR frame.               */
-/*  In/out   :                                                              */
-/*  Return   :  void                                                        */
-/*  Modified :                                                              */
-/* ======================================================================== */
-OSCL_EXPORT_REF void    PVAVCDecReset(AVCHandle *avcHandle)
-{
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    AVCDecPicBuffer *dpb;
-    int i;
-
-    if (decvid == NULL)
-    {
-        return;
-    }
-
-    video = decvid->common;
-    dpb = video->decPicBuf;
-
-    /* reset the DPB */
-
-
-    for (i = 0; i < dpb->num_fs; i++)
-    {
-        dpb->fs[i]->IsLongTerm = 0;
-        dpb->fs[i]->IsReference = 0;
-        dpb->fs[i]->IsOutputted = 3;
-        dpb->fs[i]->frame.isReference = 0;
-        dpb->fs[i]->frame.isLongTerm = 0;
-    }
-
-    video->mem_mgr_ctrl_eq_5 = FALSE;
-    video->newPic = TRUE;
-    video->newSlice = TRUE;
-    video->currPic = NULL;
-    video->currFS = NULL;
-    video->prevRefPic = NULL;
-    video->prevFrameNum = 0;
-    video->PrevRefFrameNum = 0;
-    video->prevFrameNumOffset = 0;
-    video->FrameNumOffset = 0;
-    video->mbNum = 0;
-    video->numMBs = 0;
-
-    return ;
-}
-
-
-/* ======================================================================== */
-/*  Function : PVAVCCleanUpDecoder()                                        */
-/*  Date     : 11/4/2003                                                    */
-/*  Purpose  : Clean up the decoder, free all memories allocated.           */
-/*  In/out   :                                                              */
-/*  Return   :  void                                                        */
-/*  Modified :                                                              */
-/* ======================================================================== */
-
-OSCL_EXPORT_REF void PVAVCCleanUpDecoder(AVCHandle *avcHandle)
-{
-    AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
-    AVCCommonObj *video;
-    void *userData = avcHandle->userData;
-    int i;
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCCleanUpDecoder", -1, -1);
-
-    if (decvid != NULL)
-    {
-        video = decvid->common;
-        if (video != NULL)
-        {
-            if (video->MbToSliceGroupMap != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->MbToSliceGroupMap);
-            }
-
-#ifdef MB_BASED_DEBLOCK
-            if (video->intra_pred_top != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top);
-            }
-            if (video->intra_pred_top_cb != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cb);
-            }
-            if (video->intra_pred_top_cr != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cr);
-            }
-#endif
-            if (video->mblock != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->mblock);
-            }
-
-            if (video->decPicBuf != NULL)
-            {
-                CleanUpDPB(avcHandle, video);
-                avcHandle->CBAVC_Free(userData, (int)video->decPicBuf);
-            }
-
-            if (video->sliceHdr != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)video->sliceHdr);
-            }
-
-            avcHandle->CBAVC_Free(userData, (int)video); /* last thing to do */
-
-        }
-
-        for (i = 0; i < 256; i++)
-        {
-            if (decvid->picParams[i] != NULL)
-            {
-                if (decvid->picParams[i]->slice_group_id != NULL)
-                {
-                    avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]->slice_group_id);
-                }
-                avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]);
-            }
-        }
-        for (i = 0; i < 32; i++)
-        {
-            if (decvid->seqParams[i] != NULL)
-            {
-                avcHandle->CBAVC_Free(userData, (int)decvid->seqParams[i]);
-            }
-        }
-        if (decvid->bitstream != NULL)
-        {
-            avcHandle->CBAVC_Free(userData, (int)decvid->bitstream);
-        }
-
-
-        avcHandle->CBAVC_Free(userData, (int)decvid);
-    }
-
-
-    return ;
-}
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h b/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h
deleted file mode 100644
index bd1bc59..0000000
--- a/media/libstagefright/codecs/avc/dec/src/avcdec_bitstream.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/**
-This file contains bitstream related functions.
-@publishedAll
-*/
-
-#ifndef _AVCDEC_BITSTREAM_H_
-#define _AVCDEC_BITSTREAM_H_
-
-#include "avcdec_lib.h"
-
-#define WORD_SIZE   32  /* this can vary, default to 32 bit for now */
-
-#ifndef __cplusplus
-
-#define AVC_GETDATA(x,y)   userData->AVC_GetData(x,y)
-
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-#define BitstreamFlushBits(A,B)     {(A)->bitcnt += (B); (A)->incnt -= (B); (A)->curr_word <<= (B);}
-
-    AVCDec_Status AVC_BitstreamFillCache(AVCDecBitstream *stream);
-    /**
-    This function populates bitstream structure.
-    \param "stream" "Pointer to bitstream structure."
-    \param "buffer" "Pointer to the bitstream buffer."
-    \param "size"   "Size of the buffer."
-    \param "nal_size"   "Size of the NAL unit."
-    \param "resetall"   "Flag for reset everything."
-    \return "AVCDEC_SUCCESS for success and AVCDEC_FAIL for fail."
-    */
-    AVCDec_Status BitstreamInit(AVCDecBitstream *stream, uint8 *buffer, int size);
-
-    /**
-    This function reads next aligned word and remove the emulation prevention code
-    if necessary.
-    \param "stream" "Pointer to bitstream structure."
-    \return "Next word."
-    */
-    uint BitstreamNextWord(AVCDecBitstream *stream);
-
-    /**
-    This function reads nBits bits from the current position and advance the pointer.
-    \param "stream" "Pointer to bitstream structure."
-    \param "nBits" "Number of bits to be read."
-    \param "code"   "Point to the read value."
-    \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
-                is greater than the word-size, AVCDEC_PACKET_LOSS or
-                AVCDEC_NO_DATA if callback to get data fails."
-    */
-    AVCDec_Status BitstreamReadBits(AVCDecBitstream *stream, int nBits, uint *code);
-
-    /**
-    This function shows nBits bits from the current position without advancing the pointer.
-    \param "stream" "Pointer to bitstream structure."
-    \param "nBits" "Number of bits to be read."
-    \param "code"   "Point to the read value."
-    \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
-                    is greater than the word-size, AVCDEC_NO_DATA if it needs
-                    to callback to get data."
-    */
-    AVCDec_Status BitstreamShowBits(AVCDecBitstream *stream, int nBits, uint *code);
-
-
-    /**
-    This function flushes nBits bits from the current position.
-    \param "stream" "Pointer to bitstream structure."
-    \param "nBits" "Number of bits to be read."
-    \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
-                    is greater than the word-size It will not call back to get
-                   more data. Users should call BitstreamShowBits to determine
-                   how much they want to flush."
-    */
-
-    /**
-    This function read 1 bit from the current position and advance the pointer.
-    \param "stream" "Pointer to bitstream structure."
-    \param "nBits" "Number of bits to be read."
-    \param "code"   "Point to the read value."
-    \return "AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits
-                is greater than the word-size, AVCDEC_PACKET_LOSS or
-                AVCDEC_NO_DATA if callback to get data fails."
-    */
-    AVCDec_Status BitstreamRead1Bit(AVCDecBitstream *stream, uint *code);
-
-    /**
-    This function checks whether the current bit position is byte-aligned or not.
-    \param "stream" "Pointer to the bitstream structure."
-    \return "TRUE if byte-aligned, FALSE otherwise."
-    */
-    bool byte_aligned(AVCDecBitstream *stream);
-    AVCDec_Status BitstreamByteAlign(AVCDecBitstream  *stream);
-    /**
-    This function checks whether there are more RBSP data before the trailing bits.
-    \param "stream" "Pointer to the bitstream structure."
-    \return "TRUE if yes, FALSE otherwise."
-    */
-    bool more_rbsp_data(AVCDecBitstream *stream);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus  */
-
-#endif /* _AVCDEC_BITSTREAM_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_int.h b/media/libstagefright/codecs/avc/dec/src/avcdec_int.h
deleted file mode 100644
index 878f9b3..0000000
--- a/media/libstagefright/codecs/avc/dec/src/avcdec_int.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/**
-This file contains application function interfaces to the AVC decoder library
-and necessary type defitionitions and enumerations.
-Naming convention for variables:
-lower_case_with_under_line  is  syntax element in subclause 7.2 and 7.3
-noUnderLine or NoUnderLine  is  derived variables defined somewhere else in the draft
-                                or introduced by this decoder library.
-@publishedAll
-*/
-
-#ifndef _AVCDEC_INT_H_
-#define _AVCDEC_INT_H_
-
-#include "avcint_common.h"
-#include "avcdec_api.h"
-
-
-/**
-Bitstream structure contains bitstream related parameters such as the pointer
-to the buffer, the current byte position and bit position.
-@publishedAll
-*/
-typedef struct tagDecBitstream
-{
-    uint8 *bitstreamBuffer; /* pointer to buffer memory   */
-    int nal_size;       /* size of the current NAL unit */
-    int data_end_pos;  /* bitstreamBuffer size in bytes */
-    int read_pos;       /* next position to read from bitstreamBuffer  */
-    uint curr_word; /* byte-swapped (MSB left) current word read from buffer */
-    int bit_left;      /* number of bit left in current_word */
-    uint next_word;     /* in case for old data in previous buffer hasn't been flushed. */
-    int incnt;  /* bit left in the prev_word */
-    int incnt_next;
-    int bitcnt;
-    void *userData;
-} AVCDecBitstream;
-
-/**
-This structure is the main object for AVC decoder library providing access to all
-global variables. It is allocated at PVAVCInitDecoder and freed at PVAVCCleanUpDecoder.
-@publishedAll
-*/
-typedef struct tagDecObject
-{
-
-    AVCCommonObj *common;
-
-    AVCDecBitstream     *bitstream; /* for current NAL */
-
-    /* sequence parameter set */
-    AVCSeqParamSet *seqParams[32]; /* Array of pointers, get allocated at arrival of new seq_id */
-
-    /* picture parameter set */
-    AVCPicParamSet *picParams[256]; /* Array of pointers to picture param set structures */
-
-    /* For internal operation, scratch memory for MV, prediction, transform, etc.*/
-    uint    ref_idx_l0[4]; /* [mbPartIdx], te(v) */
-    uint    ref_idx_l1[4];
-
-    /* function pointers */
-    AVCDec_Status(*residual_block)(struct tagDecObject*, int,  int,
-                                   int *, int *, int *);
-    /* Application control data */
-    AVCHandle *avcHandle;
-    void (*AVC_DebugLog)(AVCLogType type, char *string1, char *string2);
-    /*bool*/
-    uint    debugEnable;
-
-} AVCDecObject;
-
-#endif /* _AVCDEC_INT_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h b/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h
deleted file mode 100644
index fdead05..0000000
--- a/media/libstagefright/codecs/avc/dec/src/avcdec_lib.h
+++ /dev/null
@@ -1,555 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/**
-This file contains declarations of internal functions for AVC decoder library.
-@publishedAll
-*/
-#ifndef _AVCDEC_LIB_H_
-#define _AVCDEC_LIB_H_
-
-#include "avclib_common.h"
-#include "avcdec_int.h"
-
-/*----------- avcdec_api.c -------------*/
-/**
-This function takes out the emulation prevention bytes from the input to creat RBSP.
-The result is written over the input bitstream.
-\param "nal_unit"   "(I/O) Pointer to the input buffer."
-\param "size"       "(I/O) Pointer to the size of the input/output buffer."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status EBSPtoRBSP(uint8 *nal_unit, int *size);
-
-/*------------- pred_intra.c ---------------*/
-/**
-This function is the main entry point to intra prediction operation on a
-macroblock.
-\param "video"  "Pointer to AVCCommonObj."
-*/
-AVCStatus  IntraMBPrediction(AVCCommonObj *video);
-
-void SaveNeighborForIntraPred(AVCCommonObj *video, int offset);
-
-AVCStatus Intra_4x4(AVCCommonObj *video, int component, int SubBlock_indx, uint8 *comp);
-void Intra_4x4_Vertical(AVCCommonObj *video, int block_offset);
-void Intra_4x4_Horizontal(AVCCommonObj *video, int pitch, int block_offset);
-void Intra_4x4_DC(AVCCommonObj *video, int pitch, int block_offset, AVCNeighborAvailability *availability);
-void Intra_4x4_Down_Left(AVCCommonObj *video, int block_offset, AVCNeighborAvailability *availability);
-void Intra_4x4_Diagonal_Down_Right(AVCCommonObj *video, int pitch, int block_offset);
-void Intra_4x4_Diagonal_Vertical_Right(AVCCommonObj *video, int pitch, int block_offset);
-void Intra_4x4_Diagonal_Horizontal_Down(AVCCommonObj *video, int pitch, int block_offset);
-void Intra_4x4_Vertical_Left(AVCCommonObj *video,  int block_offset, AVCNeighborAvailability *availability);
-void Intra_4x4_Horizontal_Up(AVCCommonObj *video, int pitch, int block_offset);
-void  Intra_16x16_Vertical(AVCCommonObj *video);
-void Intra_16x16_Horizontal(AVCCommonObj *video, int pitch);
-void Intra_16x16_DC(AVCCommonObj *video, int pitch);
-void Intra_16x16_Plane(AVCCommonObj *video, int pitch);
-void Intra_Chroma_DC(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
-void  Intra_Chroma_Horizontal(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
-void  Intra_Chroma_Vertical(AVCCommonObj *video, uint8 *predCb, uint8 *predCr);
-void  Intra_Chroma_Plane(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr);
-
-/*------------ pred_inter.c ---------------*/
-/**
-This function is the main entrance to inter prediction operation for
-a macroblock. For decoding, this function also calls inverse transform and
-compensation.
-\param "video"  "Pointer to AVCCommonObj."
-\return "void"
-*/
-void InterMBPrediction(AVCCommonObj *video);
-
-/**
-This function is called for luma motion compensation.
-\param "ref"    "Pointer to the origin of a reference luma."
-\param "picwidth"   "Width of the picture."
-\param "picheight"  "Height of the picture."
-\param "x_pos"  "X-coordinate of the predicted block in quarter pel resolution."
-\param "y_pos"  "Y-coordinate of the predicted block in quarter pel resolution."
-\param "pred"   "Pointer to the output predicted block."
-\param "pred_pitch" "Width of pred."
-\param "blkwidth"   "Width of the current partition."
-\param "blkheight"  "Height of the current partition."
-\return "void"
-*/
-void LumaMotionComp(uint8 *ref, int picwidth, int picheight,
-                    int x_pos, int y_pos,
-                    uint8 *pred, int pred_pitch,
-                    int blkwidth, int blkheight);
-
-/**
-Functions below are special cases for luma motion compensation.
-LumaFullPelMC is for full pixel motion compensation.
-LumaBorderMC is for interpolation in only one dimension.
-LumaCrossMC is for interpolation in one dimension and half point in the other dimension.
-LumaDiagonalMC is for interpolation in diagonal direction.
-
-\param "ref"    "Pointer to the origin of a reference luma."
-\param "picwidth"   "Width of the picture."
-\param "picheight"  "Height of the picture."
-\param "x_pos"  "X-coordinate of the predicted block in full pel resolution."
-\param "y_pos"  "Y-coordinate of the predicted block in full pel resolution."
-\param "dx"     "Fraction of x_pos in quarter pel."
-\param "dy"     "Fraction of y_pos in quarter pel."
-\param "curr"   "Pointer to the current partition in the current picture."
-\param "residue"    "Pointer to the current partition for the residue block."
-\param "blkwidth"   "Width of the current partition."
-\param "blkheight"  "Height of the current partition."
-\return "void"
-*/
-void CreatePad(uint8 *ref, int picwidth, int picheight, int x_pos, int y_pos,
-               uint8 *out, int blkwidth, int blkheight);
-
-void FullPelMC(uint8 *in, int inwidth, uint8 *out, int outpitch,
-               int blkwidth, int blkheight);
-
-void HorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dx);
-
-void HorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dx);
-
-void HorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
-                   int blkwidth, int blkheight);
-
-void VertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dy);
-
-void VertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
-                   int blkwidth, int blkheight);
-
-void VertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dy);
-
-void DiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
-                      uint8 *out, int outpitch,
-                      int blkwidth, int blkheight);
-
-
-void ChromaMotionComp(uint8 *ref, int picwidth, int picheight,
-                      int x_pos, int y_pos, uint8 *pred, int pred_pitch,
-                      int blkwidth, int blkheight);
-
-void ChromaFullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-                     int blkwidth, int blkheight) ;
-void ChromaBorderMC(uint8 *ref, int picwidth, int dx, int dy,
-                    uint8 *pred, int pred_pitch, int blkwidth, int blkheight);
-void ChromaDiagonalMC(uint8 *ref, int picwidth, int dx, int dy,
-                      uint8 *pred, int pred_pitch, int blkwidth, int blkheight);
-
-void ChromaFullPelMCOutside(uint8 *ref, uint8 *pred, int pred_pitch,
-                            int blkwidth, int blkheight, int x_inc,
-                            int y_inc0, int y_inc1, int x_mid, int y_mid);
-void ChromaBorderMCOutside(uint8 *ref, int picwidth, int dx, int dy,
-                           uint8 *pred, int pred_pitch, int blkwidth, int blkheight,
-                           int x_inc, int z_inc, int y_inc0, int y_inc1, int x_mid, int y_mid);
-void ChromaDiagonalMCOutside(uint8 *ref, int picwidth,
-                             int dx, int dy, uint8 *pred, int pred_pitch,
-                             int blkwidth, int blkheight, int x_inc, int z_inc,
-                             int y_inc0, int y_inc1, int x_mid, int y_mid);
-
-void ChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                           uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                             uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                           uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                       uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                            uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                              uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-void ChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                            uint8 *pOut, int predPitch, int blkwidth, int blkheight);
-
-
-/*----------- slice.c ---------------*/
-/**
-This function performs the main decoding loop for slice data including
-INTRA/INTER prediction, transform and quantization and compensation.
-See decode_frame_slice() in JM.
-\param "video"  "Pointer to AVCDecObject."
-\return "AVCDEC_SUCCESS for success, AVCDEC_PICTURE_READY for end-of-picture and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status DecodeSlice(AVCDecObject *video);
-AVCDec_Status ConcealSlice(AVCDecObject *decvid, int mbnum_start, int mbnum_end);
-/**
-This function performs the decoding of one macroblock.
-\param "video"  "Pointer to AVCDecObject."
-\param "prevMbSkipped"  "A value derived in 7.3.4."
-\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status DecodeMB(AVCDecObject *video);
-
-/**
-This function performs macroblock prediction type decoding as in subclause 7.3.5.1.
-\param "video" "Pointer to AVCCommonObj."
-\param "currMB" "Pointer to the current macroblock."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
-
-/**
-This function performs sub-macroblock prediction type decoding as in subclause 7.3.5.2.
-\param "video" "Pointer to AVCCommonObj."
-\param "currMB" "Pointer to the current macroblock."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS for success or AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
-
-/**
-This function interprets the mb_type and sets necessary information
-when the slice type is AVC_I_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretMBModeI(AVCMacroblock *mblock, uint mb_type);
-
-/**
-This function interprets the mb_type and sets necessary information
-when the slice type is AVC_P_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretMBModeP(AVCMacroblock *mblock, uint mb_type);
-
-/**
-This function interprets the mb_type and sets necessary information
-when the slice type is AVC_B_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretMBModeB(AVCMacroblock *mblock, uint mb_type);
-
-/**
-This function interprets the mb_type and sets necessary information
-when the slice type is AVC_SI_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretMBModeSI(AVCMacroblock *mblock, uint mb_type);
-
-/**
-This function interprets the sub_mb_type and sets necessary information
-when the slice type is AVC_P_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "sub_mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretSubMBModeP(AVCMacroblock *mblock, uint *sub_mb_type);
-
-/**
-This function interprets the sub_mb_type and sets necessary information
-when the slice type is AVC_B_SLICE.
-in the macroblock structure.
-\param "mblock" "Pointer to current AVCMacroblock."
-\param "sub_mb_type" "From the syntax bitstream."
-\return "void"
-*/
-void InterpretSubMBModeB(AVCMacroblock *mblock, uint *sub_mb_type);
-
-/**
-This function decodes the Intra4x4 prediction mode from neighboring information
-and from the decoded syntax.
-\param "video"  "Pointer to AVCCommonObj."
-\param "currMB" "Pointer to current macroblock."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status DecodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream);
-
-/*----------- vlc.c -------------------*/
-/**
-This function reads and decodes Exp-Golomb codes.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "codeNum" "Pointer to the value of the codeNum."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status ue_v(AVCDecBitstream *bitstream, uint *codeNum);
-
-/**
-This function reads and decodes signed Exp-Golomb codes.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "value"  "Pointer to syntax element value."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status  se_v(AVCDecBitstream *bitstream, int *value);
-
-/**
-This function reads and decodes signed Exp-Golomb codes for
-32 bit codeword.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "value"  "Pointer to syntax element value."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status  se_v32bit(AVCDecBitstream *bitstream, int32 *value);
-
-/**
-This function reads and decodes truncated Exp-Golomb codes.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "value"  "Pointer to syntax element value."
-\param "range"  "Range of the value as input to determine the algorithm."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status te_v(AVCDecBitstream *bitstream, uint *value, uint range);
-
-/**
-This function parse Exp-Golomb code from the bitstream.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "leadingZeros" "Pointer to the number of leading zeros."
-\param "infobits"   "Pointer to the value after leading zeros and the first one.
-                    The total number of bits read is 2*leadingZeros + 1."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status GetEGBitstring(AVCDecBitstream *bitstream, int *leadingZeros, int *infobits);
-
-/**
-This function parse Exp-Golomb code from the bitstream for 32 bit codewords.
-\param "bitstream" "Pointer to AVCDecBitstream."
-\param "leadingZeros" "Pointer to the number of leading zeros."
-\param "infobits"   "Pointer to the value after leading zeros and the first one.
-                    The total number of bits read is 2*leadingZeros + 1."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status GetEGBitstring32bit(AVCDecBitstream *bitstream, int *leadingZeros, uint32 *infobits);
-
-/**
-This function performs CAVLC decoding of the CBP (coded block pattern) of a macroblock
-by calling ue_v() and then mapping the codeNum to the corresponding CBP value.
-\param "currMB"  "Pointer to the current AVCMacroblock structure."
-\param "stream"  "Pointer to the AVCDecBitstream."
-\return "void"
-*/
-AVCDec_Status DecodeCBP(AVCMacroblock *currMB, AVCDecBitstream *stream);
-
-/**
-This function decodes the syntax for trailing ones and total coefficient.
-Subject to optimization.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "TrailingOnes"   "Pointer to the trailing one variable output."
-\param "TotalCoeff" "Pointer to the total coefficient variable output."
-\param "nC" "Context for number of nonzero coefficient (prediction context)."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_TotalCoeffTrailingOnes(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff, int nC);
-
-/**
-This function decodes the syntax for trailing ones and total coefficient for
-chroma DC block. Subject to optimization.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "TrailingOnes"   "Pointer to the trailing one variable output."
-\param "TotalCoeff" "Pointer to the total coefficient variable output."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_TotalCoeffTrailingOnesChromaDC(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff);
-
-/**
-This function decode a VLC table with 2 output.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "lentab" "Table for code length."
-\param "codtab" "Table for code value."
-\param "tabwidth" "Width of the table or alphabet size of the first output."
-\param "tabheight"  "Height of the table or alphabet size of the second output."
-\param "code1"  "Pointer to the first output."
-\param "code2"  "Pointer to the second output."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status code_from_bitstream_2d(AVCDecBitstream *stream, int *lentab, int *codtab, int tabwidth,
-                                     int tabheight, int *code1, int *code2);
-
-/**
-This function decodes the level_prefix VLC value as in Table 9-6.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "code"   "Pointer to the output."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_LevelPrefix(AVCDecBitstream *stream, uint *code);
-
-/**
-This function decodes total_zeros VLC syntax as in Table 9-7 and 9-8.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "code"   "Pointer to the output."
-\param "TotalCoeff" "Context parameter."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_TotalZeros(AVCDecBitstream *stream, int *code, int TotalCoeff);
-
-/**
-This function decodes total_zeros VLC syntax for chroma DC as in Table 9-9.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "code"   "Pointer to the output."
-\param "TotalCoeff" "Context parameter."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_TotalZerosChromaDC(AVCDecBitstream *stream, int *code, int TotalCoeff);
-
-/**
-This function decodes run_before VLC syntax as in Table 9-10.
-\param "stream" "Pointer to the AVCDecBitstream."
-\param "code"   "Pointer to the output."
-\param "zeroLeft"   "Context parameter."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status ce_RunBefore(AVCDecBitstream *stream, int *code, int zeroLeft);
-
-/*----------- header.c -------------------*/
-/**
-This function parses vui_parameters.
-\param "decvid" "Pointer to AVCDecObject."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status vui_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCSeqParamSet *currSPS);
-AVCDec_Status sei_payload(AVCDecObject *decvid, AVCDecBitstream *stream, uint payloadType, uint payloadSize);
-
-AVCDec_Status buffering_period(AVCDecObject *decvid, AVCDecBitstream *stream);
-AVCDec_Status pic_timing(AVCDecObject *decvid, AVCDecBitstream *stream);
-AVCDec_Status recovery_point(AVCDecObject *decvid, AVCDecBitstream *stream);
-AVCDec_Status dec_ref_pic_marking_repetition(AVCDecObject *decvid, AVCDecBitstream *stream);
-AVCDec_Status motion_constrained_slice_group_set(AVCDecObject *decvid, AVCDecBitstream *stream);
-
-
-/**
-This function parses hrd_parameters.
-\param "decvid" "Pointer to AVCDecObject."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status hrd_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCHRDParams *HRDParam);
-
-/**
-This function decodes the syntax in sequence parameter set slice and fill up the AVCSeqParamSet
-structure.
-\param "decvid" "Pointer to AVCDecObject."
-\param "video" "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status DecodeSPS(AVCDecObject *decvid, AVCDecBitstream *stream);
-
-/**
-This function decodes the syntax in picture parameter set and fill up the AVCPicParamSet
-structure.
-\param "decvid" "Pointer to AVCDecObject."
-\param "video" "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS or AVCDEC_FAIL."
-*/
-AVCDec_Status DecodePPS(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream);
-AVCDec_Status DecodeSEI(AVCDecObject *decvid, AVCDecBitstream *stream);
-
-/**
-This function decodes slice header, calls related functions such as
-reference picture list reordering, prediction weight table, decode ref marking.
-See FirstPartOfSliceHeader() and RestOfSliceHeader() in JM.
-\param "decvid" "Pointer to AVCDecObject."
-\param "video" "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status DecodeSliceHeader(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream);
-
-/**
-This function performes necessary operations to create dummy frames when
-there is a gap in frame_num.
-\param "video"  "Pointer to AVCCommonObj."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status fill_frame_num_gap(AVCHandle *avcHandle, AVCCommonObj *video);
-
-/**
-This function decodes ref_pic_list_reordering related syntax and fill up the AVCSliceHeader
-structure.
-\param "video" "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-\param "sliceHdr" "Pointer to AVCSliceHdr."
-\param "slice_type" "Value of slice_type - 5 if greater than 5."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status ref_pic_list_reordering(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type);
-
-/**
-This function decodes dec_ref_pic_marking related syntax  and fill up the AVCSliceHeader
-structure.
-\param "video" "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-\param "sliceHdr" "Pointer to AVCSliceHdr."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-*/
-AVCDec_Status dec_ref_pic_marking(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr);
-
-/**
-This function performs POC related operation prior to decoding a picture
-\param "video" "Pointer to AVCCommonObj."
-\return "AVCDEC_SUCCESS for success and AVCDEC_FAIL otherwise."
-See also PostPOC() for initialization of some variables.
-*/
-AVCDec_Status DecodePOC(AVCCommonObj *video);
-
-
-
-/*------------ residual.c ------------------*/
-/**
-This function decodes the intra pcm data and fill it in the corresponding location
-on the current picture.
-\param "video"  "Pointer to AVCCommonObj."
-\param "stream" "Pointer to AVCDecBitstream."
-*/
-AVCDec_Status DecodeIntraPCM(AVCCommonObj *video, AVCDecBitstream *stream);
-
-/**
-This function performs residual syntax decoding as well as quantization and transformation of
-the decoded coefficients. See subclause 7.3.5.3.
-\param "video"  "Pointer to AVCDecObject."
-\param "currMB" "Pointer to current macroblock."
-*/
-AVCDec_Status residual(AVCDecObject *video, AVCMacroblock *currMB);
-
-/**
-This function performs CAVLC syntax decoding to get the run and level information of the coefficients.
-\param "video"  "Pointer to AVCDecObject."
-\param "type"   "One of AVCResidualType for a particular 4x4 block."
-\param "bx"     "Horizontal block index."
-\param "by"     "Vertical block index."
-\param "level"  "Pointer to array of level for output."
-\param "run"    "Pointer to array of run for output."
-\param "numcoeff"   "Pointer to the total number of nonzero coefficients."
-\return "AVCDEC_SUCCESS for success."
-*/
-AVCDec_Status residual_block_cavlc(AVCDecObject *video, int nC, int maxNumCoeff,
-                                   int *level, int *run, int *numcoeff);
-
-#endif /* _AVCDEC_LIB_H_ */
diff --git a/media/libstagefright/codecs/avc/dec/src/header.cpp b/media/libstagefright/codecs/avc/dec/src/header.cpp
deleted file mode 100644
index 8681e2b..0000000
--- a/media/libstagefright/codecs/avc/dec/src/header.cpp
+++ /dev/null
@@ -1,1391 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avcdec_lib.h"
-#include "avcdec_bitstream.h"
-#include "avcdec_api.h"
-
-/** see subclause 7.4.2.1 */
-AVCDec_Status DecodeSPS(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    AVCDec_Status status = AVCDEC_SUCCESS;
-    AVCSeqParamSet *seqParam;
-    uint temp;
-    int i;
-    uint profile_idc, constrained_set0_flag, constrained_set1_flag, constrained_set2_flag;
-    uint level_idc, seq_parameter_set_id;
-    void *userData = decvid->avcHandle->userData;
-    AVCHandle *avcHandle = decvid->avcHandle;
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "DecodeSPS", -1, -1);
-
-    BitstreamReadBits(stream, 8, &profile_idc);
-    BitstreamRead1Bit(stream, &constrained_set0_flag);
-//  if (profile_idc != 66 && constrained_set0_flag != 1)
-//  {
-//      return AVCDEC_FAIL;
-//  }
-    BitstreamRead1Bit(stream, &constrained_set1_flag);
-    BitstreamRead1Bit(stream, &constrained_set2_flag);
-    BitstreamReadBits(stream, 5, &temp);
-    BitstreamReadBits(stream, 8, &level_idc);
-    if (level_idc > 51)
-    {
-        return AVCDEC_FAIL;
-    }
-    if (mapLev2Idx[level_idc] == 255)
-    {
-        return AVCDEC_FAIL;
-    }
-    ue_v(stream, &seq_parameter_set_id);
-
-    if (seq_parameter_set_id > 31)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* Allocate sequence param set for seqParams[seq_parameter_set_id]. */
-    if (decvid->seqParams[seq_parameter_set_id] == NULL)  /* allocate seqParams[id] */
-    {
-        decvid->seqParams[seq_parameter_set_id] =
-            (AVCSeqParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSeqParamSet), DEFAULT_ATTR);
-
-        if (decvid->seqParams[seq_parameter_set_id] == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-    }
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "done alloc seqParams", -1, -1);
-
-    seqParam = decvid->seqParams[seq_parameter_set_id];
-
-    seqParam->profile_idc = profile_idc;
-    seqParam->constrained_set0_flag = constrained_set0_flag;
-    seqParam->constrained_set1_flag = constrained_set1_flag;
-    seqParam->constrained_set2_flag = constrained_set2_flag;
-    seqParam->level_idc = level_idc;
-    seqParam->seq_parameter_set_id = seq_parameter_set_id;
-
-    /* continue decoding SPS */
-    ue_v(stream, &(seqParam->log2_max_frame_num_minus4));
-
-    if (seqParam->log2_max_frame_num_minus4 > 12)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    ue_v(stream, &(seqParam->pic_order_cnt_type));
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 1", seqParam->log2_max_frame_num_minus4, seqParam->pic_order_cnt_type);
-
-    if (seqParam->pic_order_cnt_type == 0)
-    {
-        ue_v(stream, &(seqParam->log2_max_pic_order_cnt_lsb_minus4));
-    }
-    else if (seqParam->pic_order_cnt_type == 1)
-    {               // MC_CHECK
-        BitstreamRead1Bit(stream, (uint*)&(seqParam->delta_pic_order_always_zero_flag));
-        se_v32bit(stream, &(seqParam->offset_for_non_ref_pic));
-        se_v32bit(stream, &(seqParam->offset_for_top_to_bottom_field));
-        ue_v(stream, &(seqParam->num_ref_frames_in_pic_order_cnt_cycle));
-
-        for (i = 0; i < (int)(seqParam->num_ref_frames_in_pic_order_cnt_cycle); i++)
-        {
-            se_v32bit(stream, &(seqParam->offset_for_ref_frame[i]));
-        }
-    }
-
-    ue_v(stream, &(seqParam->num_ref_frames));
-
-    if (seqParam->num_ref_frames > 16)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 2", seqParam->num_ref_frames, -1);
-
-    BitstreamRead1Bit(stream, (uint*)&(seqParam->gaps_in_frame_num_value_allowed_flag));
-    ue_v(stream, &(seqParam->pic_width_in_mbs_minus1));
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "picwidth", seqParam->pic_width_in_mbs_minus1, -1);
-
-    ue_v(stream, &(seqParam->pic_height_in_map_units_minus1));
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "picwidth", seqParam->pic_height_in_map_units_minus1, -1);
-
-    BitstreamRead1Bit(stream, (uint*)&(seqParam->frame_mbs_only_flag));
-
-    seqParam->mb_adaptive_frame_field_flag = 0; /* default value */
-    if (!seqParam->frame_mbs_only_flag)
-    {
-        BitstreamRead1Bit(stream, (uint*)&(seqParam->mb_adaptive_frame_field_flag));
-    }
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 3", seqParam->frame_mbs_only_flag, -1);
-
-    BitstreamRead1Bit(stream, (uint*)&(seqParam->direct_8x8_inference_flag));
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 4", seqParam->direct_8x8_inference_flag, -1);
-
-    BitstreamRead1Bit(stream, (uint*)&(seqParam->frame_cropping_flag));
-    seqParam->frame_crop_left_offset = 0;  /* default value */
-    seqParam->frame_crop_right_offset = 0;/* default value */
-    seqParam->frame_crop_top_offset = 0;/* default value */
-    seqParam->frame_crop_bottom_offset = 0;/* default value */
-    if (seqParam->frame_cropping_flag)
-    {
-        ue_v(stream, &(seqParam->frame_crop_left_offset));
-        ue_v(stream, &(seqParam->frame_crop_right_offset));
-        ue_v(stream, &(seqParam->frame_crop_top_offset));
-        ue_v(stream, &(seqParam->frame_crop_bottom_offset));
-    }
-
-    DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "check point 5", seqParam->frame_cropping_flag, -1);
-
-    BitstreamRead1Bit(stream, (uint*)&(seqParam->vui_parameters_present_flag));
-    if (seqParam->vui_parameters_present_flag)
-    {
-        status = vui_parameters(decvid, stream, seqParam);
-        if (status != AVCDEC_SUCCESS)
-        {
-            return AVCDEC_FAIL;
-        }
-    }
-
-    return status;
-}
-
-
-AVCDec_Status vui_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCSeqParamSet *currSPS)
-{
-    uint temp;
-    uint temp32;
-    uint aspect_ratio_idc, overscan_appopriate_flag, video_format, video_full_range_flag;
-    /* aspect_ratio_info_present_flag */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        BitstreamReadBits(stream, 8, &aspect_ratio_idc);
-        if (aspect_ratio_idc == 255)
-        {
-            /* sar_width */
-            BitstreamReadBits(stream, 16, &temp);
-            /* sar_height */
-            BitstreamReadBits(stream, 16, &temp);
-        }
-    }
-    /* overscan_info_present */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        BitstreamRead1Bit(stream, &overscan_appopriate_flag);
-    }
-    /* video_signal_type_present_flag */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        BitstreamReadBits(stream, 3, &video_format);
-        BitstreamRead1Bit(stream, &video_full_range_flag);
-        /* colour_description_present_flag */
-        BitstreamRead1Bit(stream, &temp);
-        if (temp)
-        {
-            /* colour_primaries */
-            BitstreamReadBits(stream, 8, &temp);
-            /* transfer_characteristics */
-            BitstreamReadBits(stream, 8, &temp);
-            /* matrix coefficients */
-            BitstreamReadBits(stream, 8, &temp);
-        }
-    }
-    /*  chroma_loc_info_present_flag */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        /*  chroma_sample_loc_type_top_field */
-        ue_v(stream, &temp);
-        /*  chroma_sample_loc_type_bottom_field */
-        ue_v(stream, &temp);
-    }
-
-    /*  timing_info_present_flag*/
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        /*  num_unit_in_tick*/
-        BitstreamReadBits(stream, 32, &temp32);
-        /*  time_scale */
-        BitstreamReadBits(stream, 32, &temp32);
-        /*  fixed_frame_rate_flag */
-        BitstreamRead1Bit(stream, &temp);
-    }
-
-    /*  nal_hrd_parameters_present_flag */
-    BitstreamRead1Bit(stream, &temp);
-    currSPS->vui_parameters.nal_hrd_parameters_present_flag = temp;
-    if (temp)
-    {
-        hrd_parameters(decvid, stream, &(currSPS->vui_parameters.nal_hrd_parameters));
-    }
-    /*  vcl_hrd_parameters_present_flag*/
-    BitstreamRead1Bit(stream, &temp);
-    currSPS->vui_parameters.vcl_hrd_parameters_present_flag = temp;
-    if (temp)
-    {
-        hrd_parameters(decvid, stream, &(currSPS->vui_parameters.vcl_hrd_parameters));
-    }
-    if (currSPS->vui_parameters.nal_hrd_parameters_present_flag || currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
-    {
-        /*  low_delay_hrd_flag */
-        BitstreamRead1Bit(stream, &temp);
-    }
-    /*  pic_struct_present_flag */
-    BitstreamRead1Bit(stream, &temp);
-    currSPS->vui_parameters.pic_struct_present_flag = temp;
-    /*  bitstream_restriction_flag */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        /*  motion_vectors_over_pic_boundaries_flag */
-        BitstreamRead1Bit(stream, &temp);
-        /*  max_bytes_per_pic_denom */
-        ue_v(stream, &temp);
-        /*  max_bits_per_mb_denom */
-        ue_v(stream, &temp);
-        /*  log2_max_mv_length_horizontal */
-        ue_v(stream, &temp);
-        /*  log2_max_mv_length_vertical */
-        ue_v(stream, &temp);
-        /*  num_reorder_frames */
-        ue_v(stream, &temp);
-        /*  max_dec_frame_buffering */
-        ue_v(stream, &temp);
-    }
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status hrd_parameters(AVCDecObject *decvid, AVCDecBitstream *stream, AVCHRDParams *HRDParam)
-{
-    OSCL_UNUSED_ARG(decvid);
-    uint temp;
-    uint cpb_cnt_minus1;
-    uint i;
-    ue_v(stream, &cpb_cnt_minus1);
-    HRDParam->cpb_cnt_minus1 = cpb_cnt_minus1;
-    /*  bit_rate_scale */
-    BitstreamReadBits(stream, 4, &temp);
-    /*  cpb_size_scale */
-    BitstreamReadBits(stream, 4, &temp);
-    for (i = 0; i <= cpb_cnt_minus1; i++)
-    {
-        /*  bit_rate_value_minus1[i] */
-        ue_v(stream, &temp);
-        /*  cpb_size_value_minus1[i] */
-        ue_v(stream, &temp);
-        /*  cbr_flag[i] */
-        ue_v(stream, &temp);
-    }
-    /*  initial_cpb_removal_delay_length_minus1 */
-    BitstreamReadBits(stream, 5, &temp);
-    /*  cpb_removal_delay_length_minus1 */
-    BitstreamReadBits(stream, 5, &temp);
-    HRDParam->cpb_removal_delay_length_minus1 = temp;
-    /*  dpb_output_delay_length_minus1 */
-    BitstreamReadBits(stream, 5, &temp);
-    HRDParam->dpb_output_delay_length_minus1 = temp;
-    /*  time_offset_length  */
-    BitstreamReadBits(stream, 5, &temp);
-    HRDParam->time_offset_length = temp;
-    return AVCDEC_SUCCESS;
-}
-
-
-/** see subclause 7.4.2.2 */
-AVCDec_Status DecodePPS(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream)
-{
-    AVCPicParamSet *picParam;
-    AVCDec_Status status;
-    int i, iGroup, numBits;
-    int PicWidthInMbs, PicHeightInMapUnits, PicSizeInMapUnits;
-    uint pic_parameter_set_id, seq_parameter_set_id;
-    void *userData = decvid->avcHandle->userData;
-    AVCHandle *avcHandle = decvid->avcHandle;
-
-    ue_v(stream, &pic_parameter_set_id);
-    if (pic_parameter_set_id > 255)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    ue_v(stream, &seq_parameter_set_id);
-
-    if (seq_parameter_set_id > 31)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* 2.1 if picParams[pic_param_set_id] is NULL, allocate it. */
-    if (decvid->picParams[pic_parameter_set_id] == NULL)
-    {
-        decvid->picParams[pic_parameter_set_id] =
-            (AVCPicParamSet*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCPicParamSet), DEFAULT_ATTR);
-        if (decvid->picParams[pic_parameter_set_id] == NULL)
-        {
-            return AVCDEC_MEMORY_FAIL;
-        }
-
-        decvid->picParams[pic_parameter_set_id]->slice_group_id = NULL;
-    }
-
-    video->currPicParams = picParam = decvid->picParams[pic_parameter_set_id];
-    picParam->seq_parameter_set_id = seq_parameter_set_id;
-    picParam->pic_parameter_set_id = pic_parameter_set_id;
-
-    BitstreamRead1Bit(stream, (uint*)&(picParam->entropy_coding_mode_flag));
-    if (picParam->entropy_coding_mode_flag)
-    {
-        status = AVCDEC_FAIL;
-        goto clean_up;
-    }
-    BitstreamRead1Bit(stream, (uint*)&(picParam->pic_order_present_flag));
-    ue_v(stream, &(picParam->num_slice_groups_minus1));
-
-    if (picParam->num_slice_groups_minus1 > MAX_NUM_SLICE_GROUP - 1)
-    {
-        status = AVCDEC_FAIL;
-        goto clean_up;
-    }
-
-    picParam->slice_group_change_rate_minus1 = 0; /* default value */
-    if (picParam->num_slice_groups_minus1 > 0)
-    {
-        ue_v(stream, &(picParam->slice_group_map_type));
-        if (picParam->slice_group_map_type == 0)
-        {
-            for (iGroup = 0; iGroup <= (int)picParam->num_slice_groups_minus1; iGroup++)
-            {
-                ue_v(stream, &(picParam->run_length_minus1[iGroup]));
-            }
-        }
-        else if (picParam->slice_group_map_type == 2)
-        {   // MC_CHECK  <= or <
-            for (iGroup = 0; iGroup < (int)picParam->num_slice_groups_minus1; iGroup++)
-            {
-                ue_v(stream, &(picParam->top_left[iGroup]));
-                ue_v(stream, &(picParam->bottom_right[iGroup]));
-            }
-        }
-        else if (picParam->slice_group_map_type == 3 ||
-                 picParam->slice_group_map_type == 4 ||
-                 picParam->slice_group_map_type == 5)
-        {
-            BitstreamRead1Bit(stream, (uint*)&(picParam->slice_group_change_direction_flag));
-            ue_v(stream, &(picParam->slice_group_change_rate_minus1));
-        }
-        else if (picParam->slice_group_map_type == 6)
-        {
-            ue_v(stream, &(picParam->pic_size_in_map_units_minus1));
-
-            numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
-            i = picParam->num_slice_groups_minus1;
-            while (i > 0)
-            {
-                numBits++;
-                i >>= 1;
-            }
-
-            i = picParam->seq_parameter_set_id;
-            if (decvid->seqParams[i] == NULL)
-            {
-                status = AVCDEC_FAIL;
-                goto clean_up;
-            }
-
-
-            PicWidthInMbs = decvid->seqParams[i]->pic_width_in_mbs_minus1 + 1;
-            PicHeightInMapUnits = decvid->seqParams[i]->pic_height_in_map_units_minus1 + 1 ;
-            PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits ;
-
-            /* information has to be consistent with the seq_param */
-            if ((int)picParam->pic_size_in_map_units_minus1 != PicSizeInMapUnits - 1)
-            {
-                status = AVCDEC_FAIL;
-                goto clean_up;
-            }
-
-            if (picParam->slice_group_id)
-            {
-                avcHandle->CBAVC_Free(userData, (int)picParam->slice_group_id);
-            }
-            picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * PicSizeInMapUnits, DEFAULT_ATTR);
-            if (picParam->slice_group_id == NULL)
-            {
-                status =  AVCDEC_MEMORY_FAIL;
-                goto clean_up;
-            }
-
-            for (i = 0; i < PicSizeInMapUnits; i++)
-            {
-                BitstreamReadBits(stream, numBits, &(picParam->slice_group_id[i]));
-            }
-        }
-
-    }
-
-    ue_v(stream, &(picParam->num_ref_idx_l0_active_minus1));
-    if (picParam->num_ref_idx_l0_active_minus1 > 31)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    ue_v(stream, &(picParam->num_ref_idx_l1_active_minus1));
-    if (picParam->num_ref_idx_l1_active_minus1 > 31)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    BitstreamRead1Bit(stream, (uint*)&(picParam->weighted_pred_flag));
-    BitstreamReadBits(stream, 2, &(picParam->weighted_bipred_idc));
-    if (picParam->weighted_bipred_idc > 2)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    se_v(stream, &(picParam->pic_init_qp_minus26));
-    if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    se_v(stream, &(picParam->pic_init_qs_minus26));
-    if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    se_v(stream, &(picParam->chroma_qp_index_offset));
-    if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
-    {
-        status = AVCDEC_FAIL; /* out of range */
-        status = AVCDEC_FAIL; /* out of range */
-        goto clean_up;
-    }
-
-    BitstreamReadBits(stream, 3, &pic_parameter_set_id);
-    picParam->deblocking_filter_control_present_flag = pic_parameter_set_id >> 2;
-    picParam->constrained_intra_pred_flag = (pic_parameter_set_id >> 1) & 1;
-    picParam->redundant_pic_cnt_present_flag = pic_parameter_set_id & 1;
-
-    return AVCDEC_SUCCESS;
-clean_up:
-    if (decvid->picParams[pic_parameter_set_id])
-    {
-        if (picParam->slice_group_id)
-        {
-            avcHandle->CBAVC_Free(userData, (int)picParam->slice_group_id);
-        }
-        decvid->picParams[pic_parameter_set_id]->slice_group_id = NULL;
-        avcHandle->CBAVC_Free(userData, (int)decvid->picParams[pic_parameter_set_id]);
-        decvid->picParams[pic_parameter_set_id] = NULL;
-        return status;
-    }
-    return AVCDEC_SUCCESS;
-}
-
-
-/* FirstPartOfSliceHeader();
-    RestOfSliceHeader() */
-/** see subclause 7.4.3 */
-AVCDec_Status DecodeSliceHeader(AVCDecObject *decvid, AVCCommonObj *video, AVCDecBitstream *stream)
-{
-    AVCSliceHeader *sliceHdr = video->sliceHdr;
-    AVCPicParamSet *currPPS;
-    AVCSeqParamSet *currSPS;
-    AVCDec_Status status;
-    uint idr_pic_id;
-    int slice_type, temp, i;
-
-    ue_v(stream, &(sliceHdr->first_mb_in_slice));
-    ue_v(stream, (uint*)&slice_type);
-
-    if (sliceHdr->first_mb_in_slice != 0)
-    {
-        if ((int)sliceHdr->slice_type >= 5 && slice_type != (int)sliceHdr->slice_type - 5)
-        {
-            return AVCDEC_FAIL; /* slice type doesn't follow the first slice in the picture */
-        }
-    }
-    sliceHdr->slice_type = (AVCSliceType) slice_type;
-    if (slice_type > 4)
-    {
-        slice_type -= 5;
-    }
-
-    if (slice_type == 1 || slice_type > 2)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    video->slice_type = (AVCSliceType) slice_type;
-
-    ue_v(stream, &(sliceHdr->pic_parameter_set_id));
-    /* end FirstPartSliceHeader() */
-    /* begin RestOfSliceHeader() */
-    /* after getting pic_parameter_set_id, we have to load corresponding SPS and PPS */
-    if (sliceHdr->pic_parameter_set_id > 255)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    if (decvid->picParams[sliceHdr->pic_parameter_set_id] == NULL)
-        return AVCDEC_FAIL; /* PPS doesn't exist */
-
-    currPPS = video->currPicParams = decvid->picParams[sliceHdr->pic_parameter_set_id];
-
-    if (decvid->seqParams[currPPS->seq_parameter_set_id] == NULL)
-        return AVCDEC_FAIL; /* SPS doesn't exist */
-
-    currSPS = video->currSeqParams = decvid->seqParams[currPPS->seq_parameter_set_id];
-
-    if (currPPS->seq_parameter_set_id != video->seq_parameter_set_id)
-    {
-        video->seq_parameter_set_id = currPPS->seq_parameter_set_id;
-        status = (AVCDec_Status)AVCConfigureSequence(decvid->avcHandle, video, false);
-        if (status != AVCDEC_SUCCESS)
-            return status;
-        video->level_idc = currSPS->level_idc;
-    }
-
-    /* derived variables from SPS */
-    video->MaxFrameNum = 1 << (currSPS->log2_max_frame_num_minus4 + 4);
-    // MC_OPTIMIZE
-    video->PicWidthInMbs = currSPS->pic_width_in_mbs_minus1 + 1;
-    video->PicWidthInSamplesL = video->PicWidthInMbs * 16 ;
-    video->PicWidthInSamplesC = video->PicWidthInMbs * 8 ;
-    video->PicHeightInMapUnits = currSPS->pic_height_in_map_units_minus1 + 1 ;
-    video->PicSizeInMapUnits = video->PicWidthInMbs * video->PicHeightInMapUnits ;
-    video->FrameHeightInMbs = (2 - currSPS->frame_mbs_only_flag) * video->PicHeightInMapUnits ;
-
-    /* derived from PPS */
-    video->SliceGroupChangeRate = currPPS->slice_group_change_rate_minus1 + 1;
-
-    /* then we can continue decoding slice header */
-
-    BitstreamReadBits(stream, currSPS->log2_max_frame_num_minus4 + 4, &(sliceHdr->frame_num));
-
-    if (video->currFS == NULL && sliceHdr->frame_num != 0)
-    {
-        video->prevFrameNum = video->PrevRefFrameNum = sliceHdr->frame_num - 1;
-    }
-
-    if (!currSPS->frame_mbs_only_flag)
-    {
-        BitstreamRead1Bit(stream, &(sliceHdr->field_pic_flag));
-        if (sliceHdr->field_pic_flag)
-        {
-            return AVCDEC_FAIL;
-        }
-    }
-
-    /* derived variables from slice header*/
-    video->PicHeightInMbs = video->FrameHeightInMbs;
-    video->PicHeightInSamplesL = video->PicHeightInMbs * 16;
-    video->PicHeightInSamplesC = video->PicHeightInMbs * 8;
-    video->PicSizeInMbs = video->PicWidthInMbs * video->PicHeightInMbs;
-
-    if (sliceHdr->first_mb_in_slice >= video->PicSizeInMbs)
-    {
-        return AVCDEC_FAIL;
-    }
-    video->MaxPicNum = video->MaxFrameNum;
-    video->CurrPicNum = sliceHdr->frame_num;
-
-
-    if (video->nal_unit_type == AVC_NALTYPE_IDR)
-    {
-        if (sliceHdr->frame_num != 0)
-        {
-            return AVCDEC_FAIL;
-        }
-        ue_v(stream, &idr_pic_id);
-    }
-
-    sliceHdr->delta_pic_order_cnt_bottom = 0; /* default value */
-    sliceHdr->delta_pic_order_cnt[0] = 0; /* default value */
-    sliceHdr->delta_pic_order_cnt[1] = 0; /* default value */
-    if (currSPS->pic_order_cnt_type == 0)
-    {
-        BitstreamReadBits(stream, currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4,
-                          &(sliceHdr->pic_order_cnt_lsb));
-        video->MaxPicOrderCntLsb =  1 << (currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4);
-        if (sliceHdr->pic_order_cnt_lsb > video->MaxPicOrderCntLsb - 1)
-            return AVCDEC_FAIL; /* out of range */
-
-        if (currPPS->pic_order_present_flag)
-        {
-            se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt_bottom));
-        }
-    }
-    if (currSPS->pic_order_cnt_type == 1 && !currSPS->delta_pic_order_always_zero_flag)
-    {
-        se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt[0]));
-        if (currPPS->pic_order_present_flag)
-        {
-            se_v32bit(stream, &(sliceHdr->delta_pic_order_cnt[1]));
-        }
-    }
-
-    sliceHdr->redundant_pic_cnt = 0; /* default value */
-    if (currPPS->redundant_pic_cnt_present_flag)
-    {
-        // MC_CHECK
-        ue_v(stream, &(sliceHdr->redundant_pic_cnt));
-        if (sliceHdr->redundant_pic_cnt > 127) /* out of range */
-            return AVCDEC_FAIL;
-
-        if (sliceHdr->redundant_pic_cnt > 0) /* redundant picture */
-            return AVCDEC_FAIL; /* not supported */
-    }
-    sliceHdr->num_ref_idx_l0_active_minus1 = currPPS->num_ref_idx_l0_active_minus1;
-    sliceHdr->num_ref_idx_l1_active_minus1 = currPPS->num_ref_idx_l1_active_minus1;
-
-    if (slice_type == AVC_P_SLICE)
-    {
-        BitstreamRead1Bit(stream, &(sliceHdr->num_ref_idx_active_override_flag));
-        if (sliceHdr->num_ref_idx_active_override_flag)
-        {
-            ue_v(stream, &(sliceHdr->num_ref_idx_l0_active_minus1));
-        }
-        else  /* the following condition is not allowed if the flag is zero */
-        {
-            if ((slice_type == AVC_P_SLICE) && currPPS->num_ref_idx_l0_active_minus1 > 15)
-            {
-                return AVCDEC_FAIL; /* not allowed */
-            }
-        }
-    }
-
-
-    if (sliceHdr->num_ref_idx_l0_active_minus1 > 15 ||
-            sliceHdr->num_ref_idx_l1_active_minus1 > 15)
-    {
-        return AVCDEC_FAIL; /* not allowed */
-    }
-    /* if MbaffFrameFlag =1,
-    max value of index is num_ref_idx_l0_active_minus1 for frame MBs and
-    2*sliceHdr->num_ref_idx_l0_active_minus1 + 1 for field MBs */
-
-    /* ref_pic_list_reordering() */
-    status = ref_pic_list_reordering(video, stream, sliceHdr, slice_type);
-    if (status != AVCDEC_SUCCESS)
-    {
-        return status;
-    }
-
-
-    if (video->nal_ref_idc != 0)
-    {
-        dec_ref_pic_marking(video, stream, sliceHdr);
-    }
-    se_v(stream, &(sliceHdr->slice_qp_delta));
-
-    video->QPy = 26 + currPPS->pic_init_qp_minus26 + sliceHdr->slice_qp_delta;
-    if (video->QPy > 51 || video->QPy < 0)
-    {
-        video->QPy = AVC_CLIP3(0, 51, video->QPy);
-//                  return AVCDEC_FAIL;
-    }
-    video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->QPy + video->currPicParams->chroma_qp_index_offset)];
-
-    video->QPy_div_6 = (video->QPy * 43) >> 8;
-    video->QPy_mod_6 = video->QPy - 6 * video->QPy_div_6;
-
-    video->QPc_div_6 = (video->QPc * 43) >> 8;
-    video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
-
-    sliceHdr->slice_alpha_c0_offset_div2 = 0;
-    sliceHdr->slice_beta_offset_div_2 = 0;
-    sliceHdr->disable_deblocking_filter_idc = 0;
-    video->FilterOffsetA = video->FilterOffsetB = 0;
-
-    if (currPPS->deblocking_filter_control_present_flag)
-    {
-        ue_v(stream, &(sliceHdr->disable_deblocking_filter_idc));
-        if (sliceHdr->disable_deblocking_filter_idc > 2)
-        {
-            return AVCDEC_FAIL; /* out of range */
-        }
-        if (sliceHdr->disable_deblocking_filter_idc != 1)
-        {
-            se_v(stream, &(sliceHdr->slice_alpha_c0_offset_div2));
-            if (sliceHdr->slice_alpha_c0_offset_div2 < -6 ||
-                    sliceHdr->slice_alpha_c0_offset_div2 > 6)
-            {
-                return AVCDEC_FAIL;
-            }
-            video->FilterOffsetA = sliceHdr->slice_alpha_c0_offset_div2 << 1;
-
-            se_v(stream, &(sliceHdr->slice_beta_offset_div_2));
-            if (sliceHdr->slice_beta_offset_div_2 < -6 ||
-                    sliceHdr->slice_beta_offset_div_2 > 6)
-            {
-                return AVCDEC_FAIL;
-            }
-            video->FilterOffsetB = sliceHdr->slice_beta_offset_div_2 << 1;
-        }
-    }
-
-    if (currPPS->num_slice_groups_minus1 > 0 && currPPS->slice_group_map_type >= 3
-            && currPPS->slice_group_map_type <= 5)
-    {
-        /* Ceil(Log2(PicSizeInMapUnits/(float)SliceGroupChangeRate + 1)) */
-        temp = video->PicSizeInMapUnits / video->SliceGroupChangeRate;
-        if (video->PicSizeInMapUnits % video->SliceGroupChangeRate)
-        {
-            temp++;
-        }
-        i = 0;
-        temp++;
-        while (temp)
-        {
-            temp >>= 1;
-            i++;
-        }
-
-        BitstreamReadBits(stream, i, &(sliceHdr->slice_group_change_cycle));
-        video->MapUnitsInSliceGroup0 =
-            AVC_MIN(sliceHdr->slice_group_change_cycle * video->SliceGroupChangeRate, video->PicSizeInMapUnits);
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-
-AVCDec_Status fill_frame_num_gap(AVCHandle *avcHandle, AVCCommonObj *video)
-{
-    AVCDec_Status status;
-    int CurrFrameNum;
-    int UnusedShortTermFrameNum;
-    int tmp1 = video->sliceHdr->delta_pic_order_cnt[0];
-    int tmp2 = video->sliceHdr->delta_pic_order_cnt[1];
-    int tmp3 = video->CurrPicNum;
-    int tmp4 = video->sliceHdr->adaptive_ref_pic_marking_mode_flag;
-    UnusedShortTermFrameNum = (video->prevFrameNum + 1) % video->MaxFrameNum;
-    CurrFrameNum = video->sliceHdr->frame_num;
-
-    video->sliceHdr->delta_pic_order_cnt[0] = 0;
-    video->sliceHdr->delta_pic_order_cnt[1] = 0;
-    while (CurrFrameNum != UnusedShortTermFrameNum)
-    {
-        video->CurrPicNum = UnusedShortTermFrameNum;
-        video->sliceHdr->frame_num = UnusedShortTermFrameNum;
-
-        status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
-        if (status != AVCDEC_SUCCESS)  /* no buffer available */
-        {
-            return status;
-        }
-        DecodePOC(video);
-        DPBInitPic(video, UnusedShortTermFrameNum);
-
-
-        video->currFS->PicOrderCnt = video->PicOrderCnt;
-        video->currFS->FrameNum = video->sliceHdr->frame_num;
-
-        /* initialize everything to zero */
-        video->currFS->IsOutputted = 0x01;
-        video->currFS->IsReference = 3;
-        video->currFS->IsLongTerm = 0;
-        video->currFS->frame.isReference = TRUE;
-        video->currFS->frame.isLongTerm = FALSE;
-
-        video->sliceHdr->adaptive_ref_pic_marking_mode_flag = 0;
-
-        status = (AVCDec_Status)StorePictureInDPB(avcHandle, video);  // MC_CHECK check the return status
-        if (status != AVCDEC_SUCCESS)
-        {
-            return AVCDEC_FAIL;
-        }
-        video->prevFrameNum = UnusedShortTermFrameNum;
-        UnusedShortTermFrameNum = (UnusedShortTermFrameNum + 1) % video->MaxFrameNum;
-    }
-    video->sliceHdr->frame_num = CurrFrameNum;
-    video->CurrPicNum = tmp3;
-    video->sliceHdr->delta_pic_order_cnt[0] = tmp1;
-    video->sliceHdr->delta_pic_order_cnt[1] = tmp2;
-    video->sliceHdr->adaptive_ref_pic_marking_mode_flag = tmp4;
-    return AVCDEC_SUCCESS;
-}
-
-/** see subclause 7.4.3.1 */
-AVCDec_Status ref_pic_list_reordering(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type)
-{
-    int i;
-
-    if (slice_type != AVC_I_SLICE)
-    {
-        BitstreamRead1Bit(stream, &(sliceHdr->ref_pic_list_reordering_flag_l0));
-        if (sliceHdr->ref_pic_list_reordering_flag_l0)
-        {
-            i = 0;
-            do
-            {
-                ue_v(stream, &(sliceHdr->reordering_of_pic_nums_idc_l0[i]));
-                if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 ||
-                        sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1)
-                {
-                    ue_v(stream, &(sliceHdr->abs_diff_pic_num_minus1_l0[i]));
-                    if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 &&
-                            sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum / 2 - 1)
-                    {
-                        return AVCDEC_FAIL; /* out of range */
-                    }
-                    if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1 &&
-                            sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum / 2 - 2)
-                    {
-                        return AVCDEC_FAIL; /* out of range */
-                    }
-                }
-                else if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 2)
-                {
-                    ue_v(stream, &(sliceHdr->long_term_pic_num_l0[i]));
-                }
-                i++;
-            }
-            while (sliceHdr->reordering_of_pic_nums_idc_l0[i-1] != 3
-                    && i <= (int)sliceHdr->num_ref_idx_l0_active_minus1 + 1) ;
-        }
-    }
-    return AVCDEC_SUCCESS;
-}
-
-/** see subclause 7.4.3.3 */
-AVCDec_Status dec_ref_pic_marking(AVCCommonObj *video, AVCDecBitstream *stream, AVCSliceHeader *sliceHdr)
-{
-    int i;
-    if (video->nal_unit_type == AVC_NALTYPE_IDR)
-    {
-        BitstreamRead1Bit(stream, &(sliceHdr->no_output_of_prior_pics_flag));
-        BitstreamRead1Bit(stream, &(sliceHdr->long_term_reference_flag));
-        if (sliceHdr->long_term_reference_flag == 0) /* used for short-term */
-        {
-            video->MaxLongTermFrameIdx = -1; /* no long-term frame indx */
-        }
-        else /* used for long-term */
-        {
-            video->MaxLongTermFrameIdx = 0;
-            video->LongTermFrameIdx = 0;
-        }
-    }
-    else
-    {
-        BitstreamRead1Bit(stream, &(sliceHdr->adaptive_ref_pic_marking_mode_flag));
-        if (sliceHdr->adaptive_ref_pic_marking_mode_flag)
-        {
-            i = 0;
-            do
-            {
-                ue_v(stream, &(sliceHdr->memory_management_control_operation[i]));
-                if (sliceHdr->memory_management_control_operation[i] == 1 ||
-                        sliceHdr->memory_management_control_operation[i] == 3)
-                {
-                    ue_v(stream, &(sliceHdr->difference_of_pic_nums_minus1[i]));
-                }
-                if (sliceHdr->memory_management_control_operation[i] == 2)
-                {
-                    ue_v(stream, &(sliceHdr->long_term_pic_num[i]));
-                }
-                if (sliceHdr->memory_management_control_operation[i] == 3 ||
-                        sliceHdr->memory_management_control_operation[i] == 6)
-                {
-                    ue_v(stream, &(sliceHdr->long_term_frame_idx[i]));
-                }
-                if (sliceHdr->memory_management_control_operation[i] == 4)
-                {
-                    ue_v(stream, &(sliceHdr->max_long_term_frame_idx_plus1[i]));
-                }
-                i++;
-            }
-            while (sliceHdr->memory_management_control_operation[i-1] != 0 && i < MAX_DEC_REF_PIC_MARKING);
-            if (i >= MAX_DEC_REF_PIC_MARKING)
-            {
-                return AVCDEC_FAIL; /* we're screwed!!, not enough memory */
-            }
-        }
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see subclause 8.2.1 Decoding process for picture order count. */
-AVCDec_Status DecodePOC(AVCCommonObj *video)
-{
-    AVCSeqParamSet *currSPS = video->currSeqParams;
-    AVCSliceHeader *sliceHdr = video->sliceHdr;
-    int i;
-
-    switch (currSPS->pic_order_cnt_type)
-    {
-        case 0: /* POC MODE 0 , subclause 8.2.1.1 */
-            if (video->nal_unit_type == AVC_NALTYPE_IDR)
-            {
-                video->prevPicOrderCntMsb = 0;
-                video->prevPicOrderCntLsb = 0;
-            }
-
-            /* Calculate the MSBs of current picture */
-            if (sliceHdr->pic_order_cnt_lsb  <  video->prevPicOrderCntLsb  &&
-                    (video->prevPicOrderCntLsb - sliceHdr->pic_order_cnt_lsb)  >= (video->MaxPicOrderCntLsb / 2))
-                video->PicOrderCntMsb = video->prevPicOrderCntMsb + video->MaxPicOrderCntLsb;
-            else if (sliceHdr->pic_order_cnt_lsb  >  video->prevPicOrderCntLsb  &&
-                     (sliceHdr->pic_order_cnt_lsb - video->prevPicOrderCntLsb)  > (video->MaxPicOrderCntLsb / 2))
-                video->PicOrderCntMsb = video->prevPicOrderCntMsb - video->MaxPicOrderCntLsb;
-            else
-                video->PicOrderCntMsb = video->prevPicOrderCntMsb;
-
-            /* JVT-I010 page 81 is different from JM7.3 */
-
-
-            video->PicOrderCnt = video->TopFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
-            video->BottomFieldOrderCnt = video->TopFieldOrderCnt + sliceHdr->delta_pic_order_cnt_bottom;
-
-            break;
-
-
-        case 1: /* POC MODE 1, subclause 8.2.1.2 */
-            /* calculate FrameNumOffset */
-            if (video->nal_unit_type == AVC_NALTYPE_IDR)
-            {
-                video->prevFrameNumOffset = 0;
-                video->FrameNumOffset = 0;
-            }
-            else if (video->prevFrameNum > sliceHdr->frame_num)
-            {
-                video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
-            }
-            else
-            {
-                video->FrameNumOffset = video->prevFrameNumOffset;
-            }
-            /* calculate absFrameNum */
-            if (currSPS->num_ref_frames_in_pic_order_cnt_cycle)
-            {
-                video->absFrameNum = video->FrameNumOffset + sliceHdr->frame_num;
-            }
-            else
-            {
-                video->absFrameNum = 0;
-            }
-
-            if (video->absFrameNum > 0 && video->nal_ref_idc == 0)
-            {
-                video->absFrameNum--;
-            }
-
-            /* derive picOrderCntCycleCnt and frameNumInPicOrderCntCycle */
-            if (video->absFrameNum > 0)
-            {
-                video->picOrderCntCycleCnt = (video->absFrameNum - 1) / currSPS->num_ref_frames_in_pic_order_cnt_cycle;
-                video->frameNumInPicOrderCntCycle = (video->absFrameNum - 1) % currSPS->num_ref_frames_in_pic_order_cnt_cycle;
-            }
-            /* derive expectedDeltaPerPicOrderCntCycle */
-            video->expectedDeltaPerPicOrderCntCycle = 0;
-            for (i = 0; i < (int)currSPS->num_ref_frames_in_pic_order_cnt_cycle; i++)
-            {
-                video->expectedDeltaPerPicOrderCntCycle += currSPS->offset_for_ref_frame[i];
-            }
-            /* derive expectedPicOrderCnt */
-            if (video->absFrameNum)
-            {
-                video->expectedPicOrderCnt = video->picOrderCntCycleCnt * video->expectedDeltaPerPicOrderCntCycle;
-                for (i = 0; i <= video->frameNumInPicOrderCntCycle; i++)
-                {
-                    video->expectedPicOrderCnt += currSPS->offset_for_ref_frame[i];
-                }
-            }
-            else
-            {
-                video->expectedPicOrderCnt = 0;
-            }
-
-            if (video->nal_ref_idc == 0)
-            {
-                video->expectedPicOrderCnt += currSPS->offset_for_non_ref_pic;
-            }
-            /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
-
-            video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
-            video->BottomFieldOrderCnt = video->TopFieldOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[1];
-
-            video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
-
-
-            break;
-
-
-        case 2: /* POC MODE 2, subclause 8.2.1.3 */
-            if (video->nal_unit_type == AVC_NALTYPE_IDR)
-            {
-                video->FrameNumOffset = 0;
-            }
-            else if (video->prevFrameNum > sliceHdr->frame_num)
-            {
-                video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
-            }
-            else
-            {
-                video->FrameNumOffset = video->prevFrameNumOffset;
-            }
-            /* derive tempPicOrderCnt, we just use PicOrderCnt */
-            if (video->nal_unit_type == AVC_NALTYPE_IDR)
-            {
-                video->PicOrderCnt = 0;
-            }
-            else if (video->nal_ref_idc == 0)
-            {
-                video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num) - 1;
-            }
-            else
-            {
-                video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num);
-            }
-            video->TopFieldOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCnt;
-            break;
-        default:
-            return AVCDEC_FAIL;
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-
-AVCDec_Status DecodeSEI(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    OSCL_UNUSED_ARG(decvid);
-    OSCL_UNUSED_ARG(stream);
-    return AVCDEC_SUCCESS;
-}
-
-AVCDec_Status sei_payload(AVCDecObject *decvid, AVCDecBitstream *stream, uint payloadType, uint payloadSize)
-{
-    AVCDec_Status status = AVCDEC_SUCCESS;
-    uint i;
-    switch (payloadType)
-    {
-        case 0:
-            /*  buffering period SEI */
-            status = buffering_period(decvid, stream);
-            break;
-        case 1:
-            /*  picture timing SEI */
-            status = pic_timing(decvid, stream);
-            break;
-        case 2:
-
-        case 3:
-
-        case 4:
-
-        case 5:
-
-        case 8:
-
-        case 9:
-
-        case 10:
-
-        case 11:
-
-        case 12:
-
-        case 13:
-
-        case 14:
-
-        case 15:
-
-        case 16:
-
-        case 17:
-            for (i = 0; i < payloadSize; i++)
-            {
-                BitstreamFlushBits(stream, 8);
-            }
-            break;
-        case 6:
-            /*      recovery point SEI              */
-            status = recovery_point(decvid, stream);
-            break;
-        case 7:
-            /*      decoded reference picture marking repetition SEI */
-            status = dec_ref_pic_marking_repetition(decvid, stream);
-            break;
-
-        case 18:
-            /*      motion-constrained slice group set SEI */
-            status = motion_constrained_slice_group_set(decvid, stream);
-            break;
-        default:
-            /*          reserved_sei_message */
-            for (i = 0; i < payloadSize; i++)
-            {
-                BitstreamFlushBits(stream, 8);
-            }
-            break;
-    }
-    BitstreamByteAlign(stream);
-    return status;
-}
-
-AVCDec_Status buffering_period(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    AVCSeqParamSet *currSPS;
-    uint seq_parameter_set_id;
-    uint temp;
-    uint i;
-    ue_v(stream, &seq_parameter_set_id);
-    if (seq_parameter_set_id > 31)
-    {
-        return AVCDEC_FAIL;
-    }
-
-//  decvid->common->seq_parameter_set_id = seq_parameter_set_id;
-
-    currSPS = decvid->seqParams[seq_parameter_set_id];
-    if (currSPS->vui_parameters.nal_hrd_parameters_present_flag)
-    {
-        for (i = 0; i <= currSPS->vui_parameters.nal_hrd_parameters.cpb_cnt_minus1; i++)
-        {
-            /* initial_cpb_removal_delay[i] */
-            BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-            /*initial _cpb_removal_delay_offset[i] */
-            BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-        }
-    }
-
-    if (currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
-    {
-        for (i = 0; i <= currSPS->vui_parameters.vcl_hrd_parameters.cpb_cnt_minus1; i++)
-        {
-            /* initial_cpb_removal_delay[i] */
-            BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-            /*initial _cpb_removal_delay_offset[i] */
-            BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-        }
-    }
-
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status pic_timing(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    AVCSeqParamSet *currSPS;
-    uint temp, NumClockTs = 0, time_offset_length = 24, full_timestamp_flag;
-    uint i;
-
-    currSPS = decvid->seqParams[decvid->common->seq_parameter_set_id];
-
-    if (currSPS->vui_parameters.nal_hrd_parameters_present_flag)
-    {
-        BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-        BitstreamReadBits(stream, currSPS->vui_parameters.nal_hrd_parameters.dpb_output_delay_length_minus1 + 1, &temp);
-        time_offset_length = currSPS->vui_parameters.nal_hrd_parameters.time_offset_length;
-    }
-    else if (currSPS->vui_parameters.vcl_hrd_parameters_present_flag)
-    {
-        BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1, &temp);
-        BitstreamReadBits(stream, currSPS->vui_parameters.vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1, &temp);
-        time_offset_length = currSPS->vui_parameters.vcl_hrd_parameters.time_offset_length;
-    }
-
-    if (currSPS->vui_parameters.pic_struct_present_flag)
-    {
-        /* pic_struct */
-        BitstreamReadBits(stream, 4, &temp);
-
-        switch (temp)
-        {
-            case 0:
-            case 1:
-            case 2:
-                NumClockTs = 1;
-                break;
-            case 3:
-            case 4:
-            case 7:
-                NumClockTs = 2;
-                break;
-            case 5:
-            case 6:
-            case 8:
-                NumClockTs = 3;
-                break;
-            default:
-                NumClockTs = 0;
-                break;
-        }
-
-        for (i = 0; i < NumClockTs; i++)
-        {
-            /* clock_timestamp_flag[i] */
-            BitstreamRead1Bit(stream, &temp);
-            if (temp)
-            {
-                /* ct_type */
-                BitstreamReadBits(stream, 2, &temp);
-                /* nuit_field_based_flag */
-                BitstreamRead1Bit(stream, &temp);
-                /* counting_type        */
-                BitstreamReadBits(stream, 5, &temp);
-                /* full_timestamp_flag */
-                BitstreamRead1Bit(stream, &temp);
-                full_timestamp_flag = temp;
-                /* discontinuity_flag */
-                BitstreamRead1Bit(stream, &temp);
-                /* cnt_dropped_flag */
-                BitstreamRead1Bit(stream, &temp);
-                /* n_frames           */
-                BitstreamReadBits(stream, 8, &temp);
-
-
-                if (full_timestamp_flag)
-                {
-                    /* seconds_value */
-                    BitstreamReadBits(stream, 6, &temp);
-                    /* minutes_value */
-                    BitstreamReadBits(stream, 6, &temp);
-                    /* hours_value */
-                    BitstreamReadBits(stream, 5, &temp);
-                }
-                else
-                {
-                    /* seconds_flag  */
-                    BitstreamRead1Bit(stream, &temp);
-                    if (temp)
-                    {
-                        /* seconds_value */
-                        BitstreamReadBits(stream, 6, &temp);
-                        /* minutes_flag  */
-                        BitstreamRead1Bit(stream, &temp);
-                        if (temp)
-                        {
-                            /* minutes_value */
-                            BitstreamReadBits(stream, 6, &temp);
-
-                            /* hourss_flag  */
-                            BitstreamRead1Bit(stream, &temp);
-
-                            if (temp)
-                            {
-                                /* hours_value */
-                                BitstreamReadBits(stream, 5, &temp);
-                            }
-
-                        }
-                    }
-                }
-
-                if (time_offset_length)
-                {
-                    /* time_offset */
-                    BitstreamReadBits(stream, time_offset_length, &temp);
-                }
-                else
-                {
-                    /* time_offset */
-                    temp = 0;
-                }
-            }
-        }
-    }
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status recovery_point(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    OSCL_UNUSED_ARG(decvid);
-    uint temp;
-    /* recover_frame_cnt */
-    ue_v(stream, &temp);
-    /* exact_match_flag */
-    BitstreamRead1Bit(stream, &temp);
-    /* broken_link_flag */
-    BitstreamRead1Bit(stream, &temp);
-    /* changing slic_group_idc */
-    BitstreamReadBits(stream, 2, &temp);
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status dec_ref_pic_marking_repetition(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    AVCSeqParamSet *currSPS;
-    uint temp;
-    currSPS = decvid->seqParams[decvid->common->seq_parameter_set_id];
-    /* original_idr_flag */
-    BitstreamRead1Bit(stream, &temp);
-    /* original_frame_num */
-    ue_v(stream, &temp);
-    if (currSPS->frame_mbs_only_flag == 0)
-    {
-        /* original_field_pic_flag */
-        BitstreamRead1Bit(stream, &temp);
-        if (temp)
-        {
-            /* original_bottom_field_flag */
-            BitstreamRead1Bit(stream, &temp);
-        }
-    }
-
-    /*  dec_ref_pic_marking(video,stream,sliceHdr); */
-
-
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status motion_constrained_slice_group_set(AVCDecObject *decvid, AVCDecBitstream *stream)
-{
-    OSCL_UNUSED_ARG(decvid);
-    uint temp, i, numBits;
-    /* num_slice_groups_in_set_minus1 */
-    ue_v(stream, &temp);
-
-    numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
-    i = temp;
-    while (i > 0)
-    {
-        numBits++;
-        i >>= 1;
-    }
-    for (i = 0; i <= temp; i++)
-    {
-        /* slice_group_id */
-        BitstreamReadBits(stream, numBits, &temp);
-    }
-    /* exact_sample_value_match_flag */
-    BitstreamRead1Bit(stream, &temp);
-    /* pan_scan_rect_flag */
-    BitstreamRead1Bit(stream, &temp);
-    if (temp)
-    {
-        /* pan_scan_rect_id */
-        ue_v(stream, &temp);
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
diff --git a/media/libstagefright/codecs/avc/dec/src/itrans.cpp b/media/libstagefright/codecs/avc/dec/src/itrans.cpp
deleted file mode 100644
index 02c550d..0000000
--- a/media/libstagefright/codecs/avc/dec/src/itrans.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avclib_common.h"
-
-/* input are in the first 16 elements of block,
-   output must be in the location specified in Figure 8-6. */
-/* subclause 8.5.6 */
-void Intra16DCTrans(int16 *block, int Qq, int Rq)
-{
-    int m0, m1, m2, m3;
-    int j, offset;
-    int16 *inout;
-    int scale = dequant_coefres[Rq][0];
-
-    inout = block;
-    for (j = 0; j < 4; j++)
-    {
-        m0 = inout[0] + inout[4];
-        m1 = inout[0] - inout[4];
-        m2 = inout[8] + inout[12];
-        m3 = inout[8] - inout[12];
-
-
-        inout[0] = m0 + m2;
-        inout[4] = m0 - m2;
-        inout[8] = m1 - m3;
-        inout[12] = m1 + m3;
-        inout += 64;
-    }
-
-    inout = block;
-
-    if (Qq >= 2)  /* this way should be faster than JM */
-    {           /* they use (((m4*scale)<<(QPy/6))+2)>>2 for both cases. */
-        Qq -= 2;
-        for (j = 0; j < 4; j++)
-        {
-            m0 = inout[0] + inout[64];
-            m1 = inout[0] - inout[64];
-            m2 = inout[128] + inout[192];
-            m3 = inout[128] - inout[192];
-
-            inout[0] = ((m0 + m2) * scale) << Qq;
-            inout[64] = ((m0 - m2) * scale) << Qq;
-            inout[128] = ((m1 - m3) * scale) << Qq;
-            inout[192] = ((m1 + m3) * scale) << Qq;
-            inout += 4;
-        }
-    }
-    else
-    {
-        Qq = 2 - Qq;
-        offset = 1 << (Qq - 1);
-
-        for (j = 0; j < 4; j++)
-        {
-            m0 = inout[0] + inout[64];
-            m1 = inout[0] - inout[64];
-            m2 = inout[128] + inout[192];
-            m3 = inout[128] - inout[192];
-
-            inout[0] = (((m0 + m2) * scale + offset) >> Qq);
-            inout[64] = (((m0 - m2) * scale + offset) >> Qq);
-            inout[128] = (((m1 - m3) * scale + offset) >> Qq);
-            inout[192] = (((m1 + m3) * scale + offset) >> Qq);
-            inout += 4;
-        }
-    }
-
-    return ;
-}
-
-/* see subclase 8.5.8 */
-void itrans(int16 *block, uint8 *pred, uint8 *cur, int width)
-{
-    int e0, e1, e2, e3; /* note, at every step of the calculation, these values */
-    /* shall never exceed 16bit sign value, but we don't check */
-    int i;           /* to save the cycles. */
-    int16 *inout;
-
-    inout = block;
-
-    for (i = 4; i > 0; i--)
-    {
-        e0 = inout[0] + inout[2];
-        e1 = inout[0] - inout[2];
-        e2 = (inout[1] >> 1) - inout[3];
-        e3 = inout[1] + (inout[3] >> 1);
-
-        inout[0] = e0 + e3;
-        inout[1] = e1 + e2;
-        inout[2] = e1 - e2;
-        inout[3] = e0 - e3;
-
-        inout += 16;
-    }
-
-    for (i = 4; i > 0; i--)
-    {
-        e0 = block[0] + block[32];
-        e1 = block[0] - block[32];
-        e2 = (block[16] >> 1) - block[48];
-        e3 = block[16] + (block[48] >> 1);
-
-        e0 += e3;
-        e3 = (e0 - (e3 << 1)); /* e0-e3 */
-        e1 += e2;
-        e2 = (e1 - (e2 << 1)); /* e1-e2 */
-        e0 += 32;
-        e1 += 32;
-        e2 += 32;
-        e3 += 32;
-#ifdef USE_PRED_BLOCK
-        e0 = pred[0] + (e0 >> 6);
-        if ((uint)e0 > 0xFF)   e0 = 0xFF & (~(e0 >> 31));  /* clip */
-        e1 = pred[20] + (e1 >> 6);
-        if ((uint)e1 > 0xFF)   e1 = 0xFF & (~(e1 >> 31));  /* clip */
-        e2 = pred[40] + (e2 >> 6);
-        if ((uint)e2 > 0xFF)   e2 = 0xFF & (~(e2 >> 31));  /* clip */
-        e3 = pred[60] + (e3 >> 6);
-        if ((uint)e3 > 0xFF)   e3 = 0xFF & (~(e3 >> 31));  /* clip */
-        *cur = e0;
-        *(cur += width) = e1;
-        *(cur += width) = e2;
-        cur[width] = e3;
-        cur -= (width << 1);
-        cur++;
-        pred++;
-#else
-        OSCL_UNUSED_ARG(pred);
-
-        e0 = *cur + (e0 >> 6);
-        if ((uint)e0 > 0xFF)   e0 = 0xFF & (~(e0 >> 31));  /* clip */
-        *cur = e0;
-        e1 = *(cur += width) + (e1 >> 6);
-        if ((uint)e1 > 0xFF)   e1 = 0xFF & (~(e1 >> 31));  /* clip */
-        *cur = e1;
-        e2 = *(cur += width) + (e2 >> 6);
-        if ((uint)e2 > 0xFF)   e2 = 0xFF & (~(e2 >> 31));  /* clip */
-        *cur = e2;
-        e3 = cur[width] + (e3 >> 6);
-        if ((uint)e3 > 0xFF)   e3 = 0xFF & (~(e3 >> 31));  /* clip */
-        cur[width] = e3;
-        cur -= (width << 1);
-        cur++;
-#endif
-        block++;
-    }
-
-    return ;
-}
-
-/* see subclase 8.5.8 */
-void ictrans(int16 *block, uint8 *pred, uint8 *cur, int width)
-{
-    int e0, e1, e2, e3; /* note, at every step of the calculation, these values */
-    /* shall never exceed 16bit sign value, but we don't check */
-    int i;           /* to save the cycles. */
-    int16 *inout;
-
-    inout = block;
-
-    for (i = 4; i > 0; i--)
-    {
-        e0 = inout[0] + inout[2];
-        e1 = inout[0] - inout[2];
-        e2 = (inout[1] >> 1) - inout[3];
-        e3 = inout[1] + (inout[3] >> 1);
-
-        inout[0] = e0 + e3;
-        inout[1] = e1 + e2;
-        inout[2] = e1 - e2;
-        inout[3] = e0 - e3;
-
-        inout += 16;
-    }
-
-    for (i = 4; i > 0; i--)
-    {
-        e0 = block[0] + block[32];
-        e1 = block[0] - block[32];
-        e2 = (block[16] >> 1) - block[48];
-        e3 = block[16] + (block[48] >> 1);
-
-        e0 += e3;
-        e3 = (e0 - (e3 << 1)); /* e0-e3 */
-        e1 += e2;
-        e2 = (e1 - (e2 << 1)); /* e1-e2 */
-        e0 += 32;
-        e1 += 32;
-        e2 += 32;
-        e3 += 32;
-#ifdef USE_PRED_BLOCK
-        e0 = pred[0] + (e0 >> 6);
-        if ((uint)e0 > 0xFF)   e0 = 0xFF & (~(e0 >> 31));  /* clip */
-        e1 = pred[12] + (e1 >> 6);
-        if ((uint)e1 > 0xFF)   e1 = 0xFF & (~(e1 >> 31));  /* clip */
-        e2 = pred[24] + (e2 >> 6);
-        if ((uint)e2 > 0xFF)   e2 = 0xFF & (~(e2 >> 31));  /* clip */
-        e3 = pred[36] + (e3 >> 6);
-        if ((uint)e3 > 0xFF)   e3 = 0xFF & (~(e3 >> 31));  /* clip */
-        *cur = e0;
-        *(cur += width) = e1;
-        *(cur += width) = e2;
-        cur[width] = e3;
-        cur -= (width << 1);
-        cur++;
-        pred++;
-#else
-        OSCL_UNUSED_ARG(pred);
-
-        e0 = *cur + (e0 >> 6);
-        if ((uint)e0 > 0xFF)   e0 = 0xFF & (~(e0 >> 31));  /* clip */
-        *cur = e0;
-        e1 = *(cur += width) + (e1 >> 6);
-        if ((uint)e1 > 0xFF)   e1 = 0xFF & (~(e1 >> 31));  /* clip */
-        *cur = e1;
-        e2 = *(cur += width) + (e2 >> 6);
-        if ((uint)e2 > 0xFF)   e2 = 0xFF & (~(e2 >> 31));  /* clip */
-        *cur = e2;
-        e3 = cur[width] + (e3 >> 6);
-        if ((uint)e3 > 0xFF)   e3 = 0xFF & (~(e3 >> 31));  /* clip */
-        cur[width] = e3;
-        cur -= (width << 1);
-        cur++;
-#endif
-        block++;
-    }
-
-    return ;
-}
-
-/* see subclause 8.5.7 */
-void ChromaDCTrans(int16 *block, int Qq, int Rq)
-{
-    int c00, c01, c10, c11;
-    int f0, f1, f2, f3;
-    int scale = dequant_coefres[Rq][0];
-
-    c00 = block[0] + block[4];
-    c01 = block[0] - block[4];
-    c10 = block[64] + block[68];
-    c11 = block[64] - block[68];
-
-    f0 = c00 + c10;
-    f1 = c01 + c11;
-    f2 = c00 - c10;
-    f3 = c01 - c11;
-
-    if (Qq >= 1)
-    {
-        Qq -= 1;
-        block[0] = (f0 * scale) << Qq;
-        block[4] = (f1 * scale) << Qq;
-        block[64] = (f2 * scale) << Qq;
-        block[68] = (f3 * scale) << Qq;
-    }
-    else
-    {
-        block[0] = (f0 * scale) >> 1;
-        block[4] = (f1 * scale) >> 1;
-        block[64] = (f2 * scale) >> 1;
-        block[68] = (f3 * scale) >> 1;
-    }
-
-    return ;
-}
-
-
-void copy_block(uint8 *pred, uint8 *cur, int width, int pred_pitch)
-{
-    uint32 temp;
-
-    temp = *((uint32*)pred);
-    pred += pred_pitch;
-    *((uint32*)cur) = temp;
-    cur += width;
-    temp = *((uint32*)pred);
-    pred += pred_pitch;
-    *((uint32*)cur) = temp;
-    cur += width;
-    temp = *((uint32*)pred);
-    pred += pred_pitch;
-    *((uint32*)cur) = temp;
-    cur += width;
-    temp = *((uint32*)pred);
-    *((uint32*)cur) = temp;
-
-    return ;
-}
-
-
diff --git a/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp b/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp
deleted file mode 100644
index ba36c37..0000000
--- a/media/libstagefright/codecs/avc/dec/src/pred_inter.cpp
+++ /dev/null
@@ -1,2329 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avcdec_lib.h"
-
-
-#define CLIP_RESULT(x)      if((uint)x > 0xFF){ \
-                 x = 0xFF & (~(x>>31));}
-
-/* (blkwidth << 2) + (dy << 1) + dx */
-static void (*const ChromaMC_SIMD[8])(uint8 *, int , int , int , uint8 *, int, int , int) =
-{
-    &ChromaFullMC_SIMD,
-    &ChromaHorizontalMC_SIMD,
-    &ChromaVerticalMC_SIMD,
-    &ChromaDiagonalMC_SIMD,
-    &ChromaFullMC_SIMD,
-    &ChromaHorizontalMC2_SIMD,
-    &ChromaVerticalMC2_SIMD,
-    &ChromaDiagonalMC2_SIMD
-};
-/* Perform motion prediction and compensation with residue if exist. */
-void InterMBPrediction(AVCCommonObj *video)
-{
-    AVCMacroblock *currMB = video->currMB;
-    AVCPictureData *currPic = video->currPic;
-    int mbPartIdx, subMbPartIdx;
-    int ref_idx;
-    int offset_MbPart_indx = 0;
-    int16 *mv;
-    uint32 x_pos, y_pos;
-    uint8 *curL, *curCb, *curCr;
-    uint8 *ref_l, *ref_Cb, *ref_Cr;
-    uint8 *predBlock, *predCb, *predCr;
-    int block_x, block_y, offset_x, offset_y, offsetP, offset;
-    int x_position = (video->mb_x << 4);
-    int y_position = (video->mb_y << 4);
-    int MbHeight, MbWidth, mbPartIdx_X, mbPartIdx_Y, offset_indx;
-    int picWidth = currPic->pitch;
-    int picHeight = currPic->height;
-    int16 *dataBlock;
-    uint32 cbp4x4;
-    uint32 tmp_word;
-
-    tmp_word = y_position * picWidth;
-    curL = currPic->Sl + tmp_word + x_position;
-    offset = (tmp_word >> 2) + (x_position >> 1);
-    curCb = currPic->Scb + offset;
-    curCr = currPic->Scr + offset;
-
-#ifdef USE_PRED_BLOCK
-    predBlock = video->pred + 84;
-    predCb = video->pred + 452;
-    predCr = video->pred + 596;
-#else
-    predBlock = curL;
-    predCb = curCb;
-    predCr = curCr;
-#endif
-
-    GetMotionVectorPredictor(video, false);
-
-    for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
-    {
-        MbHeight = currMB->SubMbPartHeight[mbPartIdx];
-        MbWidth = currMB->SubMbPartWidth[mbPartIdx];
-        mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1);
-        mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) >> 1;
-        ref_idx = currMB->ref_idx_L0[(mbPartIdx_Y << 1) + mbPartIdx_X];
-        offset_indx = 0;
-
-        ref_l = video->RefPicList0[ref_idx]->Sl;
-        ref_Cb = video->RefPicList0[ref_idx]->Scb;
-        ref_Cr = video->RefPicList0[ref_idx]->Scr;
-
-        for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
-        {
-            block_x = (mbPartIdx_X << 1) + ((subMbPartIdx + offset_indx) & 1);  // check this
-            block_y = (mbPartIdx_Y << 1) + (((subMbPartIdx + offset_indx) >> 1) & 1);
-            mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
-            offset_x = x_position + (block_x << 2);
-            offset_y = y_position + (block_y << 2);
-            x_pos = (offset_x << 2) + *mv++;   /*quarter pel */
-            y_pos = (offset_y << 2) + *mv;   /*quarter pel */
-
-            //offset = offset_y * currPic->width;
-            //offsetC = (offset >> 2) + (offset_x >> 1);
-#ifdef USE_PRED_BLOCK
-            offsetP = (block_y * 80) + (block_x << 2);
-            LumaMotionComp(ref_l, picWidth, picHeight, x_pos, y_pos,
-                           /*comp_Sl + offset + offset_x,*/
-                           predBlock + offsetP, 20, MbWidth, MbHeight);
-#else
-            offsetP = (block_y << 2) * picWidth + (block_x << 2);
-            LumaMotionComp(ref_l, picWidth, picHeight, x_pos, y_pos,
-                           /*comp_Sl + offset + offset_x,*/
-                           predBlock + offsetP, picWidth, MbWidth, MbHeight);
-#endif
-
-#ifdef USE_PRED_BLOCK
-            offsetP = (block_y * 24) + (block_x << 1);
-            ChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
-                             /*comp_Scb +  offsetC,*/
-                             predCb + offsetP, 12, MbWidth >> 1, MbHeight >> 1);
-            ChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
-                             /*comp_Scr +  offsetC,*/
-                             predCr + offsetP, 12, MbWidth >> 1, MbHeight >> 1);
-#else
-            offsetP = (block_y * picWidth) + (block_x << 1);
-            ChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
-                             /*comp_Scb +  offsetC,*/
-                             predCb + offsetP, picWidth >> 1, MbWidth >> 1, MbHeight >> 1);
-            ChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
-                             /*comp_Scr +  offsetC,*/
-                             predCr + offsetP, picWidth >> 1, MbWidth >> 1, MbHeight >> 1);
-#endif
-
-            offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
-        }
-        offset_MbPart_indx = currMB->MbPartWidth >> 4;
-    }
-
-    /* used in decoder, used to be if(!encFlag)  */
-
-    /* transform in raster scan order */
-    dataBlock = video->block;
-    cbp4x4 = video->cbp4x4;
-    /* luma */
-    for (block_y = 4; block_y > 0; block_y--)
-    {
-        for (block_x = 4; block_x > 0; block_x--)
-        {
-#ifdef USE_PRED_BLOCK
-            if (cbp4x4&1)
-            {
-                itrans(dataBlock, predBlock, predBlock, 20);
-            }
-#else
-            if (cbp4x4&1)
-            {
-                itrans(dataBlock, curL, curL, picWidth);
-            }
-#endif
-            cbp4x4 >>= 1;
-            dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-            predBlock += 4;
-#else
-            curL += 4;
-#endif
-        }
-        dataBlock += 48;
-#ifdef USE_PRED_BLOCK
-        predBlock += 64;
-#else
-        curL += ((picWidth << 2) - 16);
-#endif
-    }
-
-    /* chroma */
-    picWidth = (picWidth >> 1);
-    for (block_y = 2; block_y > 0; block_y--)
-    {
-        for (block_x = 2; block_x > 0; block_x--)
-        {
-#ifdef USE_PRED_BLOCK
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, predCb, predCb, 12);
-            }
-#else
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, curCb, curCb, picWidth);
-            }
-#endif
-            cbp4x4 >>= 1;
-            dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-            predCb += 4;
-#else
-            curCb += 4;
-#endif
-        }
-        for (block_x = 2; block_x > 0; block_x--)
-        {
-#ifdef USE_PRED_BLOCK
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, predCr, predCr, 12);
-            }
-#else
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, curCr, curCr, picWidth);
-            }
-#endif
-            cbp4x4 >>= 1;
-            dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-            predCr += 4;
-#else
-            curCr += 4;
-#endif
-        }
-        dataBlock += 48;
-#ifdef USE_PRED_BLOCK
-        predCb += 40;
-        predCr += 40;
-#else
-        curCb += ((picWidth << 2) - 8);
-        curCr += ((picWidth << 2) - 8);
-#endif
-    }
-
-#ifdef MB_BASED_DEBLOCK
-    SaveNeighborForIntraPred(video, offset);
-#endif
-
-    return ;
-}
-
-
-/* preform the actual  motion comp here */
-void LumaMotionComp(uint8 *ref, int picwidth, int picheight,
-                    int x_pos, int y_pos,
-                    uint8 *pred, int pred_pitch,
-                    int blkwidth, int blkheight)
-{
-    int dx, dy;
-    uint8 temp[24][24]; /* for padding, make the size multiple of 4 for packing */
-    int temp2[21][21]; /* for intermediate results */
-    uint8 *ref2;
-
-    dx = x_pos & 3;
-    dy = y_pos & 3;
-    x_pos = x_pos >> 2;  /* round it to full-pel resolution */
-    y_pos = y_pos >> 2;
-
-    /* perform actual motion compensation */
-    if (dx == 0 && dy == 0)
-    {  /* fullpel position *//* G */
-        if (x_pos >= 0 && x_pos + blkwidth <= picwidth && y_pos >= 0 && y_pos + blkheight <= picheight)
-        {
-            ref += y_pos * picwidth + x_pos;
-            FullPelMC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight);
-        }
-        else
-        {
-            CreatePad(ref, picwidth, picheight, x_pos, y_pos, &temp[0][0], blkwidth, blkheight);
-            FullPelMC(&temp[0][0], 24, pred, pred_pitch, blkwidth, blkheight);
-        }
-
-    }   /* other positions */
-    else  if (dy == 0)
-    { /* no vertical interpolation *//* a,b,c*/
-
-        if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos >= 0 && y_pos + blkheight <= picheight)
-        {
-            ref += y_pos * picwidth + x_pos;
-
-            HorzInterp1MC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight, dx);
-        }
-        else  /* need padding */
-        {
-            CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos, &temp[0][0], blkwidth + 5, blkheight);
-
-            HorzInterp1MC(&temp[0][2], 24, pred, pred_pitch, blkwidth, blkheight, dx);
-        }
-    }
-    else if (dx == 0)
-    { /*no horizontal interpolation *//* d,h,n */
-
-        if (x_pos >= 0 && x_pos + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
-        {
-            ref += y_pos * picwidth + x_pos;
-
-            VertInterp1MC(ref, picwidth, pred, pred_pitch, blkwidth, blkheight, dy);
-        }
-        else  /* need padding */
-        {
-            CreatePad(ref, picwidth, picheight, x_pos, y_pos - 2, &temp[0][0], blkwidth, blkheight + 5);
-
-            VertInterp1MC(&temp[2][0], 24, pred, pred_pitch, blkwidth, blkheight, dy);
-        }
-    }
-    else if (dy == 2)
-    {  /* horizontal cross *//* i, j, k */
-
-        if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
-        {
-            ref += y_pos * picwidth + x_pos - 2; /* move to the left 2 pixels */
-
-            VertInterp2MC(ref, picwidth, &temp2[0][0], 21, blkwidth + 5, blkheight);
-
-            HorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
-        }
-        else /* need padding */
-        {
-            CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5, blkheight + 5);
-
-            VertInterp2MC(&temp[2][0], 24, &temp2[0][0], 21, blkwidth + 5, blkheight);
-
-            HorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
-        }
-    }
-    else if (dx == 2)
-    { /* vertical cross */ /* f,q */
-
-        if (x_pos - 2 >= 0 && x_pos + 3 + blkwidth <= picwidth && y_pos - 2 >= 0 && y_pos + 3 + blkheight <= picheight)
-        {
-            ref += (y_pos - 2) * picwidth + x_pos; /* move to up 2 lines */
-
-            HorzInterp3MC(ref, picwidth, &temp2[0][0], 21, blkwidth, blkheight + 5);
-            VertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
-        }
-        else  /* need padding */
-        {
-            CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5, blkheight + 5);
-            HorzInterp3MC(&temp[0][2], 24, &temp2[0][0], 21, blkwidth, blkheight + 5);
-            VertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
-        }
-    }
-    else
-    { /* diagonal *//* e,g,p,r */
-
-        if (x_pos - 2 >= 0 && x_pos + 3 + (dx / 2) + blkwidth <= picwidth &&
-                y_pos - 2 >= 0 && y_pos + 3 + blkheight + (dy / 2) <= picheight)
-        {
-            ref2 = ref + (y_pos + (dy / 2)) * picwidth + x_pos;
-
-            ref += (y_pos * picwidth) + x_pos + (dx / 2);
-
-            DiagonalInterpMC(ref2, ref, picwidth, pred, pred_pitch, blkwidth, blkheight);
-        }
-        else  /* need padding */
-        {
-            CreatePad(ref, picwidth, picheight, x_pos - 2, y_pos - 2, &temp[0][0], blkwidth + 5 + (dx / 2), blkheight + 5 + (dy / 2));
-
-            ref2 = &temp[2 + (dy/2)][2];
-
-            ref = &temp[2][2 + (dx/2)];
-
-            DiagonalInterpMC(ref2, ref, 24, pred, pred_pitch, blkwidth, blkheight);
-        }
-    }
-
-    return ;
-}
-
-void CreateAlign(uint8 *ref, int picwidth, int y_pos,
-                 uint8 *out, int blkwidth, int blkheight)
-{
-    int i, j;
-    int offset, out_offset;
-    uint32 prev_pix, result, pix1, pix2, pix4;
-
-    out_offset = 24 - blkwidth;
-
-    //switch(x_pos&0x3){
-    switch (((uint32)ref)&0x3)
-    {
-        case 1:
-            ref += y_pos * picwidth;
-            offset =  picwidth - blkwidth - 3;
-            for (j = 0; j < blkheight; j++)
-            {
-                pix1 = *ref++;
-                pix2 = *((uint16*)ref);
-                ref += 2;
-                result = (pix2 << 8) | pix1;
-
-                for (i = 3; i < blkwidth; i += 4)
-                {
-                    pix4 = *((uint32*)ref);
-                    ref += 4;
-                    prev_pix = (pix4 << 24) & 0xFF000000; /* mask out byte belong to previous word */
-                    result |= prev_pix;
-                    *((uint32*)out) = result;  /* write 4 bytes */
-                    out += 4;
-                    result = pix4 >> 8; /* for the next loop */
-                }
-                ref += offset;
-                out += out_offset;
-            }
-            break;
-        case 2:
-            ref += y_pos * picwidth;
-            offset =  picwidth - blkwidth - 2;
-            for (j = 0; j < blkheight; j++)
-            {
-                result = *((uint16*)ref);
-                ref += 2;
-                for (i = 2; i < blkwidth; i += 4)
-                {
-                    pix4 = *((uint32*)ref);
-                    ref += 4;
-                    prev_pix = (pix4 << 16) & 0xFFFF0000; /* mask out byte belong to previous word */
-                    result |= prev_pix;
-                    *((uint32*)out) = result;  /* write 4 bytes */
-                    out += 4;
-                    result = pix4 >> 16; /* for the next loop */
-                }
-                ref += offset;
-                out += out_offset;
-            }
-            break;
-        case 3:
-            ref += y_pos * picwidth;
-            offset =  picwidth - blkwidth - 1;
-            for (j = 0; j < blkheight; j++)
-            {
-                result = *ref++;
-                for (i = 1; i < blkwidth; i += 4)
-                {
-                    pix4 = *((uint32*)ref);
-                    ref += 4;
-                    prev_pix = (pix4 << 8) & 0xFFFFFF00; /* mask out byte belong to previous word */
-                    result |= prev_pix;
-                    *((uint32*)out) = result;  /* write 4 bytes */
-                    out += 4;
-                    result = pix4 >> 24; /* for the next loop */
-                }
-                ref += offset;
-                out += out_offset;
-            }
-            break;
-    }
-}
-
-void CreatePad(uint8 *ref, int picwidth, int picheight, int x_pos, int y_pos,
-               uint8 *out, int blkwidth, int blkheight)
-{
-    int x_inc0, x_mid;
-    int y_inc, y_inc0, y_inc1, y_mid;
-    int i, j;
-    int offset;
-
-    if (x_pos < 0)
-    {
-        x_inc0 = 0;  /* increment for the first part */
-        x_mid = ((blkwidth + x_pos > 0) ? -x_pos : blkwidth);  /* stopping point */
-        x_pos = 0;
-    }
-    else if (x_pos + blkwidth > picwidth)
-    {
-        x_inc0 = 1;  /* increasing */
-        x_mid = ((picwidth > x_pos) ? picwidth - x_pos - 1 : 0);  /* clip negative to zero, encode fool proof! */
-    }
-    else    /* normal case */
-    {
-        x_inc0 = 1;
-        x_mid = blkwidth; /* just one run */
-    }
-
-
-    /* boundary for y_pos, taking the result from x_pos into account */
-    if (y_pos < 0)
-    {
-        y_inc0 = (x_inc0 ? - x_mid : -blkwidth + x_mid); /* offset depending on x_inc1 and x_inc0 */
-        y_inc1 = picwidth + y_inc0;
-        y_mid = ((blkheight + y_pos > 0) ? -y_pos : blkheight); /* clip to prevent memory corruption */
-        y_pos = 0;
-    }
-    else  if (y_pos + blkheight > picheight)
-    {
-        y_inc1 = (x_inc0 ? - x_mid : -blkwidth + x_mid); /* saturate */
-        y_inc0 = picwidth + y_inc1;                 /* increasing */
-        y_mid = ((picheight > y_pos) ? picheight - 1 - y_pos : 0);
-    }
-    else  /* normal case */
-    {
-        y_inc1 = (x_inc0 ? - x_mid : -blkwidth + x_mid);
-        y_inc0 = picwidth + y_inc1;
-        y_mid = blkheight;
-    }
-
-    /* clip y_pos and x_pos */
-    if (y_pos > picheight - 1) y_pos = picheight - 1;
-    if (x_pos > picwidth - 1) x_pos = picwidth - 1;
-
-    ref += y_pos * picwidth + x_pos;
-
-    y_inc = y_inc0;  /* start with top half */
-
-    offset = 24 - blkwidth; /* to use in offset out */
-    blkwidth -= x_mid; /* to use in the loop limit */
-
-    if (x_inc0 == 0)
-    {
-        for (j = 0; j < blkheight; j++)
-        {
-            if (j == y_mid)  /* put a check here to reduce the code size (for unrolling the loop) */
-            {
-                y_inc = y_inc1;  /* switch to lower half */
-            }
-            for (i = x_mid; i > 0; i--)   /* first or third quarter */
-            {
-                *out++ = *ref;
-            }
-            for (i = blkwidth; i > 0; i--)  /* second or fourth quarter */
-            {
-                *out++ = *ref++;
-            }
-            out += offset;
-            ref += y_inc;
-        }
-    }
-    else
-    {
-        for (j = 0; j < blkheight; j++)
-        {
-            if (j == y_mid)  /* put a check here to reduce the code size (for unrolling the loop) */
-            {
-                y_inc = y_inc1;  /* switch to lower half */
-            }
-            for (i = x_mid; i > 0; i--)   /* first or third quarter */
-            {
-                *out++ = *ref++;
-            }
-            for (i = blkwidth; i > 0; i--)  /* second or fourth quarter */
-            {
-                *out++ = *ref;
-            }
-            out += offset;
-            ref += y_inc;
-        }
-    }
-
-    return ;
-}
-
-void HorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dx)
-{
-    uint8 *p_ref;
-    uint32 *p_cur;
-    uint32 tmp, pkres;
-    int result, curr_offset, ref_offset;
-    int j;
-    int32 r0, r1, r2, r3, r4, r5;
-    int32 r13, r6;
-
-    p_cur = (uint32*)out; /* assume it's word aligned */
-    curr_offset = (outpitch - blkwidth) >> 2;
-    p_ref = in;
-    ref_offset = inpitch - blkwidth;
-
-    if (dx&1)
-    {
-        dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
-        p_ref -= 2;
-        r13 = 0;
-        for (j = blkheight; j > 0; j--)
-        {
-            tmp = (uint32)(p_ref + blkwidth);
-            r0 = p_ref[0];
-            r1 = p_ref[2];
-            r0 |= (r1 << 16);           /* 0,c,0,a */
-            r1 = p_ref[1];
-            r2 = p_ref[3];
-            r1 |= (r2 << 16);           /* 0,d,0,b */
-            while ((uint32)p_ref < tmp)
-            {
-                r2 = *(p_ref += 4); /* move pointer to e */
-                r3 = p_ref[2];
-                r2 |= (r3 << 16);           /* 0,g,0,e */
-                r3 = p_ref[1];
-                r4 = p_ref[3];
-                r3 |= (r4 << 16);           /* 0,h,0,f */
-
-                r4 = r0 + r3;       /* c+h, a+f */
-                r5 = r0 + r1;   /* c+d, a+b */
-                r6 = r2 + r3;   /* g+h, e+f */
-                r5 >>= 16;
-                r5 |= (r6 << 16);   /* e+f, c+d */
-                r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
-                r4 += 0x100010; /* +16, +16 */
-                r5 = r1 + r2;       /* d+g, b+e */
-                r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
-                r4 >>= 5;
-                r13 |= r4;      /* check clipping */
-
-                r5 = p_ref[dx+2];
-                r6 = p_ref[dx+4];
-                r5 |= (r6 << 16);
-                r4 += r5;
-                r4 += 0x10001;
-                r4 = (r4 >> 1) & 0xFF00FF;
-
-                r5 = p_ref[4];  /* i */
-                r6 = (r5 << 16);
-                r5 = r6 | (r2 >> 16);/* 0,i,0,g */
-                r5 += r1;       /* d+i, b+g */ /* r5 not free */
-                r1 >>= 16;
-                r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
-                r1 += r2;       /* f+g, d+e */
-                r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
-                r0 >>= 16;
-                r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
-                r0 += r3;       /* e+h, c+f */
-                r5 += 0x100010; /* 16,16 */
-                r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
-                r5 >>= 5;
-                r13 |= r5;      /* check clipping */
-
-                r0 = p_ref[dx+3];
-                r1 = p_ref[dx+5];
-                r0 |= (r1 << 16);
-                r5 += r0;
-                r5 += 0x10001;
-                r5 = (r5 >> 1) & 0xFF00FF;
-
-                r4 |= (r5 << 8);    /* pack them together */
-                *p_cur++ = r4;
-                r1 = r3;
-                r0 = r2;
-            }
-            p_cur += curr_offset; /* move to the next line */
-            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
-
-            if (r13&0xFF000700) /* need clipping */
-            {
-                /* move back to the beginning of the line */
-                p_ref -= (ref_offset + blkwidth);   /* input */
-                p_cur -= (outpitch >> 2);
-
-                tmp = (uint32)(p_ref + blkwidth);
-                for (; (uint32)p_ref < tmp;)
-                {
-
-                    r0 = *p_ref++;
-                    r1 = *p_ref++;
-                    r2 = *p_ref++;
-                    r3 = *p_ref++;
-                    r4 = *p_ref++;
-                    /* first pixel */
-                    r5 = *p_ref++;
-                    result = (r0 + r5);
-                    r0 = (r1 + r4);
-                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                    r0 = (r2 + r3);
-                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    /* 3/4 pel,  no need to clip */
-                    result = (result + p_ref[dx] + 1);
-                    pkres = (result >> 1) ;
-                    /* second pixel */
-                    r0 = *p_ref++;
-                    result = (r1 + r0);
-                    r1 = (r2 + r5);
-                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                    r1 = (r3 + r4);
-                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    /* 3/4 pel,  no need to clip */
-                    result = (result + p_ref[dx] + 1);
-                    result = (result >> 1);
-                    pkres  |= (result << 8);
-                    /* third pixel */
-                    r1 = *p_ref++;
-                    result = (r2 + r1);
-                    r2 = (r3 + r0);
-                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                    r2 = (r4 + r5);
-                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    /* 3/4 pel,  no need to clip */
-                    result = (result + p_ref[dx] + 1);
-                    result = (result >> 1);
-                    pkres  |= (result << 16);
-                    /* fourth pixel */
-                    r2 = *p_ref++;
-                    result = (r3 + r2);
-                    r3 = (r4 + r1);
-                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                    r3 = (r5 + r0);
-                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    /* 3/4 pel,  no need to clip */
-                    result = (result + p_ref[dx] + 1);
-                    result = (result >> 1);
-                    pkres  |= (result << 24);
-                    *p_cur++ = pkres; /* write 4 pixels */
-                    p_ref -= 5;  /* offset back to the middle of filter */
-                }
-                p_cur += curr_offset;  /* move to the next line */
-                p_ref += ref_offset;    /* move to the next line */
-            }
-        }
-    }
-    else
-    {
-        p_ref -= 2;
-        r13 = 0;
-        for (j = blkheight; j > 0; j--)
-        {
-            tmp = (uint32)(p_ref + blkwidth);
-            r0 = p_ref[0];
-            r1 = p_ref[2];
-            r0 |= (r1 << 16);           /* 0,c,0,a */
-            r1 = p_ref[1];
-            r2 = p_ref[3];
-            r1 |= (r2 << 16);           /* 0,d,0,b */
-            while ((uint32)p_ref < tmp)
-            {
-                r2 = *(p_ref += 4); /* move pointer to e */
-                r3 = p_ref[2];
-                r2 |= (r3 << 16);           /* 0,g,0,e */
-                r3 = p_ref[1];
-                r4 = p_ref[3];
-                r3 |= (r4 << 16);           /* 0,h,0,f */
-
-                r4 = r0 + r3;       /* c+h, a+f */
-                r5 = r0 + r1;   /* c+d, a+b */
-                r6 = r2 + r3;   /* g+h, e+f */
-                r5 >>= 16;
-                r5 |= (r6 << 16);   /* e+f, c+d */
-                r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
-                r4 += 0x100010; /* +16, +16 */
-                r5 = r1 + r2;       /* d+g, b+e */
-                r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
-                r4 >>= 5;
-                r13 |= r4;      /* check clipping */
-                r4 &= 0xFF00FF; /* mask */
-
-                r5 = p_ref[4];  /* i */
-                r6 = (r5 << 16);
-                r5 = r6 | (r2 >> 16);/* 0,i,0,g */
-                r5 += r1;       /* d+i, b+g */ /* r5 not free */
-                r1 >>= 16;
-                r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
-                r1 += r2;       /* f+g, d+e */
-                r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
-                r0 >>= 16;
-                r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
-                r0 += r3;       /* e+h, c+f */
-                r5 += 0x100010; /* 16,16 */
-                r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
-                r5 >>= 5;
-                r13 |= r5;      /* check clipping */
-                r5 &= 0xFF00FF; /* mask */
-
-                r4 |= (r5 << 8);    /* pack them together */
-                *p_cur++ = r4;
-                r1 = r3;
-                r0 = r2;
-            }
-            p_cur += curr_offset; /* move to the next line */
-            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
-
-            if (r13&0xFF000700) /* need clipping */
-            {
-                /* move back to the beginning of the line */
-                p_ref -= (ref_offset + blkwidth);   /* input */
-                p_cur -= (outpitch >> 2);
-
-                tmp = (uint32)(p_ref + blkwidth);
-                for (; (uint32)p_ref < tmp;)
-                {
-
-                    r0 = *p_ref++;
-                    r1 = *p_ref++;
-                    r2 = *p_ref++;
-                    r3 = *p_ref++;
-                    r4 = *p_ref++;
-                    /* first pixel */
-                    r5 = *p_ref++;
-                    result = (r0 + r5);
-                    r0 = (r1 + r4);
-                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                    r0 = (r2 + r3);
-                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    pkres  = result;
-                    /* second pixel */
-                    r0 = *p_ref++;
-                    result = (r1 + r0);
-                    r1 = (r2 + r5);
-                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                    r1 = (r3 + r4);
-                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    pkres  |= (result << 8);
-                    /* third pixel */
-                    r1 = *p_ref++;
-                    result = (r2 + r1);
-                    r2 = (r3 + r0);
-                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                    r2 = (r4 + r5);
-                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    pkres  |= (result << 16);
-                    /* fourth pixel */
-                    r2 = *p_ref++;
-                    result = (r3 + r2);
-                    r3 = (r4 + r1);
-                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                    r3 = (r5 + r0);
-                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    pkres  |= (result << 24);
-                    *p_cur++ = pkres;   /* write 4 pixels */
-                    p_ref -= 5;
-                }
-                p_cur += curr_offset; /* move to the next line */
-                p_ref += ref_offset;
-            }
-        }
-    }
-
-    return ;
-}
-
-void HorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dx)
-{
-    int *p_ref;
-    uint32 *p_cur;
-    uint32 tmp, pkres;
-    int result, result2, curr_offset, ref_offset;
-    int j, r0, r1, r2, r3, r4, r5;
-
-    p_cur = (uint32*)out; /* assume it's word aligned */
-    curr_offset = (outpitch - blkwidth) >> 2;
-    p_ref = in;
-    ref_offset = inpitch - blkwidth;
-
-    if (dx&1)
-    {
-        dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
-
-        for (j = blkheight; j > 0 ; j--)
-        {
-            tmp = (uint32)(p_ref + blkwidth);
-            for (; (uint32)p_ref < tmp;)
-            {
-
-                r0 = p_ref[-2];
-                r1 = p_ref[-1];
-                r2 = *p_ref++;
-                r3 = *p_ref++;
-                r4 = *p_ref++;
-                /* first pixel */
-                r5 = *p_ref++;
-                result = (r0 + r5);
-                r0 = (r1 + r4);
-                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                r0 = (r2 + r3);
-                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dx] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                pkres = (result >> 1);
-                /* second pixel */
-                r0 = *p_ref++;
-                result = (r1 + r0);
-                r1 = (r2 + r5);
-                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                r1 = (r3 + r4);
-                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dx] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                pkres  |= (result << 8);
-                /* third pixel */
-                r1 = *p_ref++;
-                result = (r2 + r1);
-                r2 = (r3 + r0);
-                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                r2 = (r4 + r5);
-                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dx] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                pkres  |= (result << 16);
-                /* fourth pixel */
-                r2 = *p_ref++;
-                result = (r3 + r2);
-                r3 = (r4 + r1);
-                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                r3 = (r5 + r0);
-                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dx] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                pkres  |= (result << 24);
-                *p_cur++ = pkres; /* write 4 pixels */
-                p_ref -= 3;  /* offset back to the middle of filter */
-            }
-            p_cur += curr_offset;  /* move to the next line */
-            p_ref += ref_offset;    /* move to the next line */
-        }
-    }
-    else
-    {
-        for (j = blkheight; j > 0 ; j--)
-        {
-            tmp = (uint32)(p_ref + blkwidth);
-            for (; (uint32)p_ref < tmp;)
-            {
-
-                r0 = p_ref[-2];
-                r1 = p_ref[-1];
-                r2 = *p_ref++;
-                r3 = *p_ref++;
-                r4 = *p_ref++;
-                /* first pixel */
-                r5 = *p_ref++;
-                result = (r0 + r5);
-                r0 = (r1 + r4);
-                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                r0 = (r2 + r3);
-                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                pkres  = result;
-                /* second pixel */
-                r0 = *p_ref++;
-                result = (r1 + r0);
-                r1 = (r2 + r5);
-                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                r1 = (r3 + r4);
-                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                pkres  |= (result << 8);
-                /* third pixel */
-                r1 = *p_ref++;
-                result = (r2 + r1);
-                r2 = (r3 + r0);
-                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                r2 = (r4 + r5);
-                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                pkres  |= (result << 16);
-                /* fourth pixel */
-                r2 = *p_ref++;
-                result = (r3 + r2);
-                r3 = (r4 + r1);
-                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                r3 = (r5 + r0);
-                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                pkres  |= (result << 24);
-                *p_cur++ = pkres; /* write 4 pixels */
-                p_ref -= 3;  /* offset back to the middle of filter */
-            }
-            p_cur += curr_offset;  /* move to the next line */
-            p_ref += ref_offset;    /* move to the next line */
-        }
-    }
-
-    return ;
-}
-
-void HorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
-                   int blkwidth, int blkheight)
-{
-    uint8 *p_ref;
-    int   *p_cur;
-    uint32 tmp;
-    int result, curr_offset, ref_offset;
-    int j, r0, r1, r2, r3, r4, r5;
-
-    p_cur = out;
-    curr_offset = (outpitch - blkwidth);
-    p_ref = in;
-    ref_offset = inpitch - blkwidth;
-
-    for (j = blkheight; j > 0 ; j--)
-    {
-        tmp = (uint32)(p_ref + blkwidth);
-        for (; (uint32)p_ref < tmp;)
-        {
-
-            r0 = p_ref[-2];
-            r1 = p_ref[-1];
-            r2 = *p_ref++;
-            r3 = *p_ref++;
-            r4 = *p_ref++;
-            /* first pixel */
-            r5 = *p_ref++;
-            result = (r0 + r5);
-            r0 = (r1 + r4);
-            result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-            r0 = (r2 + r3);
-            result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-            *p_cur++ = result;
-            /* second pixel */
-            r0 = *p_ref++;
-            result = (r1 + r0);
-            r1 = (r2 + r5);
-            result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-            r1 = (r3 + r4);
-            result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-            *p_cur++ = result;
-            /* third pixel */
-            r1 = *p_ref++;
-            result = (r2 + r1);
-            r2 = (r3 + r0);
-            result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-            r2 = (r4 + r5);
-            result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-            *p_cur++ = result;
-            /* fourth pixel */
-            r2 = *p_ref++;
-            result = (r3 + r2);
-            r3 = (r4 + r1);
-            result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-            r3 = (r5 + r0);
-            result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-            *p_cur++ = result;
-            p_ref -= 3; /* move back to the middle of the filter */
-        }
-        p_cur += curr_offset; /* move to the next line */
-        p_ref += ref_offset;
-    }
-
-    return ;
-}
-void VertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dy)
-{
-    uint8 *p_cur, *p_ref;
-    uint32 tmp;
-    int result, curr_offset, ref_offset;
-    int j, i;
-    int32 r0, r1, r2, r3, r4, r5, r6, r7, r8, r13;
-    uint8  tmp_in[24][24];
-
-    /* not word-aligned */
-    if (((uint32)in)&0x3)
-    {
-        CreateAlign(in, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
-        in = &tmp_in[2][0];
-        inpitch = 24;
-    }
-    p_cur = out;
-    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
-    ref_offset = blkheight * inpitch; /* for limit */
-
-    curr_offset += 3;
-
-    if (dy&1)
-    {
-        dy = (dy >> 1) ? 0 : -inpitch;
-
-        for (j = 0; j < blkwidth; j += 4, in += 4)
-        {
-            r13 = 0;
-            p_ref = in;
-            p_cur -= outpitch;  /* compensate for the first offset */
-            tmp = (uint32)(p_ref + ref_offset); /* limit */
-            while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
-            {
-                r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
-                p_ref += inpitch;
-                r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
-                r0 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-
-                r0 += r1;
-                r6 += r7;
-
-                r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
-                r8 = (r2 >> 8) & 0xFF00FF;
-                r2 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-                r1 += r2;
-
-                r7 += r8;
-
-                r0 += 20 * r1;
-                r6 += 20 * r7;
-                r0 += 0x100010;
-                r6 += 0x100010;
-
-                r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
-                r8 = (r2 >> 8) & 0xFF00FF;
-                r2 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-                r1 += r2;
-
-                r7 += r8;
-
-                r0 -= 5 * r1;
-                r6 -= 5 * r7;
-
-                r0 >>= 5;
-                r6 >>= 5;
-                /* clip */
-                r13 |= r6;
-                r13 |= r0;
-                //CLIPPACK(r6,result)
-
-                r1 = *((uint32*)(p_ref + dy));
-                r2 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-                r0 += r1;
-                r6 += r2;
-                r0 += 0x10001;
-                r6 += 0x10001;
-                r0 = (r0 >> 1) & 0xFF00FF;
-                r6 = (r6 >> 1) & 0xFF00FF;
-
-                r0 |= (r6 << 8);  /* pack it back */
-                *((uint32*)(p_cur += outpitch)) = r0;
-            }
-            p_cur += curr_offset; /* offset to the next pixel */
-            if (r13 & 0xFF000700) /* this column need clipping */
-            {
-                p_cur -= 4;
-                for (i = 0; i < 4; i++)
-                {
-                    p_ref = in + i;
-                    p_cur -= outpitch;  /* compensate for the first offset */
-
-                    tmp = (uint32)(p_ref + ref_offset); /* limit */
-                    while ((uint32)p_ref < tmp)
-                    {                           /* loop un-rolled */
-                        r0 = *(p_ref - (inpitch << 1));
-                        r1 = *(p_ref - inpitch);
-                        r2 = *p_ref;
-                        r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-                        r4 = *(p_ref += inpitch);
-                        /* first pixel */
-                        r5 = *(p_ref += inpitch);
-                        result = (r0 + r5);
-                        r0 = (r1 + r4);
-                        result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                        r0 = (r2 + r3);
-                        result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        /* 3/4 pel,  no need to clip */
-                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
-                        result = (result >> 1);
-                        *(p_cur += outpitch) = result;
-                        /* second pixel */
-                        r0 = *(p_ref += inpitch);
-                        result = (r1 + r0);
-                        r1 = (r2 + r5);
-                        result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                        r1 = (r3 + r4);
-                        result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        /* 3/4 pel,  no need to clip */
-                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
-                        result = (result >> 1);
-                        *(p_cur += outpitch) = result;
-                        /* third pixel */
-                        r1 = *(p_ref += inpitch);
-                        result = (r2 + r1);
-                        r2 = (r3 + r0);
-                        result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                        r2 = (r4 + r5);
-                        result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        /* 3/4 pel,  no need to clip */
-                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
-                        result = (result >> 1);
-                        *(p_cur += outpitch) = result;
-                        /* fourth pixel */
-                        r2 = *(p_ref += inpitch);
-                        result = (r3 + r2);
-                        r3 = (r4 + r1);
-                        result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                        r3 = (r5 + r0);
-                        result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        /* 3/4 pel,  no need to clip */
-                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
-                        result = (result >> 1);
-                        *(p_cur += outpitch) = result;
-                        p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-                    }
-                    p_cur += (curr_offset - 3);
-                }
-            }
-        }
-    }
-    else
-    {
-        for (j = 0; j < blkwidth; j += 4, in += 4)
-        {
-            r13 = 0;
-            p_ref = in;
-            p_cur -= outpitch;  /* compensate for the first offset */
-            tmp = (uint32)(p_ref + ref_offset); /* limit */
-            while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
-            {
-                r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
-                p_ref += inpitch;
-                r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
-                r0 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-
-                r0 += r1;
-                r6 += r7;
-
-                r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
-                r8 = (r2 >> 8) & 0xFF00FF;
-                r2 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-                r1 += r2;
-
-                r7 += r8;
-
-                r0 += 20 * r1;
-                r6 += 20 * r7;
-                r0 += 0x100010;
-                r6 += 0x100010;
-
-                r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
-                r8 = (r2 >> 8) & 0xFF00FF;
-                r2 &= 0xFF00FF;
-
-                r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
-                r7 = (r1 >> 8) & 0xFF00FF;
-                r1 &= 0xFF00FF;
-                r1 += r2;
-
-                r7 += r8;
-
-                r0 -= 5 * r1;
-                r6 -= 5 * r7;
-
-                r0 >>= 5;
-                r6 >>= 5;
-                /* clip */
-                r13 |= r6;
-                r13 |= r0;
-                //CLIPPACK(r6,result)
-                r0 &= 0xFF00FF;
-                r6 &= 0xFF00FF;
-                r0 |= (r6 << 8);  /* pack it back */
-                *((uint32*)(p_cur += outpitch)) = r0;
-            }
-            p_cur += curr_offset; /* offset to the next pixel */
-            if (r13 & 0xFF000700) /* this column need clipping */
-            {
-                p_cur -= 4;
-                for (i = 0; i < 4; i++)
-                {
-                    p_ref = in + i;
-                    p_cur -= outpitch;  /* compensate for the first offset */
-                    tmp = (uint32)(p_ref + ref_offset); /* limit */
-                    while ((uint32)p_ref < tmp)
-                    {                           /* loop un-rolled */
-                        r0 = *(p_ref - (inpitch << 1));
-                        r1 = *(p_ref - inpitch);
-                        r2 = *p_ref;
-                        r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-                        r4 = *(p_ref += inpitch);
-                        /* first pixel */
-                        r5 = *(p_ref += inpitch);
-                        result = (r0 + r5);
-                        r0 = (r1 + r4);
-                        result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                        r0 = (r2 + r3);
-                        result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        *(p_cur += outpitch) = result;
-                        /* second pixel */
-                        r0 = *(p_ref += inpitch);
-                        result = (r1 + r0);
-                        r1 = (r2 + r5);
-                        result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                        r1 = (r3 + r4);
-                        result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        *(p_cur += outpitch) = result;
-                        /* third pixel */
-                        r1 = *(p_ref += inpitch);
-                        result = (r2 + r1);
-                        r2 = (r3 + r0);
-                        result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                        r2 = (r4 + r5);
-                        result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        *(p_cur += outpitch) = result;
-                        /* fourth pixel */
-                        r2 = *(p_ref += inpitch);
-                        result = (r3 + r2);
-                        r3 = (r4 + r1);
-                        result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                        r3 = (r5 + r0);
-                        result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                        result = (result + 16) >> 5;
-                        CLIP_RESULT(result)
-                        *(p_cur += outpitch) = result;
-                        p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-                    }
-                    p_cur += (curr_offset - 3);
-                }
-            }
-        }
-    }
-
-    return ;
-}
-
-void VertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
-                   int blkwidth, int blkheight)
-{
-    int *p_cur;
-    uint8 *p_ref;
-    uint32 tmp;
-    int result, curr_offset, ref_offset;
-    int j, r0, r1, r2, r3, r4, r5;
-
-    p_cur = out;
-    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
-    ref_offset = blkheight * inpitch; /* for limit */
-
-    for (j = 0; j < blkwidth; j++)
-    {
-        p_cur -= outpitch; /* compensate for the first offset */
-        p_ref = in++;
-
-        tmp = (uint32)(p_ref + ref_offset); /* limit */
-        while ((uint32)p_ref < tmp)
-        {                           /* loop un-rolled */
-            r0 = *(p_ref - (inpitch << 1));
-            r1 = *(p_ref - inpitch);
-            r2 = *p_ref;
-            r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-            r4 = *(p_ref += inpitch);
-            /* first pixel */
-            r5 = *(p_ref += inpitch);
-            result = (r0 + r5);
-            r0 = (r1 + r4);
-            result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-            r0 = (r2 + r3);
-            result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-            *(p_cur += outpitch) = result;
-            /* second pixel */
-            r0 = *(p_ref += inpitch);
-            result = (r1 + r0);
-            r1 = (r2 + r5);
-            result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-            r1 = (r3 + r4);
-            result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-            *(p_cur += outpitch) = result;
-            /* third pixel */
-            r1 = *(p_ref += inpitch);
-            result = (r2 + r1);
-            r2 = (r3 + r0);
-            result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-            r2 = (r4 + r5);
-            result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-            *(p_cur += outpitch) = result;
-            /* fourth pixel */
-            r2 = *(p_ref += inpitch);
-            result = (r3 + r2);
-            r3 = (r4 + r1);
-            result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-            r3 = (r5 + r0);
-            result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-            *(p_cur += outpitch) = result;
-            p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-        }
-        p_cur += curr_offset;
-    }
-
-    return ;
-}
-
-void VertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
-                   int blkwidth, int blkheight, int dy)
-{
-    uint8 *p_cur;
-    int *p_ref;
-    uint32 tmp;
-    int result, result2, curr_offset, ref_offset;
-    int j, r0, r1, r2, r3, r4, r5;
-
-    p_cur = out;
-    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
-    ref_offset = blkheight * inpitch; /* for limit */
-
-    if (dy&1)
-    {
-        dy = (dy >> 1) ? -(inpitch << 1) : -(inpitch << 1) - inpitch;
-
-        for (j = 0; j < blkwidth; j++)
-        {
-            p_cur -= outpitch; /* compensate for the first offset */
-            p_ref = in++;
-
-            tmp = (uint32)(p_ref + ref_offset); /* limit */
-            while ((uint32)p_ref < tmp)
-            {                           /* loop un-rolled */
-                r0 = *(p_ref - (inpitch << 1));
-                r1 = *(p_ref - inpitch);
-                r2 = *p_ref;
-                r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-                r4 = *(p_ref += inpitch);
-                /* first pixel */
-                r5 = *(p_ref += inpitch);
-                result = (r0 + r5);
-                r0 = (r1 + r4);
-                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                r0 = (r2 + r3);
-                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dy] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                *(p_cur += outpitch) = result;
-                /* second pixel */
-                r0 = *(p_ref += inpitch);
-                result = (r1 + r0);
-                r1 = (r2 + r5);
-                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                r1 = (r3 + r4);
-                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dy] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                *(p_cur += outpitch) = result;
-                /* third pixel */
-                r1 = *(p_ref += inpitch);
-                result = (r2 + r1);
-                r2 = (r3 + r0);
-                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                r2 = (r4 + r5);
-                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dy] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                *(p_cur += outpitch) = result;
-                /* fourth pixel */
-                r2 = *(p_ref += inpitch);
-                result = (r3 + r2);
-                r3 = (r4 + r1);
-                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                r3 = (r5 + r0);
-                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                result2 = ((p_ref[dy] + 16) >> 5);
-                CLIP_RESULT(result2)
-                /* 3/4 pel,  no need to clip */
-                result = (result + result2 + 1);
-                result = (result >> 1);
-                *(p_cur += outpitch) = result;
-                p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-            }
-            p_cur += curr_offset;
-        }
-    }
-    else
-    {
-        for (j = 0; j < blkwidth; j++)
-        {
-            p_cur -= outpitch; /* compensate for the first offset */
-            p_ref = in++;
-
-            tmp = (uint32)(p_ref + ref_offset); /* limit */
-            while ((uint32)p_ref < tmp)
-            {                           /* loop un-rolled */
-                r0 = *(p_ref - (inpitch << 1));
-                r1 = *(p_ref - inpitch);
-                r2 = *p_ref;
-                r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-                r4 = *(p_ref += inpitch);
-                /* first pixel */
-                r5 = *(p_ref += inpitch);
-                result = (r0 + r5);
-                r0 = (r1 + r4);
-                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                r0 = (r2 + r3);
-                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                *(p_cur += outpitch) = result;
-                /* second pixel */
-                r0 = *(p_ref += inpitch);
-                result = (r1 + r0);
-                r1 = (r2 + r5);
-                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                r1 = (r3 + r4);
-                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                *(p_cur += outpitch) = result;
-                /* third pixel */
-                r1 = *(p_ref += inpitch);
-                result = (r2 + r1);
-                r2 = (r3 + r0);
-                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                r2 = (r4 + r5);
-                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                *(p_cur += outpitch) = result;
-                /* fourth pixel */
-                r2 = *(p_ref += inpitch);
-                result = (r3 + r2);
-                r3 = (r4 + r1);
-                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                r3 = (r5 + r0);
-                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                result = (result + 512) >> 10;
-                CLIP_RESULT(result)
-                *(p_cur += outpitch) = result;
-                p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-            }
-            p_cur += curr_offset;
-        }
-    }
-
-    return ;
-}
-
-void DiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
-                      uint8 *out, int outpitch,
-                      int blkwidth, int blkheight)
-{
-    int j, i;
-    int result;
-    uint8 *p_cur, *p_ref, *p_tmp8;
-    int curr_offset, ref_offset;
-    uint8 tmp_res[24][24], tmp_in[24][24];
-    uint32 *p_tmp;
-    uint32 tmp, pkres, tmp_result;
-    int32 r0, r1, r2, r3, r4, r5;
-    int32 r6, r7, r8, r9, r10, r13;
-
-    ref_offset = inpitch - blkwidth;
-    p_ref = in1 - 2;
-    /* perform horizontal interpolation */
-    /* not word-aligned */
-    /* It is faster to read 1 byte at time to avoid calling CreateAlign */
-    /*  if(((uint32)p_ref)&0x3)
-        {
-            CreateAlign(p_ref,inpitch,0,&tmp_in[0][0],blkwidth+8,blkheight);
-            p_ref = &tmp_in[0][0];
-            ref_offset = 24-blkwidth;
-        }*/
-
-    p_tmp = (uint32*) & (tmp_res[0][0]);
-    for (j = blkheight; j > 0; j--)
-    {
-        r13 = 0;
-        tmp = (uint32)(p_ref + blkwidth);
-
-        //r0 = *((uint32*)p_ref);   /* d,c,b,a */
-        //r1 = (r0>>8)&0xFF00FF;    /* 0,d,0,b */
-        //r0 &= 0xFF00FF;           /* 0,c,0,a */
-        /* It is faster to read 1 byte at a time,  */
-        r0 = p_ref[0];
-        r1 = p_ref[2];
-        r0 |= (r1 << 16);           /* 0,c,0,a */
-        r1 = p_ref[1];
-        r2 = p_ref[3];
-        r1 |= (r2 << 16);           /* 0,d,0,b */
-
-        while ((uint32)p_ref < tmp)
-        {
-            //r2 = *((uint32*)(p_ref+=4));/* h,g,f,e */
-            //r3 = (r2>>8)&0xFF00FF;  /* 0,h,0,f */
-            //r2 &= 0xFF00FF;           /* 0,g,0,e */
-            /* It is faster to read 1 byte at a time,  */
-            r2 = *(p_ref += 4);
-            r3 = p_ref[2];
-            r2 |= (r3 << 16);           /* 0,g,0,e */
-            r3 = p_ref[1];
-            r4 = p_ref[3];
-            r3 |= (r4 << 16);           /* 0,h,0,f */
-
-            r4 = r0 + r3;       /* c+h, a+f */
-            r5 = r0 + r1;   /* c+d, a+b */
-            r6 = r2 + r3;   /* g+h, e+f */
-            r5 >>= 16;
-            r5 |= (r6 << 16);   /* e+f, c+d */
-            r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
-            r4 += 0x100010; /* +16, +16 */
-            r5 = r1 + r2;       /* d+g, b+e */
-            r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
-            r4 >>= 5;
-            r13 |= r4;      /* check clipping */
-            r4 &= 0xFF00FF; /* mask */
-
-            r5 = p_ref[4];  /* i */
-            r6 = (r5 << 16);
-            r5 = r6 | (r2 >> 16);/* 0,i,0,g */
-            r5 += r1;       /* d+i, b+g */ /* r5 not free */
-            r1 >>= 16;
-            r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
-            r1 += r2;       /* f+g, d+e */
-            r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
-            r0 >>= 16;
-            r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
-            r0 += r3;       /* e+h, c+f */
-            r5 += 0x100010; /* 16,16 */
-            r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
-            r5 >>= 5;
-            r13 |= r5;      /* check clipping */
-            r5 &= 0xFF00FF; /* mask */
-
-            r4 |= (r5 << 8);    /* pack them together */
-            *p_tmp++ = r4;
-            r1 = r3;
-            r0 = r2;
-        }
-        p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
-        p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
-
-        if (r13&0xFF000700) /* need clipping */
-        {
-            /* move back to the beginning of the line */
-            p_ref -= (ref_offset + blkwidth);   /* input */
-            p_tmp -= 6; /* intermediate output */
-            tmp = (uint32)(p_ref + blkwidth);
-            while ((uint32)p_ref < tmp)
-            {
-                r0 = *p_ref++;
-                r1 = *p_ref++;
-                r2 = *p_ref++;
-                r3 = *p_ref++;
-                r4 = *p_ref++;
-                /* first pixel */
-                r5 = *p_ref++;
-                result = (r0 + r5);
-                r0 = (r1 + r4);
-                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                r0 = (r2 + r3);
-                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                result = (result + 16) >> 5;
-                CLIP_RESULT(result)
-                pkres = result;
-                /* second pixel */
-                r0 = *p_ref++;
-                result = (r1 + r0);
-                r1 = (r2 + r5);
-                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                r1 = (r3 + r4);
-                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                result = (result + 16) >> 5;
-                CLIP_RESULT(result)
-                pkres |= (result << 8);
-                /* third pixel */
-                r1 = *p_ref++;
-                result = (r2 + r1);
-                r2 = (r3 + r0);
-                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                r2 = (r4 + r5);
-                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                result = (result + 16) >> 5;
-                CLIP_RESULT(result)
-                pkres |= (result << 16);
-                /* fourth pixel */
-                r2 = *p_ref++;
-                result = (r3 + r2);
-                r3 = (r4 + r1);
-                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                r3 = (r5 + r0);
-                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                result = (result + 16) >> 5;
-                CLIP_RESULT(result)
-                pkres |= (result << 24);
-
-                *p_tmp++ = pkres; /* write 4 pixel */
-                p_ref -= 5;
-            }
-            p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
-            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
-        }
-    }
-
-    /*  perform vertical interpolation */
-    /* not word-aligned */
-    if (((uint32)in2)&0x3)
-    {
-        CreateAlign(in2, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
-        in2 = &tmp_in[2][0];
-        inpitch = 24;
-    }
-
-    p_cur = out;
-    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically up and one pixel right */
-    pkres = blkheight * inpitch; /* reuse it for limit */
-
-    curr_offset += 3;
-
-    for (j = 0; j < blkwidth; j += 4, in2 += 4)
-    {
-        r13 = 0;
-        p_ref = in2;
-        p_tmp8 = &(tmp_res[0][j]); /* intermediate result */
-        p_tmp8 -= 24;  /* compensate for the first offset */
-        p_cur -= outpitch;  /* compensate for the first offset */
-        tmp = (uint32)(p_ref + pkres); /* limit */
-        while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
-        {
-            /* Read 1 byte at a time is too slow, too many read and pack ops, need to call CreateAlign,  */
-            /*p_ref8 = p_ref-(inpitch<<1);          r0 = p_ref8[0];         r1 = p_ref8[2];
-            r0 |= (r1<<16);         r6 = p_ref8[1];         r1 = p_ref8[3];
-            r6 |= (r1<<16);         p_ref+=inpitch; */
-            r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
-            p_ref += inpitch;
-            r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
-            r0 &= 0xFF00FF;
-
-            /*p_ref8 = p_ref+(inpitch<<1);
-            r1 = p_ref8[0];         r7 = p_ref8[2];         r1 |= (r7<<16);
-            r7 = p_ref8[1];         r2 = p_ref8[3];         r7 |= (r2<<16);*/
-            r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
-            r7 = (r1 >> 8) & 0xFF00FF;
-            r1 &= 0xFF00FF;
-
-            r0 += r1;
-            r6 += r7;
-
-            /*r2 = p_ref[0];            r8 = p_ref[2];          r2 |= (r8<<16);
-            r8 = p_ref[1];          r1 = p_ref[3];          r8 |= (r1<<16);*/
-            r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
-            r8 = (r2 >> 8) & 0xFF00FF;
-            r2 &= 0xFF00FF;
-
-            /*p_ref8 = p_ref-inpitch;           r1 = p_ref8[0];         r7 = p_ref8[2];
-            r1 |= (r7<<16);         r1 += r2;           r7 = p_ref8[1];
-            r2 = p_ref8[3];         r7 |= (r2<<16);*/
-            r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
-            r7 = (r1 >> 8) & 0xFF00FF;
-            r1 &= 0xFF00FF;
-            r1 += r2;
-
-            r7 += r8;
-
-            r0 += 20 * r1;
-            r6 += 20 * r7;
-            r0 += 0x100010;
-            r6 += 0x100010;
-
-            /*p_ref8 = p_ref-(inpitch<<1);          r2 = p_ref8[0];         r8 = p_ref8[2];
-            r2 |= (r8<<16);         r8 = p_ref8[1];         r1 = p_ref8[3];         r8 |= (r1<<16);*/
-            r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
-            r8 = (r2 >> 8) & 0xFF00FF;
-            r2 &= 0xFF00FF;
-
-            /*p_ref8 = p_ref+inpitch;           r1 = p_ref8[0];         r7 = p_ref8[2];
-            r1 |= (r7<<16);         r1 += r2;           r7 = p_ref8[1];
-            r2 = p_ref8[3];         r7 |= (r2<<16);*/
-            r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
-            r7 = (r1 >> 8) & 0xFF00FF;
-            r1 &= 0xFF00FF;
-            r1 += r2;
-
-            r7 += r8;
-
-            r0 -= 5 * r1;
-            r6 -= 5 * r7;
-
-            r0 >>= 5;
-            r6 >>= 5;
-            /* clip */
-            r13 |= r6;
-            r13 |= r0;
-            //CLIPPACK(r6,result)
-            /* add with horizontal results */
-            r10 = *((uint32*)(p_tmp8 += 24));
-            r9 = (r10 >> 8) & 0xFF00FF;
-            r10 &= 0xFF00FF;
-
-            r0 += r10;
-            r0 += 0x10001;
-            r0 = (r0 >> 1) & 0xFF00FF;   /* mask to 8 bytes */
-
-            r6 += r9;
-            r6 += 0x10001;
-            r6 = (r6 >> 1) & 0xFF00FF;   /* mask to 8 bytes */
-
-            r0 |= (r6 << 8);  /* pack it back */
-            *((uint32*)(p_cur += outpitch)) = r0;
-        }
-        p_cur += curr_offset; /* offset to the next pixel */
-        if (r13 & 0xFF000700) /* this column need clipping */
-        {
-            p_cur -= 4;
-            for (i = 0; i < 4; i++)
-            {
-                p_ref = in2 + i;
-                p_tmp8 = &(tmp_res[0][j+i]); /* intermediate result */
-                p_tmp8 -= 24;  /* compensate for the first offset */
-                p_cur -= outpitch;  /* compensate for the first offset */
-                tmp = (uint32)(p_ref + pkres); /* limit */
-                while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
-                {
-                    r0 = *(p_ref - (inpitch << 1));
-                    r1 = *(p_ref - inpitch);
-                    r2 = *p_ref;
-                    r3 = *(p_ref += inpitch);  /* modify pointer before loading */
-                    r4 = *(p_ref += inpitch);
-                    /* first pixel */
-                    r5 = *(p_ref += inpitch);
-                    result = (r0 + r5);
-                    r0 = (r1 + r4);
-                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
-                    r0 = (r2 + r3);
-                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    tmp_result = *(p_tmp8 += 24);  /* modify pointer before loading */
-                    result = (result + tmp_result + 1);  /* no clip */
-                    result = (result >> 1);
-                    *(p_cur += outpitch) = result;
-                    /* second pixel */
-                    r0 = *(p_ref += inpitch);
-                    result = (r1 + r0);
-                    r1 = (r2 + r5);
-                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
-                    r1 = (r3 + r4);
-                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
-                    result = (result + tmp_result + 1);  /* no clip */
-                    result = (result >> 1);
-                    *(p_cur += outpitch) = result;
-                    /* third pixel */
-                    r1 = *(p_ref += inpitch);
-                    result = (r2 + r1);
-                    r2 = (r3 + r0);
-                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
-                    r2 = (r4 + r5);
-                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
-                    result = (result + tmp_result + 1);  /* no clip */
-                    result = (result >> 1);
-                    *(p_cur += outpitch) = result;
-                    /* fourth pixel */
-                    r2 = *(p_ref += inpitch);
-                    result = (r3 + r2);
-                    r3 = (r4 + r1);
-                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
-                    r3 = (r5 + r0);
-                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
-                    result = (result + 16) >> 5;
-                    CLIP_RESULT(result)
-                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
-                    result = (result + tmp_result + 1);  /* no clip */
-                    result = (result >> 1);
-                    *(p_cur += outpitch) = result;
-                    p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
-                }
-                p_cur += (curr_offset - 3);
-            }
-        }
-    }
-
-    return ;
-}
-
-/* position G */
-void FullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
-               int blkwidth, int blkheight)
-{
-    int i, j;
-    int offset_in = inpitch - blkwidth;
-    int offset_out = outpitch - blkwidth;
-    uint32 temp;
-    uint8 byte;
-
-    if (((uint32)in)&3)
-    {
-        for (j = blkheight; j > 0; j--)
-        {
-            for (i = blkwidth; i > 0; i -= 4)
-            {
-                temp = *in++;
-                byte = *in++;
-                temp |= (byte << 8);
-                byte = *in++;
-                temp |= (byte << 16);
-                byte = *in++;
-                temp |= (byte << 24);
-
-                *((uint32*)out) = temp; /* write 4 bytes */
-                out += 4;
-            }
-            out += offset_out;
-            in += offset_in;
-        }
-    }
-    else
-    {
-        for (j = blkheight; j > 0; j--)
-        {
-            for (i = blkwidth; i > 0; i -= 4)
-            {
-                temp = *((uint32*)in);
-                *((uint32*)out) = temp;
-                in += 4;
-                out += 4;
-            }
-            out += offset_out;
-            in += offset_in;
-        }
-    }
-    return ;
-}
-
-void ChromaMotionComp(uint8 *ref, int picwidth, int picheight,
-                      int x_pos, int y_pos,
-                      uint8 *pred, int pred_pitch,
-                      int blkwidth, int blkheight)
-{
-    int dx, dy;
-    int offset_dx, offset_dy;
-    int index;
-    uint8 temp[24][24];
-
-    dx = x_pos & 7;
-    dy = y_pos & 7;
-    offset_dx = (dx + 7) >> 3;
-    offset_dy = (dy + 7) >> 3;
-    x_pos = x_pos >> 3;  /* round it to full-pel resolution */
-    y_pos = y_pos >> 3;
-
-    if ((x_pos >= 0 && x_pos + blkwidth + offset_dx <= picwidth) && (y_pos >= 0 && y_pos + blkheight + offset_dy <= picheight))
-    {
-        ref += y_pos * picwidth + x_pos;
-    }
-    else
-    {
-        CreatePad(ref, picwidth, picheight, x_pos, y_pos, &temp[0][0], blkwidth + offset_dx, blkheight + offset_dy);
-        ref = &temp[0][0];
-        picwidth = 24;
-    }
-
-    index = offset_dx + (offset_dy << 1) + ((blkwidth << 1) & 0x7);
-
-    (*(ChromaMC_SIMD[index]))(ref, picwidth , dx, dy, pred, pred_pitch, blkwidth, blkheight);
-    return ;
-}
-
-
-/* SIMD routines, unroll the loops in vertical direction, decreasing loops (things to be done)  */
-void ChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                           uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    int32 r0, r1, r2, r3, result0, result1;
-    uint8 temp[288];
-    uint8 *ref, *out;
-    int i, j;
-    int dx_8 = 8 - dx;
-    int dy_8 = 8 - dy;
-
-    /* horizontal first */
-    out = temp;
-    for (i = 0; i < blkheight + 1; i++)
-    {
-        ref = pRef;
-        r0 = ref[0];
-        for (j = 0; j < blkwidth; j += 4)
-        {
-            r0 |= (ref[2] << 16);
-            result0 = dx_8 * r0;
-
-            r1 = ref[1] | (ref[3] << 16);
-            result0 += dx * r1;
-            *(int32 *)out = result0;
-
-            result0 = dx_8 * r1;
-
-            r2 = ref[4];
-            r0 = r0 >> 16;
-            r1 = r0 | (r2 << 16);
-            result0 += dx * r1;
-            *(int32 *)(out + 16) = result0;
-
-            ref += 4;
-            out += 4;
-            r0 = r2;
-        }
-        pRef += srcPitch;
-        out += (32 - blkwidth);
-    }
-
-//  pRef -= srcPitch*(blkheight+1);
-    ref = temp;
-
-    for (j = 0; j < blkwidth; j += 4)
-    {
-        r0 = *(int32 *)ref;
-        r1 = *(int32 *)(ref + 16);
-        ref += 32;
-        out = pOut;
-        for (i = 0; i < (blkheight >> 1); i++)
-        {
-            result0 = dy_8 * r0 + 0x00200020;
-            r2 = *(int32 *)ref;
-            result0 += dy * r2;
-            result0 >>= 6;
-            result0 &= 0x00FF00FF;
-            r0 = r2;
-
-            result1 = dy_8 * r1 + 0x00200020;
-            r3 = *(int32 *)(ref + 16);
-            result1 += dy * r3;
-            result1 >>= 6;
-            result1 &= 0x00FF00FF;
-            r1 = r3;
-            *(int32 *)out = result0 | (result1 << 8);
-            out += predPitch;
-            ref += 32;
-
-            result0 = dy_8 * r0 + 0x00200020;
-            r2 = *(int32 *)ref;
-            result0 += dy * r2;
-            result0 >>= 6;
-            result0 &= 0x00FF00FF;
-            r0 = r2;
-
-            result1 = dy_8 * r1 + 0x00200020;
-            r3 = *(int32 *)(ref + 16);
-            result1 += dy * r3;
-            result1 >>= 6;
-            result1 &= 0x00FF00FF;
-            r1 = r3;
-            *(int32 *)out = result0 | (result1 << 8);
-            out += predPitch;
-            ref += 32;
-        }
-        pOut += 4;
-        ref = temp + 4; /* since it can only iterate twice max  */
-    }
-    return;
-}
-
-void ChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                             uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(dy);
-    int32 r0, r1, r2, result0, result1;
-    uint8 *ref, *out;
-    int i, j;
-    int dx_8 = 8 - dx;
-
-    /* horizontal first */
-    for (i = 0; i < blkheight; i++)
-    {
-        ref = pRef;
-        out = pOut;
-
-        r0 = ref[0];
-        for (j = 0; j < blkwidth; j += 4)
-        {
-            r0 |= (ref[2] << 16);
-            result0 = dx_8 * r0 + 0x00040004;
-
-            r1 = ref[1] | (ref[3] << 16);
-            result0 += dx * r1;
-            result0 >>= 3;
-            result0 &= 0x00FF00FF;
-
-            result1 = dx_8 * r1 + 0x00040004;
-
-            r2 = ref[4];
-            r0 = r0 >> 16;
-            r1 = r0 | (r2 << 16);
-            result1 += dx * r1;
-            result1 >>= 3;
-            result1 &= 0x00FF00FF;
-
-            *(int32 *)out = result0 | (result1 << 8);
-
-            ref += 4;
-            out += 4;
-            r0 = r2;
-        }
-
-        pRef += srcPitch;
-        pOut += predPitch;
-    }
-    return;
-}
-
-void ChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                           uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(dx);
-    int32 r0, r1, r2, r3, result0, result1;
-    int i, j;
-    uint8 *ref, *out;
-    int dy_8 = 8 - dy;
-    /* vertical first */
-    for (i = 0; i < blkwidth; i += 4)
-    {
-        ref = pRef;
-        out = pOut;
-
-        r0 = ref[0] | (ref[2] << 16);
-        r1 = ref[1] | (ref[3] << 16);
-        ref += srcPitch;
-        for (j = 0; j < blkheight; j++)
-        {
-            result0 = dy_8 * r0 + 0x00040004;
-            r2 = ref[0] | (ref[2] << 16);
-            result0 += dy * r2;
-            result0 >>= 3;
-            result0 &= 0x00FF00FF;
-            r0 = r2;
-
-            result1 = dy_8 * r1 + 0x00040004;
-            r3 = ref[1] | (ref[3] << 16);
-            result1 += dy * r3;
-            result1 >>= 3;
-            result1 &= 0x00FF00FF;
-            r1 = r3;
-            *(int32 *)out = result0 | (result1 << 8);
-            ref += srcPitch;
-            out += predPitch;
-        }
-        pOut += 4;
-        pRef += 4;
-    }
-    return;
-}
-
-void ChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                            uint8 *pOut,  int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(blkwidth);
-    int32 r0, r1, temp0, temp1, result;
-    int32 temp[9];
-    int32 *out;
-    int i, r_temp;
-    int dy_8 = 8 - dy;
-
-    /* horizontal first */
-    out = temp;
-    for (i = 0; i < blkheight + 1; i++)
-    {
-        r_temp = pRef[1];
-        temp0 = (pRef[0] << 3) + dx * (r_temp - pRef[0]);
-        temp1 = (r_temp << 3) + dx * (pRef[2] - r_temp);
-        r0 = temp0 | (temp1 << 16);
-        *out++ = r0;
-        pRef += srcPitch;
-    }
-
-    pRef -= srcPitch * (blkheight + 1);
-
-    out = temp;
-
-    r0 = *out++;
-
-    for (i = 0; i < blkheight; i++)
-    {
-        result = dy_8 * r0 + 0x00200020;
-        r1 = *out++;
-        result += dy * r1;
-        result >>= 6;
-        result &= 0x00FF00FF;
-        *(int16 *)pOut = (result >> 8) | (result & 0xFF);
-        r0 = r1;
-        pOut += predPitch;
-    }
-    return;
-}
-
-void ChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                              uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(dy);
-    OSCL_UNUSED_ARG(blkwidth);
-    int i, temp, temp0, temp1;
-
-    /* horizontal first */
-    for (i = 0; i < blkheight; i++)
-    {
-        temp = pRef[1];
-        temp0 = ((pRef[0] << 3) + dx * (temp - pRef[0]) + 4) >> 3;
-        temp1 = ((temp << 3) + dx * (pRef[2] - temp) + 4) >> 3;
-
-        *(int16 *)pOut = temp0 | (temp1 << 8);
-        pRef += srcPitch;
-        pOut += predPitch;
-
-    }
-    return;
-}
-void ChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                            uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(dx);
-    OSCL_UNUSED_ARG(blkwidth);
-    int32 r0, r1, result;
-    int i;
-    int dy_8 = 8 - dy;
-    r0 = pRef[0] | (pRef[1] << 16);
-    pRef += srcPitch;
-    for (i = 0; i < blkheight; i++)
-    {
-        result = dy_8 * r0 + 0x00040004;
-        r1 = pRef[0] | (pRef[1] << 16);
-        result += dy * r1;
-        result >>= 3;
-        result &= 0x00FF00FF;
-        *(int16 *)pOut = (result >> 8) | (result & 0xFF);
-        r0 = r1;
-        pRef += srcPitch;
-        pOut += predPitch;
-    }
-    return;
-}
-
-void ChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
-                       uint8 *pOut, int predPitch, int blkwidth, int blkheight)
-{
-    OSCL_UNUSED_ARG(dx);
-    OSCL_UNUSED_ARG(dy);
-    int i, j;
-    int offset_in = srcPitch - blkwidth;
-    int offset_out = predPitch - blkwidth;
-    uint16 temp;
-    uint8 byte;
-
-    if (((uint32)pRef)&1)
-    {
-        for (j = blkheight; j > 0; j--)
-        {
-            for (i = blkwidth; i > 0; i -= 2)
-            {
-                temp = *pRef++;
-                byte = *pRef++;
-                temp |= (byte << 8);
-                *((uint16*)pOut) = temp; /* write 2 bytes */
-                pOut += 2;
-            }
-            pOut += offset_out;
-            pRef += offset_in;
-        }
-    }
-    else
-    {
-        for (j = blkheight; j > 0; j--)
-        {
-            for (i = blkwidth; i > 0; i -= 2)
-            {
-                temp = *((uint16*)pRef);
-                *((uint16*)pOut) = temp;
-                pRef += 2;
-                pOut += 2;
-            }
-            pOut += offset_out;
-            pRef += offset_in;
-        }
-    }
-    return ;
-}
diff --git a/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp b/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp
deleted file mode 100644
index 0b613a4..0000000
--- a/media/libstagefright/codecs/avc/dec/src/pred_intra.cpp
+++ /dev/null
@@ -1,1786 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avcdec_lib.h"
-
-#define CLIP_COMP  *comp++ = (uint8)(((uint)temp>0xFF)? 0xFF&(~(temp>>31)): temp)
-#define CLIP_RESULT(x)      if((uint)x > 0xFF){ \
-                 x = 0xFF & (~(x>>31));}
-
-
-/* We should combine the Intra4x4 functions with residual decoding and compensation  */
-AVCStatus IntraMBPrediction(AVCCommonObj *video)
-{
-    int component, SubBlock_indx, temp;
-    AVCStatus status;
-    AVCMacroblock *currMB = video->currMB;
-    AVCPictureData *currPic = video->currPic;
-    uint8 *curL, *curCb, *curCr;
-    uint8 *comp;
-    int block_x, block_y, offset;
-    int16 *dataBlock = video->block;
-    uint8 *predCb, *predCr;
-#ifdef USE_PRED_BLOCK
-    uint8 *pred;
-#endif
-    int pitch = currPic->pitch;
-    uint32 cbp4x4 = video->cbp4x4;
-
-    offset = (video->mb_y << 4) * pitch + (video->mb_x << 4);
-    curL = currPic->Sl + offset;
-
-#ifdef USE_PRED_BLOCK
-    video->pred_block = video->pred + 84;  /* point to separate prediction memory */
-    pred = video->pred_block;
-    video->pred_pitch = 20;
-#else
-    video->pred_block = curL;   /* point directly to the frame buffer */
-    video->pred_pitch = pitch;
-#endif
-
-    if (currMB->mbMode == AVC_I4)
-    {
-        /* luminance first */
-        block_x = block_y = 0;
-        for (component = 0; component < 4; component++)
-        {
-            block_x = ((component & 1) << 1);
-            block_y = ((component >> 1) << 1);
-            comp = curL;// + (block_x<<2) + (block_y<<2)*currPic->pitch;
-
-            for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++)
-            {
-                status = Intra_4x4(video, block_x, block_y, comp);
-                if (status != AVC_SUCCESS)
-                {
-                    return status;
-                }
-                /* transform following the 4x4 prediction, can't be SIMD
-                with other blocks. */
-#ifdef USE_PRED_BLOCK
-                if (cbp4x4&(1 << ((block_y << 2) + block_x)))
-                {
-                    itrans(dataBlock, pred, pred, 20);
-                }
-#else
-                if (cbp4x4&(1 << ((block_y << 2) + block_x)))
-                {
-                    itrans(dataBlock, comp, comp, pitch);
-                }
-#endif
-                temp = SubBlock_indx & 1;
-                if (temp)
-                {
-                    block_y++;
-                    block_x--;
-                    dataBlock += 60;
-#ifdef USE_PRED_BLOCK
-                    pred += 76;
-#else
-                    comp += ((pitch << 2) - 4);
-#endif
-                }
-                else
-                {
-                    block_x++;
-                    dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-                    pred += 4;
-#else
-                    comp += 4;
-#endif
-                }
-            }
-            if (component&1)
-            {
-#ifdef USE_PRED_BLOCK
-                pred -= 8;
-#else
-                curL += (pitch << 3) - 8;
-#endif
-                dataBlock -= 8;
-            }
-            else
-            {
-#ifdef USE_PRED_BLOCK
-                pred -= 152;
-#else
-                curL += 8;
-#endif
-                dataBlock -= 120;
-            }
-        }
-        cbp4x4 >>= 16;
-    }
-    else   /* AVC_I16 */
-    {
-#ifdef MB_BASED_DEBLOCK
-        video->pintra_pred_top = video->intra_pred_top + (video->mb_x << 4);
-        video->pintra_pred_left = video->intra_pred_left + 1;
-        video->intra_pred_topleft = video->intra_pred_left[0];
-        pitch = 1;
-#else
-        video->pintra_pred_top = curL - pitch;
-        video->pintra_pred_left = curL - 1;
-        if (video->mb_y)
-        {
-            video->intra_pred_topleft = *(curL - pitch - 1);
-        }
-#endif
-        switch (currMB->i16Mode)
-        {
-            case AVC_I16_Vertical:      /* Intra_16x16_Vertical */
-                /* check availability of top */
-                if (video->intraAvailB)
-                {
-                    Intra_16x16_Vertical(video);
-                }
-                else
-                {
-                    return AVC_FAIL;
-                }
-                break;
-            case AVC_I16_Horizontal:        /* Intra_16x16_Horizontal */
-                /* check availability of left */
-                if (video->intraAvailA)
-                {
-                    Intra_16x16_Horizontal(video, pitch);
-                }
-                else
-                {
-                    return AVC_FAIL;
-                }
-                break;
-            case AVC_I16_DC:        /* Intra_16x16_DC */
-                Intra_16x16_DC(video, pitch);
-                break;
-            case AVC_I16_Plane:     /* Intra_16x16_Plane */
-                if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
-                {
-                    Intra_16x16_Plane(video, pitch);
-                }
-                else
-                {
-                    return AVC_FAIL;
-                }
-                break;
-            default:
-                break;
-        }
-
-        pitch = currPic->pitch;
-
-        /* transform */
-        /* can go in raster scan order now */
-        /* can be done in SIMD,  */
-        for (block_y = 4; block_y > 0; block_y--)
-        {
-            for (block_x = 4; block_x > 0; block_x--)
-            {
-#ifdef USE_PRED_BLOCK
-                if (cbp4x4&1)
-                {
-                    itrans(dataBlock, pred, pred, 20);
-                }
-#else
-                if (cbp4x4&1)
-                {
-                    itrans(dataBlock, curL, curL, pitch);
-                }
-#endif
-                cbp4x4 >>= 1;
-                dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-                pred += 4;
-#else
-                curL += 4;
-#endif
-            }
-            dataBlock += 48;
-#ifdef USE_PRED_BLOCK
-            pred += 64;
-#else
-            curL += ((pitch << 2) - 16);
-#endif
-        }
-    }
-
-    offset = (offset >> 2) + (video->mb_x << 2); //((video->mb_y << 3)* pitch + (video->mb_x << 3));
-    curCb = currPic->Scb + offset;
-    curCr = currPic->Scr + offset;
-
-#ifdef MB_BASED_DEBLOCK
-    video->pintra_pred_top_cb = video->intra_pred_top_cb + (video->mb_x << 3);
-    video->pintra_pred_left_cb = video->intra_pred_left_cb + 1;
-    video->intra_pred_topleft_cb = video->intra_pred_left_cb[0];
-    video->pintra_pred_top_cr = video->intra_pred_top_cr + (video->mb_x << 3);
-    video->pintra_pred_left_cr = video->intra_pred_left_cr + 1;
-    video->intra_pred_topleft_cr = video->intra_pred_left_cr[0];
-    pitch  = 1;
-#else
-    pitch >>= 1;
-    video->pintra_pred_top_cb = curCb - pitch;
-    video->pintra_pred_left_cb = curCb - 1;
-    video->pintra_pred_top_cr = curCr - pitch;
-    video->pintra_pred_left_cr = curCr - 1;
-
-    if (video->mb_y)
-    {
-        video->intra_pred_topleft_cb = *(curCb - pitch - 1);
-        video->intra_pred_topleft_cr = *(curCr - pitch - 1);
-    }
-#endif
-
-#ifdef USE_PRED_BLOCK
-    predCb = video->pred + 452;
-    predCr = predCb + 144;
-    video->pred_pitch = 12;
-#else
-    predCb = curCb;
-    predCr = curCr;
-    video->pred_pitch = currPic->pitch >> 1;
-#endif
-    /* chrominance */
-    switch (currMB->intra_chroma_pred_mode)
-    {
-        case AVC_IC_DC:     /* Intra_Chroma_DC */
-            Intra_Chroma_DC(video, pitch, predCb, predCr);
-            break;
-        case AVC_IC_Horizontal:     /* Intra_Chroma_Horizontal */
-            if (video->intraAvailA)
-            {
-                /* check availability of left */
-                Intra_Chroma_Horizontal(video, pitch, predCb, predCr);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-        case AVC_IC_Vertical:       /* Intra_Chroma_Vertical */
-            if (video->intraAvailB)
-            {
-                /* check availability of top */
-                Intra_Chroma_Vertical(video, predCb, predCr);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-        case AVC_IC_Plane:      /* Intra_Chroma_Plane */
-            if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
-            {
-                /* check availability of top and left */
-                Intra_Chroma_Plane(video, pitch, predCb, predCr);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-        default:
-            break;
-    }
-
-    /* transform, done in raster scan manner */
-    pitch = currPic->pitch >> 1;
-
-    for (block_y = 2; block_y > 0; block_y--)
-    {
-        for (block_x = 2; block_x > 0; block_x--)
-        {
-#ifdef USE_PRED_BLOCK
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, predCb, predCb, 12);
-            }
-#else
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, curCb, curCb, pitch);
-            }
-#endif
-            cbp4x4 >>= 1;
-            dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-            predCb += 4;
-#else
-            curCb += 4;
-#endif
-        }
-        for (block_x = 2; block_x > 0; block_x--)
-        {
-#ifdef USE_PRED_BLOCK
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, predCr, predCr, 12);
-            }
-#else
-            if (cbp4x4&1)
-            {
-                ictrans(dataBlock, curCr, curCr, pitch);
-            }
-#endif
-            cbp4x4 >>= 1;
-            dataBlock += 4;
-#ifdef USE_PRED_BLOCK
-            predCr += 4;
-#else
-            curCr += 4;
-#endif
-        }
-        dataBlock += 48;
-#ifdef USE_PRED_BLOCK
-        predCb += 40;
-        predCr += 40;
-#else
-        curCb += ((pitch << 2) - 8);
-        curCr += ((pitch << 2) - 8);
-#endif
-    }
-
-#ifdef MB_BASED_DEBLOCK
-    SaveNeighborForIntraPred(video, offset);
-#endif
-    return AVC_SUCCESS;
-}
-
-#ifdef MB_BASED_DEBLOCK
-void SaveNeighborForIntraPred(AVCCommonObj *video, int offset)
-{
-    AVCPictureData *currPic = video->currPic;
-    int pitch;
-    uint8 *pred, *predCb, *predCr;
-    uint8 *tmp_ptr, tmp_byte;
-    uint32 tmp_word;
-    int mb_x = video->mb_x;
-
-    /* save the value for intra prediction  */
-#ifdef USE_PRED_BLOCK
-    pitch = 20;
-    pred = video->pred + 384; /* bottom line for Y */
-    predCb = pred + 152;    /* bottom line for Cb */
-    predCr = predCb + 144;  /* bottom line for Cr */
-#else
-    pitch = currPic->pitch;
-    tmp_word = offset + (pitch << 2) - (pitch >> 1);
-    predCb = currPic->Scb + tmp_word;/* bottom line for Cb */
-    predCr = currPic->Scr + tmp_word;/* bottom line for Cr */
-
-    offset = (offset << 2) - (mb_x << 4);
-    pred = currPic->Sl + offset + (pitch << 4) - pitch;/* bottom line for Y */
-
-#endif
-
-    video->intra_pred_topleft = video->intra_pred_top[(mb_x<<4)+15];
-    video->intra_pred_topleft_cb = video->intra_pred_top_cb[(mb_x<<3)+7];
-    video->intra_pred_topleft_cr = video->intra_pred_top_cr[(mb_x<<3)+7];
-
-    /* then copy to video->intra_pred_top, intra_pred_top_cb, intra_pred_top_cr */
-    /*memcpy(video->intra_pred_top + (mb_x<<4), pred, 16);
-    memcpy(video->intra_pred_top_cb + (mb_x<<3), predCb, 8);
-    memcpy(video->intra_pred_top_cr + (mb_x<<3), predCr, 8);*/
-    tmp_ptr = video->intra_pred_top + (mb_x << 4);
-    *((uint32*)tmp_ptr) = *((uint32*)pred);
-    *((uint32*)(tmp_ptr + 4)) = *((uint32*)(pred + 4));
-    *((uint32*)(tmp_ptr + 8)) = *((uint32*)(pred + 8));
-    *((uint32*)(tmp_ptr + 12)) = *((uint32*)(pred + 12));
-    tmp_ptr = video->intra_pred_top_cb + (mb_x << 3);
-    *((uint32*)tmp_ptr) = *((uint32*)predCb);
-    *((uint32*)(tmp_ptr + 4)) = *((uint32*)(predCb + 4));
-    tmp_ptr = video->intra_pred_top_cr + (mb_x << 3);
-    *((uint32*)tmp_ptr) = *((uint32*)predCr);
-    *((uint32*)(tmp_ptr + 4)) = *((uint32*)(predCr + 4));
-
-
-    /* now save last column */
-#ifdef USE_PRED_BLOCK
-    pred = video->pred + 99;    /* last column*/
-#else
-    pred -= ((pitch << 4) - pitch - 15);    /* last column */
-#endif
-    tmp_ptr = video->intra_pred_left;
-    tmp_word = video->intra_pred_topleft;
-    tmp_byte = *(pred);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)tmp_ptr) = tmp_word;
-    tmp_word = *(pred += pitch);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)(tmp_ptr += 4)) = tmp_word;
-    tmp_word = *(pred += pitch);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)(tmp_ptr += 4)) = tmp_word;
-    tmp_word = *(pred += pitch);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(pred += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)(tmp_ptr += 4)) = tmp_word;
-    *(tmp_ptr += 4) = *(pred += pitch);
-
-    /* now for Cb */
-#ifdef USE_PRED_BLOCK
-    predCb = video->pred + 459;
-    pitch = 12;
-#else
-    pitch >>= 1;
-    predCb -= (7 * pitch - 7);
-#endif
-    tmp_ptr = video->intra_pred_left_cb;
-    tmp_word = video->intra_pred_topleft_cb;
-    tmp_byte = *(predCb);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(predCb += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(predCb += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)tmp_ptr) = tmp_word;
-    tmp_word = *(predCb += pitch);
-    tmp_byte = *(predCb += pitch);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(predCb += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(predCb += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)(tmp_ptr += 4)) = tmp_word;
-    *(tmp_ptr += 4) = *(predCb += pitch);
-
-    /* now for Cr */
-#ifdef USE_PRED_BLOCK
-    predCr = video->pred + 603;
-#else
-    predCr -= (7 * pitch - 7);
-#endif
-    tmp_ptr = video->intra_pred_left_cr;
-    tmp_word = video->intra_pred_topleft_cr;
-    tmp_byte = *(predCr);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(predCr += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(predCr += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)tmp_ptr) = tmp_word;
-    tmp_word = *(predCr += pitch);
-    tmp_byte = *(predCr += pitch);
-    tmp_word |= (tmp_byte << 8);
-    tmp_byte = *(predCr += pitch);
-    tmp_word |= (tmp_byte << 16);
-    tmp_byte = *(predCr += pitch);
-    tmp_word |= (tmp_byte << 24);
-    *((uint32*)(tmp_ptr += 4)) = tmp_word;
-    *(tmp_ptr += 4) = *(predCr += pitch);
-
-    return ;
-}
-#endif /* MB_BASED_DEBLOCK */
-
-AVCStatus Intra_4x4(AVCCommonObj *video, int block_x, int block_y, uint8 *comp)
-{
-    AVCMacroblock *currMB = video->currMB;
-    int block_offset;
-    AVCNeighborAvailability availability;
-    int pitch = video->currPic->pitch;
-
-#ifdef USE_PRED_BLOCK
-    block_offset = (block_y * 80) + (block_x << 2);
-#else
-    block_offset = (block_y << 2) * pitch + (block_x << 2);
-#endif
-
-#ifdef MB_BASED_DEBLOCK
-    /* boundary blocks use video->pred_intra_top, pred_intra_left, pred_intra_topleft */
-    if (!block_x)
-    {
-        video->pintra_pred_left = video->intra_pred_left + 1 + (block_y << 2);
-        pitch = 1;
-    }
-    else
-    {
-        video->pintra_pred_left = video->pred_block + block_offset - 1;
-        pitch = video->pred_pitch;
-    }
-
-    if (!block_y)
-    {
-        video->pintra_pred_top = video->intra_pred_top + (block_x << 2) + (video->mb_x << 4);
-    }
-    else
-    {
-        video->pintra_pred_top = video->pred_block + block_offset - video->pred_pitch;
-    }
-
-    if (!block_x)
-    {
-        video->intra_pred_topleft = video->intra_pred_left[block_y<<2];
-    }
-    else if (!block_y)
-    {
-        video->intra_pred_topleft = video->intra_pred_top[(video->mb_x<<4)+(block_x<<2)-1];
-    }
-    else
-    {
-        video->intra_pred_topleft = video->pred_block[block_offset - video->pred_pitch - 1];
-    }
-
-#else
-    /* normal case */
-    video->pintra_pred_top = comp - pitch;
-    video->pintra_pred_left = comp - 1;
-    if (video->mb_y || block_y)
-    {
-        video->intra_pred_topleft = *(comp - pitch - 1);
-    }
-#endif
-
-    switch (currMB->i4Mode[(block_y << 2) + block_x])
-    {
-        case AVC_I4_Vertical:       /* Intra_4x4_Vertical */
-            if (block_y > 0 || video->intraAvailB)/* to prevent out-of-bound access*/
-            {
-                Intra_4x4_Vertical(video,  block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-        case AVC_I4_Horizontal:     /* Intra_4x4_Horizontal */
-            if (block_x || video->intraAvailA)  /* to prevent out-of-bound access */
-            {
-                Intra_4x4_Horizontal(video, pitch, block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-        case AVC_I4_DC:     /* Intra_4x4_DC */
-            availability.left = TRUE;
-            availability.top = TRUE;
-            if (!block_y)
-            { /* check availability up */
-                availability.top = video->intraAvailB ;
-            }
-            if (!block_x)
-            { /* check availability left */
-                availability.left = video->intraAvailA ;
-            }
-            Intra_4x4_DC(video, pitch, block_offset, &availability);
-            break;
-
-        case AVC_I4_Diagonal_Down_Left:     /* Intra_4x4_Diagonal_Down_Left */
-            /* lookup table will be more appropriate for this case  */
-            if (block_y == 0 && !video->intraAvailB)
-            {
-                return AVC_FAIL;
-            }
-
-            availability.top_right = BlkTopRight[(block_y<<2) + block_x];
-
-            if (availability.top_right == 2)
-            {
-                availability.top_right = video->intraAvailB;
-            }
-            else if (availability.top_right == 3)
-            {
-                availability.top_right = video->intraAvailC;
-            }
-
-            Intra_4x4_Down_Left(video, block_offset, &availability);
-            break;
-
-        case AVC_I4_Diagonal_Down_Right:        /* Intra_4x4_Diagonal_Down_Right */
-            if ((block_y && block_x)  /* to prevent out-of-bound access */
-                    || (block_y && video->intraAvailA)
-                    || (block_x && video->intraAvailB)
-                    || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
-            {
-                Intra_4x4_Diagonal_Down_Right(video, pitch, block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-        case AVC_I4_Vertical_Right:     /* Intra_4x4_Vertical_Right */
-            if ((block_y && block_x)  /* to prevent out-of-bound access */
-                    || (block_y && video->intraAvailA)
-                    || (block_x && video->intraAvailB)
-                    || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
-            {
-                Intra_4x4_Diagonal_Vertical_Right(video, pitch, block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-        case AVC_I4_Horizontal_Down:        /* Intra_4x4_Horizontal_Down */
-            if ((block_y && block_x)  /* to prevent out-of-bound access */
-                    || (block_y && video->intraAvailA)
-                    || (block_x && video->intraAvailB)
-                    || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
-            {
-                Intra_4x4_Diagonal_Horizontal_Down(video, pitch, block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-        case AVC_I4_Vertical_Left:      /* Intra_4x4_Vertical_Left */
-            /* lookup table may be more appropriate for this case  */
-            if (block_y == 0 && !video->intraAvailB)
-            {
-                return AVC_FAIL;
-            }
-
-            availability.top_right = BlkTopRight[(block_y<<2) + block_x];
-
-            if (availability.top_right == 2)
-            {
-                availability.top_right = video->intraAvailB;
-            }
-            else if (availability.top_right == 3)
-            {
-                availability.top_right = video->intraAvailC;
-            }
-
-            Intra_4x4_Vertical_Left(video,  block_offset, &availability);
-            break;
-
-        case AVC_I4_Horizontal_Up:      /* Intra_4x4_Horizontal_Up */
-            if (block_x || video->intraAvailA)
-            {
-                Intra_4x4_Horizontal_Up(video, pitch, block_offset);
-            }
-            else
-            {
-                return AVC_FAIL;
-            }
-            break;
-
-
-        default:
-
-            break;
-    }
-
-    return AVC_SUCCESS;
-}
-
-
-/* =============================== BEGIN 4x4
-MODES======================================*/
-void Intra_4x4_Vertical(AVCCommonObj *video,  int block_offset)
-{
-    uint8 *comp_ref = video->pintra_pred_top;
-    uint32 temp;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    /*P = (int) *comp_ref++;
-    Q = (int) *comp_ref++;
-    R = (int) *comp_ref++;
-    S = (int) *comp_ref++;
-    temp = S|(R<<8)|(Q<<16)|(P<<24);*/
-    temp = *((uint32*)comp_ref);
-
-    *((uint32*)pred) =  temp; /* write 4 at a time */
-    pred += pred_pitch;
-    *((uint32*)pred) =  temp;
-    pred += pred_pitch;
-    *((uint32*)pred) =  temp;
-    pred += pred_pitch;
-    *((uint32*)pred) =  temp;
-
-    return ;
-}
-
-void Intra_4x4_Horizontal(AVCCommonObj *video, int pitch, int block_offset)
-{
-    uint8   *comp_ref = video->pintra_pred_left;
-    uint32 temp;
-    int P;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    P = *comp_ref;
-    temp = P | (P << 8);
-    temp = temp | (temp << 16);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    comp_ref += pitch;
-    P = *comp_ref;
-    temp = P | (P << 8);
-    temp = temp | (temp << 16);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    comp_ref += pitch;
-    P = *comp_ref;
-    temp = P | (P << 8);
-    temp = temp | (temp << 16);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    comp_ref += pitch;
-    P = *comp_ref;
-    temp = P | (P << 8);
-    temp = temp | (temp << 16);
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-
-void Intra_4x4_DC(AVCCommonObj *video, int pitch, int block_offset,
-                  AVCNeighborAvailability *availability)
-{
-    uint8   *comp_ref = video->pintra_pred_left;
-    uint32  temp;
-    int DC;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    if (availability->left)
-    {
-        DC = *comp_ref;
-        comp_ref += pitch;
-        DC += *comp_ref;
-        comp_ref += pitch;
-        DC += *comp_ref;
-        comp_ref += pitch;
-        DC += *comp_ref;
-        comp_ref = video->pintra_pred_top;
-
-        if (availability->top)
-        {
-            DC = (comp_ref[0] + comp_ref[1] + comp_ref[2] + comp_ref[3] + DC + 4) >> 3;
-        }
-        else
-        {
-            DC = (DC + 2) >> 2;
-
-        }
-    }
-    else if (availability->top)
-    {
-        comp_ref = video->pintra_pred_top;
-        DC = (comp_ref[0] + comp_ref[1] + comp_ref[2] + comp_ref[3] + 2) >> 2;
-
-    }
-    else
-    {
-        DC = 128;
-    }
-
-    temp = DC | (DC << 8);
-    temp = temp | (temp << 16);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-
-void Intra_4x4_Down_Left(AVCCommonObj *video, int block_offset,
-                         AVCNeighborAvailability *availability)
-{
-    uint8   *comp_refx = video->pintra_pred_top;
-    uint32 temp;
-    int r0, r1, r2, r3, r4, r5, r6, r7;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    r0 = *comp_refx++;
-    r1 = *comp_refx++;
-    r2 = *comp_refx++;
-    r3 = *comp_refx++;
-    if (availability->top_right)
-    {
-        r4 = *comp_refx++;
-        r5 = *comp_refx++;
-        r6 = *comp_refx++;
-        r7 = *comp_refx++;
-    }
-    else
-    {
-        r4 = r3;
-        r5 = r3;
-        r6 = r3;
-        r7 = r3;
-    }
-
-    r0 += (r1 << 1);
-    r0 += r2;
-    r0 += 2;
-    r0 >>= 2;
-    r1 += (r2 << 1);
-    r1 += r3;
-    r1 += 2;
-    r1 >>= 2;
-    r2 += (r3 << 1);
-    r2 += r4;
-    r2 += 2;
-    r2 >>= 2;
-    r3 += (r4 << 1);
-    r3 += r5;
-    r3 += 2;
-    r3 >>= 2;
-    r4 += (r5 << 1);
-    r4 += r6;
-    r4 += 2;
-    r4 >>= 2;
-    r5 += (r6 << 1);
-    r5 += r7;
-    r5 += 2;
-    r5 >>= 2;
-    r6 += (3 * r7);
-    r6 += 2;
-    r6 >>= 2;
-
-    temp = r0 | (r1 << 8);
-    temp |= (r2 << 16);
-    temp |= (r3 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = (temp >> 8) | (r4 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = (temp >> 8) | (r5 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = (temp >> 8) | (r6 << 24);
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-
-void Intra_4x4_Diagonal_Down_Right(AVCCommonObj *video, int pitch, int
-                                   block_offset)
-{
-    uint8 *comp_refx = video->pintra_pred_top;
-    uint8 *comp_refy = video->pintra_pred_left;
-    uint32 temp;
-    int P_x, Q_x, R_x, P_y, Q_y, R_y, D;
-    int x0, x1, x2;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    temp = *((uint32*)comp_refx); /* read 4 bytes */
-    x0 = temp & 0xFF;
-    x1 = (temp >> 8) & 0xFF;
-    x2 = (temp >> 16) & 0xFF;
-
-    Q_x = (x0 + 2 * x1 + x2 + 2) >> 2;
-    R_x = (x1 + 2 * x2 + (temp >> 24) + 2) >> 2;
-
-    x2 = video->intra_pred_topleft; /* re-use x2 instead of y0 */
-    P_x = (x2 + 2 * x0 + x1 + 2) >> 2;
-
-    x1 = *comp_refy;
-    comp_refy += pitch; /* re-use x1 instead of y1 */
-    D = (x0 + 2 * x2 + x1 + 2) >> 2;
-
-    x0 = *comp_refy;
-    comp_refy += pitch; /* re-use x0 instead of y2 */
-    P_y = (x2 + 2 * x1 + x0 + 2) >> 2;
-
-    x2 = *comp_refy;
-    comp_refy += pitch; /* re-use x2 instead of y3 */
-    Q_y = (x1 + 2 * x0 + x2 + 2) >> 2;
-
-    x1 = *comp_refy;                    /* re-use x1 instead of y4 */
-    R_y = (x0 + 2 * x2 + x1 + 2) >> 2;
-
-    /* we can pack these  */
-    temp =  D | (P_x << 8);   //[D   P_x Q_x R_x]
-    //[P_y D   P_x Q_x]
-    temp |= (Q_x << 16); //[Q_y P_y D   P_x]
-    temp |= (R_x << 24);  //[R_y Q_y P_y D  ]
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp =  P_y | (D << 8);
-    temp |= (P_x << 16);
-    temp |= (Q_x << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp =  Q_y | (P_y << 8);
-    temp |= (D << 16);
-    temp |= (P_x << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = R_y | (Q_y << 8);
-    temp |= (P_y << 16);
-    temp |= (D << 24);
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-
-void    Intra_4x4_Diagonal_Vertical_Right(AVCCommonObj *video, int pitch, int block_offset)
-{
-    uint8   *comp_refx = video->pintra_pred_top;
-    uint8   *comp_refy = video->pintra_pred_left;
-    uint32 temp;
-    int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2, D;
-    int x0, x1, x2;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    x0 = *comp_refx++;
-    x1 = *comp_refx++;
-    Q0 = x0 + x1 + 1;
-
-    x2 = *comp_refx++;
-    R0 = x1 + x2 + 1;
-
-    x1 = *comp_refx++; /* reuse x1 instead of x3 */
-    S0 = x2 + x1 + 1;
-
-    x1 = video->intra_pred_topleft; /* reuse x1 instead of y0 */
-    P0 = x1 + x0 + 1;
-
-    x2 = *comp_refy;
-    comp_refy += pitch; /* reuse x2 instead of y1 */
-    D = (x2 + 2 * x1 + x0 + 2) >> 2;
-
-    P1 = (P0 + Q0) >> 2;
-    Q1 = (Q0 + R0) >> 2;
-    R1 = (R0 + S0) >> 2;
-
-    P0 >>= 1;
-    Q0 >>= 1;
-    R0 >>= 1;
-    S0 >>= 1;
-
-    x0 = *comp_refy;
-    comp_refy += pitch; /* reuse x0 instead of y2 */
-    P2 = (x1 + 2 * x2 + x0 + 2) >> 2;
-    x1 = *comp_refy;
-    comp_refy += pitch; /* reuse x1 instead of y3 */
-    Q2 = (x2 + 2 * x0 + x1 + 2) >> 2;
-
-    temp =  P0 | (Q0 << 8);  //[P0 Q0 R0 S0]
-    //[D  P1 Q1 R1]
-    temp |= (R0 << 16); //[P2 P0 Q0 R0]
-    temp |= (S0 << 24); //[Q2 D  P1 Q1]
-    *((uint32*)pred) =  temp;
-    pred += pred_pitch;
-
-    temp =  D | (P1 << 8);
-    temp |= (Q1 << 16);
-    temp |= (R1 << 24);
-    *((uint32*)pred) =  temp;
-    pred += pred_pitch;
-
-    temp = P2 | (P0 << 8);
-    temp |= (Q0 << 16);
-    temp |= (R0 << 24);
-    *((uint32*)pred) =  temp;
-    pred += pred_pitch;
-
-    temp = Q2 | (D << 8);
-    temp |= (P1 << 16);
-    temp |= (Q1 << 24);
-    *((uint32*)pred) =  temp;
-
-    return ;
-}
-
-void Intra_4x4_Diagonal_Horizontal_Down(AVCCommonObj *video, int pitch,
-                                        int block_offset)
-{
-    uint8   *comp_refx = video->pintra_pred_top;
-    uint8   *comp_refy = video->pintra_pred_left;
-    uint32 temp;
-    int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2, D;
-    int x0, x1, x2;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    x0 = *comp_refx++;
-    x1 = *comp_refx++;
-    x2 = *comp_refx++;
-    Q2 = (x0 + 2 * x1 + x2 + 2) >> 2;
-
-    x2 = video->intra_pred_topleft; /* reuse x2 instead of y0 */
-    P2 = (x2 + 2 * x0 + x1 + 2) >> 2;
-
-    x1 = *comp_refy;
-    comp_refy += pitch; /* reuse x1 instead of y1 */
-    D = (x1 + 2 * x2 + x0 + 2) >> 2;
-    P0 = x2 + x1 + 1;
-
-    x0 = *comp_refy;
-    comp_refy += pitch; /* reuse x0 instead of y2 */
-    Q0 = x1 + x0 + 1;
-
-    x1 = *comp_refy;
-    comp_refy += pitch; /* reuse x1 instead of y3 */
-    R0 = x0 + x1 + 1;
-
-    x2 = *comp_refy;    /* reuse x2 instead of y4 */
-    S0 = x1 + x2 + 1;
-
-    P1 = (P0 + Q0) >> 2;
-    Q1 = (Q0 + R0) >> 2;
-    R1 = (R0 + S0) >> 2;
-
-    P0 >>= 1;
-    Q0 >>= 1;
-    R0 >>= 1;
-    S0 >>= 1;
-
-
-    /* we can pack these  */
-    temp = P0 | (D << 8);   //[P0 D  P2 Q2]
-    //[Q0 P1 P0 D ]
-    temp |= (P2 << 16);  //[R0 Q1 Q0 P1]
-    temp |= (Q2 << 24); //[S0 R1 R0 Q1]
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = Q0 | (P1 << 8);
-    temp |= (P0 << 16);
-    temp |= (D << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = R0 | (Q1 << 8);
-    temp |= (Q0 << 16);
-    temp |= (P1 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = S0 | (R1 << 8);
-    temp |= (R0 << 16);
-    temp |= (Q1 << 24);
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-
-void Intra_4x4_Vertical_Left(AVCCommonObj *video, int block_offset, AVCNeighborAvailability *availability)
-{
-    uint8   *comp_refx = video->pintra_pred_top;
-    uint32 temp1, temp2;
-    int x0, x1, x2, x3, x4, x5, x6;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    x0 = *comp_refx++;
-    x1 = *comp_refx++;
-    x2 = *comp_refx++;
-    x3 = *comp_refx++;
-    if (availability->top_right)
-    {
-        x4 = *comp_refx++;
-        x5 = *comp_refx++;
-        x6 = *comp_refx++;
-    }
-    else
-    {
-        x4 = x3;
-        x5 = x3;
-        x6 = x3;
-    }
-
-    x0 += x1 + 1;
-    x1 += x2 + 1;
-    x2 += x3 + 1;
-    x3 += x4 + 1;
-    x4 += x5 + 1;
-    x5 += x6 + 1;
-
-    temp1 = (x0 >> 1);
-    temp1 |= ((x1 >> 1) << 8);
-    temp1 |= ((x2 >> 1) << 16);
-    temp1 |= ((x3 >> 1) << 24);
-
-    *((uint32*)pred) = temp1;
-    pred += pred_pitch;
-
-    temp2 = ((x0 + x1) >> 2);
-    temp2 |= (((x1 + x2) >> 2) << 8);
-    temp2 |= (((x2 + x3) >> 2) << 16);
-    temp2 |= (((x3 + x4) >> 2) << 24);
-
-    *((uint32*)pred) = temp2;
-    pred += pred_pitch;
-
-    temp1 = (temp1 >> 8) | ((x4 >> 1) << 24);   /* rotate out old value */
-    *((uint32*)pred) = temp1;
-    pred += pred_pitch;
-
-    temp2 = (temp2 >> 8) | (((x4 + x5) >> 2) << 24); /* rotate out old value */
-    *((uint32*)pred) = temp2;
-    pred += pred_pitch;
-
-    return ;
-}
-
-void Intra_4x4_Horizontal_Up(AVCCommonObj *video, int pitch, int block_offset)
-{
-    uint8   *comp_refy = video->pintra_pred_left;
-    uint32 temp;
-    int Q0, R0, Q1, D0, D1, P0, P1;
-    int y0, y1, y2, y3;
-    uint8 *pred = video->pred_block + block_offset;
-    int pred_pitch = video->pred_pitch;
-
-    y0 = *comp_refy;
-    comp_refy += pitch;
-    y1 = *comp_refy;
-    comp_refy += pitch;
-    y2 = *comp_refy;
-    comp_refy += pitch;
-    y3 = *comp_refy;
-
-    Q0 = (y1 + y2 + 1) >> 1;
-    Q1 = (y1 + (y2 << 1) + y3 + 2) >> 2;
-    P0 = ((y0 + y1 + 1) >> 1);
-    P1 = ((y0 + (y1 << 1) + y2 + 2) >> 2);
-
-    temp = P0 | (P1 << 8);      // [P0 P1 Q0 Q1]
-    temp |= (Q0 << 16);     // [Q0 Q1 R0 DO]
-    temp |= (Q1 << 24);     // [R0 D0 D1 D1]
-    *((uint32*)pred) = temp;      // [D1 D1 D1 D1]
-    pred += pred_pitch;
-
-    D0 = (y2 + 3 * y3 + 2) >> 2;
-    R0 = (y2 + y3 + 1) >> 1;
-
-    temp = Q0 | (Q1 << 8);
-    temp |= (R0 << 16);
-    temp |= (D0 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    D1 = y3;
-
-    temp = R0 | (D0 << 8);
-    temp |= (D1 << 16);
-    temp |= (D1 << 24);
-    *((uint32*)pred) = temp;
-    pred += pred_pitch;
-
-    temp = D1 | (D1 << 8);
-    temp |= (temp << 16);
-    *((uint32*)pred) = temp;
-
-    return ;
-}
-/* =============================== END 4x4 MODES======================================*/
-void  Intra_16x16_Vertical(AVCCommonObj *video)
-{
-    int i;
-    uint32 temp1, temp2, temp3, temp4;
-    uint8   *comp_ref = video->pintra_pred_top;
-    uint8 *pred = video->pred_block;
-    int pred_pitch = video->pred_pitch;
-
-    temp1 = *((uint32*)comp_ref);
-    comp_ref += 4;
-
-    temp2 = *((uint32*)comp_ref);
-    comp_ref += 4;
-
-    temp3 = *((uint32*)comp_ref);
-    comp_ref += 4;
-
-    temp4 = *((uint32*)comp_ref);
-    comp_ref += 4;
-
-    i = 16;
-    while (i > 0)
-    {
-        *((uint32*)pred) = temp1;
-        *((uint32*)(pred + 4)) = temp2;
-        *((uint32*)(pred + 8)) = temp3;
-        *((uint32*)(pred + 12)) = temp4;
-        pred += pred_pitch;
-        i--;
-    }
-
-    return ;
-}
-
-void Intra_16x16_Horizontal(AVCCommonObj *video, int pitch)
-{
-    int i;
-    uint32 temp;
-    uint8 *comp_ref = video->pintra_pred_left;
-    uint8 *pred = video->pred_block;
-    int pred_pitch = video->pred_pitch;
-
-    for (i = 0; i < 16; i++)
-    {
-        temp = *comp_ref;
-        temp |= (temp << 8);
-        temp |= (temp << 16);
-        *((uint32*)pred) = temp;
-        *((uint32*)(pred + 4)) = temp;
-        *((uint32*)(pred + 8)) = temp;
-        *((uint32*)(pred + 12)) = temp;
-        pred += pred_pitch;
-        comp_ref += pitch;
-    }
-}
-
-
-void  Intra_16x16_DC(AVCCommonObj *video, int pitch)
-{
-    int i;
-    uint32 temp, temp2;
-    uint8 *comp_ref_x = video->pintra_pred_top;
-    uint8 *comp_ref_y = video->pintra_pred_left;
-    int sum = 0;
-    uint8 *pred = video->pred_block;
-    int pred_pitch = video->pred_pitch;
-
-    if (video->intraAvailB)
-    {
-        temp = *((uint32*)comp_ref_x);
-        comp_ref_x += 4;
-        temp2 = (temp >> 8) & 0xFF00FF;
-        temp &= 0xFF00FF;
-        temp += temp2;
-        sum = temp + (temp >> 16);
-        temp = *((uint32*)comp_ref_x);
-        comp_ref_x += 4;
-        temp2 = (temp >> 8) & 0xFF00FF;
-        temp &= 0xFF00FF;
-        temp += temp2;
-        sum += temp + (temp >> 16);
-        temp = *((uint32*)comp_ref_x);
-        comp_ref_x += 4;
-        temp2 = (temp >> 8) & 0xFF00FF;
-        temp &= 0xFF00FF;
-        temp += temp2;
-        sum += temp + (temp >> 16);
-        temp = *((uint32*)comp_ref_x);
-        comp_ref_x += 4;
-        temp2 = (temp >> 8) & 0xFF00FF;
-        temp &= 0xFF00FF;
-        temp += temp2;
-        sum += temp + (temp >> 16);
-        sum &= 0xFFFF;
-
-        if (video->intraAvailA)
-        {
-            for (i = 0; i < 16; i++)
-            {
-                sum += (*comp_ref_y);
-                comp_ref_y += pitch;
-            }
-            sum = (sum + 16) >> 5;
-        }
-        else
-        {
-            sum = (sum + 8) >> 4;
-        }
-    }
-    else if (video->intraAvailA)
-    {
-        for (i = 0; i < 16; i++)
-        {
-            sum += *comp_ref_y;
-            comp_ref_y += pitch;
-        }
-        sum = (sum + 8) >> 4;
-    }
-    else
-    {
-        sum = 128;
-    }
-
-    temp = sum | (sum << 8);
-    temp |= (temp << 16);
-
-    for (i = 0; i < 16; i++)
-    {
-        *((uint32*)pred) = temp;
-        *((uint32*)(pred + 4)) = temp;
-        *((uint32*)(pred + 8)) = temp;
-        *((uint32*)(pred + 12)) = temp;
-        pred += pred_pitch;
-    }
-
-}
-
-void Intra_16x16_Plane(AVCCommonObj *video, int pitch)
-{
-    int i, a_16, b, c, factor_c;
-    uint8 *comp_ref_x = video->pintra_pred_top;
-    uint8 *comp_ref_y = video->pintra_pred_left;
-    uint8 *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
-    int H = 0, V = 0 , tmp;
-    uint8 *pred = video->pred_block;
-    uint32 temp;
-    uint8 byte1, byte2, byte3;
-    int value;
-    int pred_pitch = video->pred_pitch;
-
-    comp_ref_x0 = comp_ref_x + 8;
-    comp_ref_x1 = comp_ref_x + 6;
-    comp_ref_y0 = comp_ref_y + (pitch << 3);
-    comp_ref_y1 = comp_ref_y + 6 * pitch;
-
-    for (i = 1; i < 8; i++)
-    {
-        H += i * (*comp_ref_x0++ - *comp_ref_x1--);
-        V += i * (*comp_ref_y0 - *comp_ref_y1);
-        comp_ref_y0 += pitch;
-        comp_ref_y1 -= pitch;
-    }
-
-    H += i * (*comp_ref_x0++ - video->intra_pred_topleft);
-    V += i * (*comp_ref_y0 - *comp_ref_y1);
-
-
-    a_16 = ((*(comp_ref_x + 15) + *(comp_ref_y + 15 * pitch)) << 4) + 16;;
-    b = (5 * H + 32) >> 6;
-    c = (5 * V + 32) >> 6;
-
-    tmp = 0;
-
-    for (i = 0; i < 16; i++)
-    {
-        factor_c = a_16 + c * (tmp++ - 7);
-
-        factor_c -= 7 * b;
-
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte1 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte2 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte3 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        temp = byte1 | (byte2 << 8);
-        temp |= (byte3 << 16);
-        temp |= (value << 24);
-        *((uint32*)pred) = temp;
-
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte1 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte2 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte3 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        temp = byte1 | (byte2 << 8);
-        temp |= (byte3 << 16);
-        temp |= (value << 24);
-        *((uint32*)(pred + 4)) = temp;
-
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte1 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte2 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte3 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        temp = byte1 | (byte2 << 8);
-        temp |= (byte3 << 16);
-        temp |= (value << 24);
-        *((uint32*)(pred + 8)) = temp;
-
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte1 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte2 = value;
-        value = factor_c >> 5;
-        factor_c += b;
-        CLIP_RESULT(value)
-        byte3 = value;
-        value = factor_c >> 5;
-        CLIP_RESULT(value)
-        temp = byte1 | (byte2 << 8);
-        temp |= (byte3 << 16);
-        temp |= (value << 24);
-        *((uint32*)(pred + 12)) = temp;
-        pred += pred_pitch;
-    }
-}
-
-/************** Chroma intra prediction *********************/
-
-void Intra_Chroma_DC(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
-{
-    int i;
-    uint32 temp, temp2, pred_a, pred_b;
-    uint8 *comp_ref_x, *comp_ref_y;
-    uint8 *comp_ref_cb_x = video->pintra_pred_top_cb;
-    uint8 *comp_ref_cb_y = video->pintra_pred_left_cb;
-    uint8 *comp_ref_cr_x = video->pintra_pred_top_cr;
-    uint8 *comp_ref_cr_y = video->pintra_pred_left_cr;
-    int  component, j;
-    int  sum_x0, sum_x1, sum_y0, sum_y1;
-    int pred_0[2], pred_1[2], pred_2[2], pred_3[2];
-    int pred_pitch = video->pred_pitch;
-    uint8 *pred;
-
-    if (video->intraAvailB & video->intraAvailA)
-    {
-        comp_ref_x = comp_ref_cb_x;
-        comp_ref_y = comp_ref_cb_y;
-        for (i = 0; i < 2; i++)
-        {
-            temp = *((uint32*)comp_ref_x);
-            comp_ref_x += 4;
-            temp2 = (temp >> 8) & 0xFF00FF;
-            temp &= 0xFF00FF;
-            temp += temp2;
-            temp += (temp >> 16);
-            sum_x0 = temp & 0xFFFF;
-
-            temp = *((uint32*)comp_ref_x);
-            temp2 = (temp >> 8) & 0xFF00FF;
-            temp &= 0xFF00FF;
-            temp += temp2;
-            temp += (temp >> 16);
-            sum_x1 = temp & 0xFFFF;
-
-            pred_1[i] = (sum_x1 + 2) >> 2;
-
-            sum_y0 = *comp_ref_y;
-            sum_y0 += *(comp_ref_y += pitch);
-            sum_y0 += *(comp_ref_y += pitch);
-            sum_y0 += *(comp_ref_y += pitch);
-
-            sum_y1 = *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-
-            pred_2[i] = (sum_y1 + 2) >> 2;
-
-            pred_0[i] = (sum_y0 + sum_x0 + 4) >> 3;
-            pred_3[i] = (sum_y1 + sum_x1 + 4) >> 3;
-
-            comp_ref_x = comp_ref_cr_x;
-            comp_ref_y = comp_ref_cr_y;
-        }
-    }
-
-    else if (video->intraAvailA)
-    {
-        comp_ref_y = comp_ref_cb_y;
-        for (i = 0; i < 2; i++)
-        {
-            sum_y0 = *comp_ref_y;
-            sum_y0 += *(comp_ref_y += pitch);
-            sum_y0 += *(comp_ref_y += pitch);
-            sum_y0 += *(comp_ref_y += pitch);
-
-            sum_y1 = *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-            sum_y1 += *(comp_ref_y += pitch);
-
-            pred_0[i] = pred_1[i] = (sum_y0 + 2) >> 2;
-            pred_2[i] = pred_3[i] = (sum_y1 + 2) >> 2;
-            comp_ref_y = comp_ref_cr_y;
-        }
-    }
-    else if (video->intraAvailB)
-    {
-        comp_ref_x = comp_ref_cb_x;
-        for (i = 0; i < 2; i++)
-        {
-            temp = *((uint32*)comp_ref_x);
-            comp_ref_x += 4;
-            temp2 = (temp >> 8) & 0xFF00FF;
-            temp &= 0xFF00FF;
-            temp += temp2;
-            temp += (temp >> 16);
-            sum_x0 = temp & 0xFFFF;
-
-            temp = *((uint32*)comp_ref_x);
-            temp2 = (temp >> 8) & 0xFF00FF;
-            temp &= 0xFF00FF;
-            temp += temp2;
-            temp += (temp >> 16);
-            sum_x1 = temp & 0xFFFF;
-
-            pred_0[i] = pred_2[i] = (sum_x0 + 2) >> 2;
-            pred_1[i] = pred_3[i] = (sum_x1 + 2) >> 2;
-            comp_ref_x = comp_ref_cr_x;
-        }
-    }
-    else
-    {
-        pred_0[0] = pred_0[1] = pred_1[0] = pred_1[1] =
-                                                pred_2[0] = pred_2[1] = pred_3[0] = pred_3[1] = 128;
-    }
-
-    pred = predCb;
-    for (component = 0; component < 2; component++)
-    {
-        pred_a = pred_0[component];
-        pred_b = pred_1[component];
-        pred_a |= (pred_a << 8);
-        pred_a |= (pred_a << 16);
-        pred_b |= (pred_b << 8);
-        pred_b |= (pred_b << 16);
-
-        for (i = 4; i < 6; i++)
-        {
-            for (j = 0; j < 4; j++) /* 4 lines */
-            {
-                *((uint32*)pred) = pred_a;
-                *((uint32*)(pred + 4)) = pred_b;
-                pred += pred_pitch; /* move to the next line */
-            }
-            pred_a = pred_2[component];
-            pred_b = pred_3[component];
-            pred_a |= (pred_a << 8);
-            pred_a |= (pred_a << 16);
-            pred_b |= (pred_b << 8);
-            pred_b |= (pred_b << 16);
-        }
-        pred = predCr; /* point to cr */
-    }
-}
-
-void  Intra_Chroma_Horizontal(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
-{
-    int i;
-    uint32 temp;
-    uint8   *comp_ref_cb_y = video->pintra_pred_left_cb;
-    uint8   *comp_ref_cr_y = video->pintra_pred_left_cr;
-    uint8  *comp;
-    int component, j;
-    int     pred_pitch = video->pred_pitch;
-    uint8   *pred;
-
-    comp = comp_ref_cb_y;
-    pred = predCb;
-    for (component = 0; component < 2; component++)
-    {
-        for (i = 4; i < 6; i++)
-        {
-            for (j = 0; j < 4; j++)
-            {
-                temp = *comp;
-                comp += pitch;
-                temp |= (temp << 8);
-                temp |= (temp << 16);
-                *((uint32*)pred) = temp;
-                *((uint32*)(pred + 4)) = temp;
-                pred += pred_pitch;
-            }
-        }
-        comp = comp_ref_cr_y;
-        pred = predCr; /* point to cr */
-    }
-
-}
-
-void  Intra_Chroma_Vertical(AVCCommonObj *video, uint8 *predCb, uint8 *predCr)
-{
-    uint32  temp1, temp2;
-    uint8   *comp_ref_cb_x = video->pintra_pred_top_cb;
-    uint8   *comp_ref_cr_x = video->pintra_pred_top_cr;
-    uint8   *comp_ref;
-    int     component, j;
-    int     pred_pitch = video->pred_pitch;
-    uint8   *pred;
-
-    comp_ref = comp_ref_cb_x;
-    pred = predCb;
-    for (component = 0; component < 2; component++)
-    {
-        temp1 = *((uint32*)comp_ref);
-        temp2 = *((uint32*)(comp_ref + 4));
-        for (j = 0; j < 8; j++)
-        {
-            *((uint32*)pred) = temp1;
-            *((uint32*)(pred + 4)) = temp2;
-            pred += pred_pitch;
-        }
-        comp_ref = comp_ref_cr_x;
-        pred = predCr; /* point to cr */
-    }
-
-}
-
-void  Intra_Chroma_Plane(AVCCommonObj *video, int pitch, uint8 *predCb, uint8 *predCr)
-{
-    int i;
-    int a_16_C[2], b_C[2], c_C[2], a_16, b, c, factor_c;
-    uint8 *comp_ref_x, *comp_ref_y, *comp_ref_x0, *comp_ref_x1,  *comp_ref_y0, *comp_ref_y1;
-    int component, j;
-    int H, V, tmp;
-    uint32 temp;
-    uint8 byte1, byte2, byte3;
-    int value;
-    uint8 topleft;
-    int pred_pitch = video->pred_pitch;
-    uint8 *pred;
-
-    comp_ref_x = video->pintra_pred_top_cb;
-    comp_ref_y = video->pintra_pred_left_cb;
-    topleft = video->intra_pred_topleft_cb;
-
-    for (component = 0; component < 2; component++)
-    {
-        H = V = 0;
-        comp_ref_x0 = comp_ref_x + 4;
-        comp_ref_x1 = comp_ref_x + 2;
-        comp_ref_y0 = comp_ref_y + (pitch << 2);
-        comp_ref_y1 = comp_ref_y + (pitch << 1);
-        for (i = 1; i < 4; i++)
-        {
-            H += i * (*comp_ref_x0++ - *comp_ref_x1--);
-            V += i * (*comp_ref_y0 - *comp_ref_y1);
-            comp_ref_y0 += pitch;
-            comp_ref_y1 -= pitch;
-        }
-        H += i * (*comp_ref_x0++ - topleft);
-        V += i * (*comp_ref_y0 - *comp_ref_y1);
-
-        a_16_C[component] = ((*(comp_ref_x + 7) + *(comp_ref_y + 7 * pitch)) << 4) + 16;
-        b_C[component] = (17 * H + 16) >> 5;
-        c_C[component] = (17 * V + 16) >> 5;
-
-        comp_ref_x = video->pintra_pred_top_cr;
-        comp_ref_y = video->pintra_pred_left_cr;
-        topleft = video->intra_pred_topleft_cr;
-    }
-
-    pred = predCb;
-    for (component = 0; component < 2; component++)
-    {
-        a_16 = a_16_C[component];
-        b = b_C[component];
-        c = c_C[component];
-        tmp = 0;
-        for (i = 4; i < 6; i++)
-        {
-            for (j = 0; j < 4; j++)
-            {
-                factor_c = a_16 + c * (tmp++ - 3);
-
-                factor_c -= 3 * b;
-
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte1 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte2 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte3 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                temp = byte1 | (byte2 << 8);
-                temp |= (byte3 << 16);
-                temp |= (value << 24);
-                *((uint32*)pred) = temp;
-
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte1 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte2 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                byte3 = value;
-                value = factor_c >> 5;
-                factor_c += b;
-                CLIP_RESULT(value)
-                temp = byte1 | (byte2 << 8);
-                temp |= (byte3 << 16);
-                temp |= (value << 24);
-                *((uint32*)(pred + 4)) = temp;
-                pred += pred_pitch;
-            }
-        }
-        pred = predCr; /* point to cr */
-    }
-}
-
diff --git a/media/libstagefright/codecs/avc/dec/src/residual.cpp b/media/libstagefright/codecs/avc/dec/src/residual.cpp
deleted file mode 100644
index c68550d..0000000
--- a/media/libstagefright/codecs/avc/dec/src/residual.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 <string.h>
-
-#include "avcdec_lib.h"
-#include "avcdec_bitstream.h"
-
-AVCDec_Status DecodeIntraPCM(AVCCommonObj *video, AVCDecBitstream *stream)
-{
-    AVCDec_Status status;
-    int j;
-    int mb_x, mb_y, offset1;
-    uint8 *pDst;
-    uint32 byte0, byte1;
-    int pitch;
-
-    mb_x = video->mb_x;
-    mb_y = video->mb_y;
-
-#ifdef USE_PRED_BLOCK
-    pDst = video->pred_block + 84;
-    pitch = 20;
-#else
-    offset1 = (mb_x << 4) + (mb_y << 4) * video->PicWidthInSamplesL;
-    pDst = video->currPic->Sl + offset1;
-    pitch = video->currPic->pitch;
-#endif
-
-    /* at this point bitstream is byte-aligned */
-    j = 16;
-    while (j > 0)
-    {
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)pDst) = byte0;
-
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)(pDst + 4)) = byte0;
-
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)(pDst + 8)) = byte0;
-
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)(pDst + 12)) = byte0;
-        j--;
-        pDst += pitch;
-
-        if (status != AVCDEC_SUCCESS)  /* check only once per line */
-            return status;
-    }
-
-#ifdef USE_PRED_BLOCK
-    pDst = video->pred_block + 452;
-    pitch = 12;
-#else
-    offset1 = (offset1 >> 2) + (mb_x << 2);
-    pDst = video->currPic->Scb + offset1;
-    pitch >>= 1;
-#endif
-
-    j = 8;
-    while (j > 0)
-    {
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)pDst) = byte0;
-
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)(pDst + 4)) = byte0;
-
-        j--;
-        pDst += pitch;
-
-        if (status != AVCDEC_SUCCESS)  /* check only once per line */
-            return status;
-    }
-
-#ifdef USE_PRED_BLOCK
-    pDst = video->pred_block + 596;
-    pitch = 12;
-#else
-    pDst = video->currPic->Scr + offset1;
-#endif
-    j = 8;
-    while (j > 0)
-    {
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)pDst) = byte0;
-
-        status = BitstreamReadBits(stream, 8, (uint*) & byte0);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 8);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 16);
-        status = BitstreamReadBits(stream, 8, (uint*) & byte1);
-        byte0 |= (byte1 << 24);
-        *((uint32*)(pDst + 4)) = byte0;
-
-        j--;
-        pDst += pitch;
-
-        if (status != AVCDEC_SUCCESS)  /* check only once per line */
-            return status;
-    }
-
-#ifdef MB_BASED_DEBLOCK
-    SaveNeighborForIntraPred(video, offset1);
-#endif
-
-    return AVCDEC_SUCCESS;
-}
-
-
-
-/* see subclause 7.3.5.3 and readCBPandCoeffsFromNAL() in JM*/
-AVCDec_Status residual(AVCDecObject *decvid, AVCMacroblock *currMB)
-{
-    AVCCommonObj *video = decvid->common;
-    int16 *block;
-    int level[16], run[16], numcoeff; /* output from residual_block_cavlc */
-    int block_x, i, j, k, idx, iCbCr;
-    int mbPartIdx, subMbPartIdx, mbPartIdx_X, mbPartIdx_Y;
-    int nC, maxNumCoeff = 16;
-    int coeffNum, start_scan = 0;
-    uint8 *zz_scan;
-    int Rq, Qq;
-    uint32 cbp4x4 = 0;
-
-    /* in 8.5.4, it only says if it's field macroblock. */
-
-    zz_scan = (uint8*) ZZ_SCAN_BLOCK;
-
-
-    /* see 8.5.8 for the initialization of these values */
-    Qq = video->QPy_div_6;
-    Rq = video->QPy_mod_6;
-
-    memset(video->block, 0, sizeof(int16)*NUM_PIXELS_IN_MB);
-
-    if (currMB->mbMode == AVC_I16)
-    {
-        nC = predict_nnz(video, 0, 0);
-        decvid->residual_block(decvid, nC, 16, level, run, &numcoeff);
-        /* then performs zigzag and transform */
-        block = video->block;
-        coeffNum = -1;
-        for (i = numcoeff - 1; i >= 0; i--)
-        {
-            coeffNum += run[i] + 1;
-            if (coeffNum > 15)
-            {
-                return AVCDEC_FAIL;
-            }
-            idx = zz_scan[coeffNum] << 2;
-            /*          idx = ((idx>>2)<<6) + ((idx&3)<<2); */
-            block[idx] = level[i];
-        }
-
-        /* inverse transform on Intra16x16DCLevel */
-        if (numcoeff)
-        {
-            Intra16DCTrans(block, Qq, Rq);
-            cbp4x4 = 0xFFFF;
-        }
-        maxNumCoeff = 15;
-        start_scan = 1;
-    }
-
-    memset(currMB->nz_coeff, 0, sizeof(uint8)*24);
-
-    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
-    {
-        mbPartIdx_X = (mbPartIdx & 1) << 1;
-        mbPartIdx_Y = mbPartIdx & -2;
-
-        if (currMB->CBP&(1 << mbPartIdx))
-        {
-            for (subMbPartIdx = 0; subMbPartIdx < 4; subMbPartIdx++)
-            {
-                i = mbPartIdx_X + (subMbPartIdx & 1);  // check this
-                j = mbPartIdx_Y + (subMbPartIdx >> 1);
-                block = video->block + (j << 6) + (i << 2);  //
-                nC = predict_nnz(video, i, j);
-                decvid->residual_block(decvid, nC, maxNumCoeff, level, run, &numcoeff);
-
-                /* convert to raster scan and quantize*/
-                /* Note: for P mb in SP slice and SI mb in SI slice,
-                 the quantization cannot be done here.
-                 block[idx] should be assigned with level[k].
-                itrans will be done after the prediction.
-                There will be transformation on the predicted value,
-                then addition with block[idx], then this quantization
-                and transform.*/
-
-                coeffNum = -1 + start_scan;
-                for (k = numcoeff - 1; k >= 0; k--)
-                {
-                    coeffNum += run[k] + 1;
-                    if (coeffNum > 15)
-                    {
-                        return AVCDEC_FAIL;
-                    }
-                    idx = zz_scan[coeffNum];
-                    block[idx] = (level[k] * dequant_coefres[Rq][coeffNum]) << Qq ;
-                }
-
-                currMB->nz_coeff[(j<<2)+i] = numcoeff;
-                if (numcoeff)
-                {
-                    cbp4x4 |= (1 << ((j << 2) + i));
-                }
-            }
-        }
-    }
-
-    Qq = video->QPc_div_6;
-    Rq = video->QPc_mod_6;
-
-    if (currMB->CBP & (3 << 4)) /* chroma DC residual present */
-    {
-        for (iCbCr = 0; iCbCr < 2; iCbCr++)
-        {
-            decvid->residual_block(decvid, -1, 4, level, run, &numcoeff);
-            block = video->block + 256 + (iCbCr << 3);
-            coeffNum = -1;
-            for (i = numcoeff - 1; i >= 0; i--)
-            {
-                coeffNum += run[i] + 1;
-                if (coeffNum > 3)
-                {
-                    return AVCDEC_FAIL;
-                }
-                block[(coeffNum>>1)*64 + (coeffNum&1)*4] = level[i];
-            }
-            /* inverse transform on chroma DC */
-            /* for P in SP and SI in SI, this function can't be done here,
-            must do prediction transform/quant first. */
-            if (numcoeff)
-            {
-                ChromaDCTrans(block, Qq, Rq);
-                cbp4x4 |= (iCbCr ? 0xcc0000 : 0x330000);
-            }
-        }
-    }
-
-    if (currMB->CBP & (2 << 4))
-    {
-        for (block_x = 0; block_x < 4; block_x += 2) /* for iCbCr */
-        {
-            for (j = 4; j < 6; j++)  /* for each block inside Cb or Cr */
-            {
-                for (i = block_x; i < block_x + 2; i++)
-                {
-
-                    block = video->block + (j << 6) + (i << 2);
-
-                    nC = predict_nnz_chroma(video, i, j);
-                    decvid->residual_block(decvid, nC, 15, level, run, &numcoeff);
-
-                    /* convert to raster scan and quantize */
-                    /* for P MB in SP slice and SI MB in SI slice,
-                       the dequant and transform cannot be done here.
-                       It needs the prediction values. */
-                    coeffNum = 0;
-                    for (k = numcoeff - 1; k >= 0; k--)
-                    {
-                        coeffNum += run[k] + 1;
-                        if (coeffNum > 15)
-                        {
-                            return AVCDEC_FAIL;
-                        }
-                        idx = zz_scan[coeffNum];
-                        block[idx] = (level[k] * dequant_coefres[Rq][coeffNum]) << Qq;
-                    }
-
-
-                    /* then transform */
-                    //              itrans(block); /* transform */
-                    currMB->nz_coeff[(j<<2)+i] = numcoeff;    //
-                    if (numcoeff)
-                    {
-                        cbp4x4 |= (1 << ((j << 2) + i));
-                    }
-                }
-
-            }
-        }
-    }
-
-    video->cbp4x4 = cbp4x4;
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see subclause 7.3.5.3.1 and 9.2 and readCoeff4x4_CAVLC() in JM */
-AVCDec_Status residual_block_cavlc(AVCDecObject *decvid, int nC, int maxNumCoeff,
-                                   int *level, int *run, int *numcoeff)
-{
-    int i, j;
-    int TrailingOnes, TotalCoeff;
-    AVCDecBitstream *stream = decvid->bitstream;
-    int suffixLength;
-    uint trailing_ones_sign_flag, level_prefix, level_suffix;
-    int levelCode, levelSuffixSize, zerosLeft;
-    int run_before;
-
-
-    if (nC >= 0)
-    {
-        ce_TotalCoeffTrailingOnes(stream, &TrailingOnes, &TotalCoeff, nC);
-    }
-    else
-    {
-        ce_TotalCoeffTrailingOnesChromaDC(stream, &TrailingOnes, &TotalCoeff);
-    }
-
-    *numcoeff = TotalCoeff;
-
-    /* This part is done quite differently in ReadCoef4x4_CAVLC() */
-    if (TotalCoeff == 0)
-    {
-        return AVCDEC_SUCCESS;
-    }
-
-    if (TrailingOnes) /* keep reading the sign of those trailing ones */
-    {
-        /* instead of reading one bit at a time, read the whole thing at once */
-        BitstreamReadBits(stream, TrailingOnes, &trailing_ones_sign_flag);
-        trailing_ones_sign_flag <<= 1;
-        for (i = 0; i < TrailingOnes; i++)
-        {
-            level[i] = 1 - ((trailing_ones_sign_flag >> (TrailingOnes - i - 1)) & 2);
-        }
-    }
-
-    i = TrailingOnes;
-    suffixLength = 1;
-    if (TotalCoeff > TrailingOnes)
-    {
-        ce_LevelPrefix(stream, &level_prefix);
-        if (TotalCoeff < 11 || TrailingOnes == 3)
-        {
-            if (level_prefix < 14)
-            {
-//              levelSuffixSize = 0;
-                levelCode = level_prefix;
-            }
-            else if (level_prefix == 14)
-            {
-//              levelSuffixSize = 4;
-                BitstreamReadBits(stream, 4, &level_suffix);
-                levelCode = 14 + level_suffix;
-            }
-            else /* if (level_prefix == 15) */
-            {
-//              levelSuffixSize = 12;
-                BitstreamReadBits(stream, 12, &level_suffix);
-                levelCode = 30 + level_suffix;
-            }
-        }
-        else
-        {
-            /*              suffixLength = 1; */
-            if (level_prefix < 15)
-            {
-                levelSuffixSize = suffixLength;
-            }
-            else
-            {
-                levelSuffixSize = 12;
-            }
-            BitstreamReadBits(stream, levelSuffixSize, &level_suffix);
-
-            levelCode = (level_prefix << 1) + level_suffix;
-        }
-
-        if (TrailingOnes < 3)
-        {
-            levelCode += 2;
-        }
-
-        level[i] = (levelCode + 2) >> 1;
-        if (level[i] > 3)
-        {
-            suffixLength = 2;
-        }
-
-        if (levelCode & 1)
-        {
-            level[i] = -level[i];
-        }
-        i++;
-
-    }
-
-    for (j = TotalCoeff - i; j > 0 ; j--)
-    {
-        ce_LevelPrefix(stream, &level_prefix);
-        if (level_prefix < 15)
-        {
-            levelSuffixSize = suffixLength;
-        }
-        else
-        {
-            levelSuffixSize = 12;
-        }
-        BitstreamReadBits(stream, levelSuffixSize, &level_suffix);
-
-        levelCode = (level_prefix << suffixLength) + level_suffix;
-        level[i] = (levelCode >> 1) + 1;
-        if (level[i] > (3 << (suffixLength - 1)) && suffixLength < 6)
-        {
-            suffixLength++;
-        }
-        if (levelCode & 1)
-        {
-            level[i] = -level[i];
-        }
-        i++;
-    }
-
-
-    if (TotalCoeff < maxNumCoeff)
-    {
-        if (nC >= 0)
-        {
-            ce_TotalZeros(stream, &zerosLeft, TotalCoeff);
-        }
-        else
-        {
-            ce_TotalZerosChromaDC(stream, &zerosLeft, TotalCoeff);
-        }
-    }
-    else
-    {
-        zerosLeft = 0;
-    }
-
-    for (i = 0; i < TotalCoeff - 1; i++)
-    {
-        if (zerosLeft > 0)
-        {
-            ce_RunBefore(stream, &run_before, zerosLeft);
-            run[i] = run_before;
-        }
-        else
-        {
-            run[i] = 0;
-            zerosLeft = 0; // could be negative under error conditions
-        }
-
-        zerosLeft = zerosLeft - run[i];
-    }
-
-    if (zerosLeft < 0)
-    {
-        zerosLeft = 0;
-//      return AVCDEC_FAIL;
-    }
-
-    run[TotalCoeff-1] = zerosLeft;
-
-    /* leave the inverse zigzag scan part for the caller */
-
-
-    return AVCDEC_SUCCESS;
-}
diff --git a/media/libstagefright/codecs/avc/dec/src/slice.cpp b/media/libstagefright/codecs/avc/dec/src/slice.cpp
deleted file mode 100644
index 7a2ef3d..0000000
--- a/media/libstagefright/codecs/avc/dec/src/slice.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/* Note for optimization: syntax decoding or operations related to B_SLICE should be
-commented out by macro definition or function pointers. */
-
-#include <string.h>
-
-#include "avcdec_lib.h"
-#include "avcdec_bitstream.h"
-
-const static int mbPart2raster[3][4] = {{0, 0, 0, 0}, {1, 1, 0, 0}, {1, 0, 1, 0}};
-/* decode_frame_slice() */
-/* decode_one_slice() */
-AVCDec_Status DecodeSlice(AVCDecObject *decvid)
-{
-    AVCDec_Status status;
-    AVCCommonObj *video = decvid->common;
-    AVCSliceHeader *sliceHdr = video->sliceHdr;
-    AVCMacroblock *currMB ;
-    AVCDecBitstream *stream = decvid->bitstream;
-    uint slice_group_id;
-    uint CurrMbAddr, moreDataFlag;
-
-    /* set the first mb in slice */
-    CurrMbAddr = sliceHdr->first_mb_in_slice;
-    slice_group_id = video->MbToSliceGroupMap[CurrMbAddr];
-
-    if ((CurrMbAddr && (CurrMbAddr != (uint)(video->mbNum + 1))) && video->currSeqParams->constrained_set1_flag == 1)
-    {
-        ConcealSlice(decvid, video->mbNum, CurrMbAddr);
-    }
-
-    moreDataFlag = 1;
-    video->mb_skip_run = -1;
-
-
-    /* while loop , see subclause 7.3.4 */
-    do
-    {
-        if (CurrMbAddr >= video->PicSizeInMbs)
-        {
-            return AVCDEC_FAIL;
-        }
-
-        currMB = video->currMB = &(video->mblock[CurrMbAddr]);
-        video->mbNum = CurrMbAddr;
-        currMB->slice_id = video->slice_id;  //  slice
-
-        /* we can remove this check if we don't support Mbaff. */
-        /* we can wrap below into an initMB() function which will also
-        do necessary reset of macroblock related parameters. */
-
-        video->mb_x = CurrMbAddr % video->PicWidthInMbs;
-        video->mb_y = CurrMbAddr / video->PicWidthInMbs;
-
-        /* check the availability of neighboring macroblocks */
-        InitNeighborAvailability(video, CurrMbAddr);
-
-        /* read_macroblock and decode_one_macroblock() */
-        status = DecodeMB(decvid);
-        if (status != AVCDEC_SUCCESS)
-        {
-            return status;
-        }
-#ifdef MB_BASED_DEBLOCK
-        if (video->currPicParams->num_slice_groups_minus1 == 0)
-        {
-            MBInLoopDeblock(video); /* MB-based deblocking */
-        }
-        else    /* this mode cannot be used if the number of slice group is not one. */
-        {
-            return AVCDEC_FAIL;
-        }
-#endif
-        video->numMBs--;
-
-        moreDataFlag = more_rbsp_data(stream);
-
-
-        /* go to next MB */
-        while (++CurrMbAddr < video->PicSizeInMbs && video->MbToSliceGroupMap[CurrMbAddr] != (int)slice_group_id)
-        {
-        }
-
-    }
-    while ((moreDataFlag && video->numMBs > 0) || video->mb_skip_run > 0); /* even if no more data, but last few MBs are skipped */
-
-    if (video->numMBs == 0)
-    {
-        video->newPic = TRUE;
-        video->mbNum = 0;  // _Conceal
-        return AVCDEC_PICTURE_READY;
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/* read MB mode and motion vectors */
-/* perform Intra/Inter prediction and residue */
-/* update video->mb_skip_run */
-AVCDec_Status DecodeMB(AVCDecObject *decvid)
-{
-    AVCDec_Status status;
-    AVCCommonObj *video = decvid->common;
-    AVCDecBitstream *stream = decvid->bitstream;
-    AVCMacroblock *currMB = video->currMB;
-    uint mb_type;
-    int slice_type = video->slice_type;
-    int temp;
-
-    currMB->QPy = video->QPy;
-    currMB->QPc = video->QPc;
-
-    if (slice_type == AVC_P_SLICE)
-    {
-        if (video->mb_skip_run < 0)
-        {
-            ue_v(stream, (uint *)&(video->mb_skip_run));
-        }
-
-        if (video->mb_skip_run == 0)
-        {
-            /* this will not handle the case where the slice ends with a mb_skip_run == 0 and no following MB data  */
-            ue_v(stream, &mb_type);
-            if (mb_type > 30)
-            {
-                return AVCDEC_FAIL;
-            }
-            InterpretMBModeP(currMB, mb_type);
-            video->mb_skip_run = -1;
-        }
-        else
-        {
-            /* see subclause 7.4.4 for more details on how
-            mb_field_decoding_flag is derived in case of skipped MB */
-
-            currMB->mb_intra = FALSE;
-
-            currMB->mbMode = AVC_SKIP;
-            currMB->MbPartWidth = currMB->MbPartHeight = 16;
-            currMB->NumMbPart = 1;
-            currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
-                                          currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1; //
-            currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
-                                            currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
-            currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
-                                             currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
-
-            memset(currMB->nz_coeff, 0, sizeof(uint8)*NUM_BLKS_IN_MB);
-
-            currMB->CBP = 0;
-            video->cbp4x4 = 0;
-            /* for skipped MB, always look at the first entry in RefPicList */
-            currMB->RefIdx[0] = currMB->RefIdx[1] =
-                                    currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
-            InterMBPrediction(video);
-            video->mb_skip_run--;
-            return AVCDEC_SUCCESS;
-        }
-
-    }
-    else
-    {
-        /* Then decode mode and MV */
-        ue_v(stream, &mb_type);
-        if (mb_type > 25)
-        {
-            return AVCDEC_FAIL;
-        }
-        InterpretMBModeI(currMB, mb_type);
-    }
-
-
-    if (currMB->mbMode != AVC_I_PCM)
-    {
-
-        if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
-        {
-            status = sub_mb_pred(video, currMB, stream);
-        }
-        else
-        {
-            status = mb_pred(video, currMB, stream) ;
-        }
-
-        if (status != AVCDEC_SUCCESS)
-        {
-            return status;
-        }
-
-        if (currMB->mbMode != AVC_I16)
-        {
-            /* decode coded_block_pattern */
-            status = DecodeCBP(currMB, stream);
-            if (status != AVCDEC_SUCCESS)
-            {
-                return status;
-            }
-        }
-
-        if (currMB->CBP > 0 || currMB->mbMode == AVC_I16)
-        {
-            se_v(stream, &temp);
-            if (temp)
-            {
-                temp += (video->QPy + 52);
-                currMB->QPy = video->QPy = temp - 52 * (temp * 79 >> 12);
-                if (currMB->QPy > 51 || currMB->QPy < 0)
-                {
-                    video->QPy = AVC_CLIP3(0, 51, video->QPy);
-//                  return AVCDEC_FAIL;
-                }
-                video->QPy_div_6 = (video->QPy * 43) >> 8;
-                video->QPy_mod_6 = video->QPy - 6 * video->QPy_div_6;
-                currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->QPy + video->currPicParams->chroma_qp_index_offset)];
-                video->QPc_div_6 = (video->QPc * 43) >> 8;
-                video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
-            }
-        }
-        /* decode residue and inverse transform */
-        status = residual(decvid, currMB);
-        if (status != AVCDEC_SUCCESS)
-        {
-            return status;
-        }
-    }
-    else
-    {
-        if (stream->bitcnt & 7)
-        {
-            BitstreamByteAlign(stream);
-        }
-        /* decode pcm_byte[i] */
-        DecodeIntraPCM(video, stream);
-
-        currMB->QPy = 0;  /* necessary for deblocking */ // _OPTIMIZE
-        currMB->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->currPicParams->chroma_qp_index_offset)];
-
-        /* default values, don't know if really needed */
-        currMB->CBP = 0x3F;
-        video->cbp4x4 = 0xFFFF;
-        currMB->mb_intra = TRUE;
-        memset(currMB->nz_coeff, 16, sizeof(uint8)*NUM_BLKS_IN_MB);
-        return AVCDEC_SUCCESS;
-    }
-
-
-    /* do Intra/Inter prediction, together with the residue compensation */
-    /* This part should be common between the skip and no-skip */
-    if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
-    {
-        IntraMBPrediction(video);
-    }
-    else
-    {
-        InterMBPrediction(video);
-    }
-
-
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see subclause 7.3.5.1 */
-AVCDec_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
-{
-    int mbPartIdx;
-    AVCSliceHeader *sliceHdr = video->sliceHdr;
-    uint max_ref_idx;
-    const int *temp_0;
-    int16 *temp_1;
-    uint code;
-
-    if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
-    {
-
-        video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
-
-        if (!video->currPicParams->constrained_intra_pred_flag)
-        {
-            video->intraAvailA = video->mbAvailA;
-            video->intraAvailB = video->mbAvailB;
-            video->intraAvailC = video->mbAvailC;
-            video->intraAvailD = video->mbAvailD;
-        }
-        else
-        {
-            if (video->mbAvailA)
-            {
-                video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
-            }
-            if (video->mbAvailB)
-            {
-                video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
-            }
-            if (video->mbAvailC)
-            {
-                video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
-            }
-            if (video->mbAvailD)
-            {
-                video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
-            }
-        }
-
-
-        if (currMB->mbMode == AVC_I4)
-        {
-            /* perform prediction to get the actual intra 4x4 pred mode */
-            DecodeIntra4x4Mode(video, currMB, stream);
-            /* output will be in currMB->i4Mode[4][4] */
-        }
-
-        ue_v(stream, &code);
-
-        if (code > 3)
-        {
-            return AVCDEC_FAIL; /* out of range */
-        }
-        currMB->intra_chroma_pred_mode = (AVCIntraChromaPredMode)code;
-    }
-    else
-    {
-
-        memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
-
-        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
-//      max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
-        max_ref_idx = video->refList0Size - 1;
-
-        /* decode ref index for L0 */
-        if (sliceHdr->num_ref_idx_l0_active_minus1 > 0)
-        {
-            for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
-            {
-                te_v(stream, &code, max_ref_idx);
-                if (code > (uint)max_ref_idx)
-                {
-                    return AVCDEC_FAIL;
-                }
-                currMB->ref_idx_L0[mbPartIdx] = code;
-            }
-        }
-
-        /* populate ref_idx_L0 */
-        temp_0 = &mbPart2raster[currMB->mbMode-AVC_P16][0];
-        temp_1 = &currMB->ref_idx_L0[3];
-
-        *temp_1-- = currMB->ref_idx_L0[*temp_0++];
-        *temp_1-- = currMB->ref_idx_L0[*temp_0++];
-        *temp_1-- = currMB->ref_idx_L0[*temp_0++];
-        *temp_1-- = currMB->ref_idx_L0[*temp_0++];
-
-        /* Global reference index, these values are used in deblock */
-        currMB->RefIdx[0] = video->RefPicList0[currMB->ref_idx_L0[0]]->RefIdx;
-        currMB->RefIdx[1] = video->RefPicList0[currMB->ref_idx_L0[1]]->RefIdx;
-        currMB->RefIdx[2] = video->RefPicList0[currMB->ref_idx_L0[2]]->RefIdx;
-        currMB->RefIdx[3] = video->RefPicList0[currMB->ref_idx_L0[3]]->RefIdx;
-
-        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
-        max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
-        /* decode mvd_l0 */
-        for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
-        {
-            se_v(stream, &(video->mvd_l0[mbPartIdx][0][0]));
-            se_v(stream, &(video->mvd_l0[mbPartIdx][0][1]));
-        }
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see subclause 7.3.5.2 */
-AVCDec_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
-{
-    int mbPartIdx, subMbPartIdx;
-    AVCSliceHeader *sliceHdr = video->sliceHdr;
-    uint max_ref_idx;
-    uint sub_mb_type[4];
-    uint code;
-
-    memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
-
-    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
-    {
-        ue_v(stream, &(sub_mb_type[mbPartIdx]));
-        if (sub_mb_type[mbPartIdx] > 3)
-        {
-            return AVCDEC_FAIL;
-        }
-
-    }
-    /* we have to check the values to make sure they are valid  */
-    /* assign values to currMB->sub_mb_type[], currMB->MBPartPredMode[][x] */
-
-    InterpretSubMBModeP(currMB, sub_mb_type);
-
-
-    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
-//      max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
-    max_ref_idx = video->refList0Size - 1;
-
-    if (sliceHdr->num_ref_idx_l0_active_minus1 > 0 && currMB->mbMode != AVC_P8ref0)
-    {
-        for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
-        {
-            te_v(stream, (uint*)&code, max_ref_idx);
-            if (code > max_ref_idx)
-            {
-                return AVCDEC_FAIL;
-            }
-            currMB->ref_idx_L0[mbPartIdx] = code;
-        }
-    }
-    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
-
-    max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
-    /*  if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
-            max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;*/
-    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
-    {
-        for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
-        {
-            se_v(stream, &(video->mvd_l0[mbPartIdx][subMbPartIdx][0]));
-            se_v(stream, &(video->mvd_l0[mbPartIdx][subMbPartIdx][1]));
-        }
-        /* used in deblocking */
-        currMB->RefIdx[mbPartIdx] = video->RefPicList0[currMB->ref_idx_L0[mbPartIdx]]->RefIdx;
-    }
-    return AVCDEC_SUCCESS;
-}
-
-void InterpretMBModeI(AVCMacroblock *mblock, uint mb_type)
-{
-    mblock->NumMbPart = 1;
-
-    mblock->mb_intra = TRUE;
-
-    if (mb_type == 0) /* I_4x4 */
-    {
-        mblock->mbMode = AVC_I4;
-    }
-    else if (mb_type < 25) /* I_PCM */
-    {
-        mblock->mbMode = AVC_I16;
-        mblock->i16Mode = (AVCIntra16x16PredMode)((mb_type - 1) & 0x3);
-        if (mb_type > 12)
-        {
-            mblock->CBP = (((mb_type - 13) >> 2) << 4) + 0x0F;
-        }
-        else
-        {
-            mblock->CBP = ((mb_type - 1) >> 2) << 4;
-        }
-    }
-    else
-    {
-        mblock->mbMode = AVC_I_PCM;
-    }
-
-    return ;
-}
-
-void InterpretMBModeP(AVCMacroblock *mblock, uint mb_type)
-{
-    const static int map2PartWidth[5] = {16, 16, 8, 8, 8};
-    const static int map2PartHeight[5] = {16, 8, 16, 8, 8};
-    const static int map2NumPart[5] = {1, 2, 2, 4, 4};
-    const static AVCMBMode map2mbMode[5] = {AVC_P16, AVC_P16x8, AVC_P8x16, AVC_P8, AVC_P8ref0};
-
-    mblock->mb_intra = FALSE;
-    if (mb_type < 5)
-    {
-        mblock->mbMode = map2mbMode[mb_type];
-        mblock->MbPartWidth = map2PartWidth[mb_type];
-        mblock->MbPartHeight = map2PartHeight[mb_type];
-        mblock->NumMbPart = map2NumPart[mb_type];
-        mblock->NumSubMbPart[0] = mblock->NumSubMbPart[1] =
-                                      mblock->NumSubMbPart[2] = mblock->NumSubMbPart[3] = 1;
-        mblock->SubMbPartWidth[0] = mblock->SubMbPartWidth[1] =
-                                        mblock->SubMbPartWidth[2] = mblock->SubMbPartWidth[3] = mblock->MbPartWidth;
-        mblock->SubMbPartHeight[0] = mblock->SubMbPartHeight[1] =
-                                         mblock->SubMbPartHeight[2] = mblock->SubMbPartHeight[3] = mblock->MbPartHeight;
-    }
-    else
-    {
-        InterpretMBModeI(mblock, mb_type - 5);
-        /* set MV and Ref_Idx codes of Intra blocks in P-slices  */
-        memset(mblock->mvL0, 0, sizeof(int32)*16);
-        mblock->ref_idx_L0[0] = mblock->ref_idx_L0[1] = mblock->ref_idx_L0[2] = mblock->ref_idx_L0[3] = -1;
-    }
-    return ;
-}
-
-void InterpretMBModeB(AVCMacroblock *mblock, uint mb_type)
-{
-    const static int map2PartWidth[23] = {8, 16, 16, 16, 16, 8, 16, 8, 16, 8,
-                                          16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 8
-                                         };
-    const static int map2PartHeight[23] = {8, 16, 16, 16, 8, 16, 8, 16, 8,
-                                           16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8, 16, 8
-                                          };
-    /* see enum AVCMBType declaration */
-    const static AVCMBMode map2mbMode[23] = {AVC_BDirect16, AVC_P16, AVC_P16, AVC_P16,
-                                            AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16,
-                                            AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16,
-                                            AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P16x8, AVC_P8x16, AVC_P8
-                                            };
-    const static int map2PredMode1[23] = {3, 0, 1, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, -1};
-    const static int map2PredMode2[23] = { -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, -1};
-    const static int map2NumPart[23] = { -1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4};
-
-    mblock->mb_intra = FALSE;
-
-    if (mb_type < 23)
-    {
-        mblock->mbMode = map2mbMode[mb_type];
-        mblock->NumMbPart = map2NumPart[mb_type];
-        mblock->MBPartPredMode[0][0] = (AVCPredMode)map2PredMode1[mb_type];
-        if (mblock->NumMbPart > 1)
-        {
-            mblock->MBPartPredMode[1][0] = (AVCPredMode)map2PredMode2[mb_type];
-        }
-        mblock->MbPartWidth = map2PartWidth[mb_type];
-        mblock->MbPartHeight = map2PartHeight[mb_type];
-    }
-    else
-    {
-        InterpretMBModeI(mblock, mb_type - 23);
-    }
-
-    return ;
-}
-
-void InterpretMBModeSI(AVCMacroblock *mblock, uint mb_type)
-{
-    mblock->mb_intra = TRUE;
-
-    if (mb_type == 0)
-    {
-        mblock->mbMode = AVC_SI4;
-        /* other values are N/A */
-    }
-    else
-    {
-        InterpretMBModeI(mblock, mb_type - 1);
-    }
-    return ;
-}
-
-/* input is mblock->sub_mb_type[] */
-void InterpretSubMBModeP(AVCMacroblock *mblock, uint *sub_mb_type)
-{
-    int i,  sub_type;
-    /* see enum AVCMBType declaration */
-//  const static AVCSubMBMode map2subMbMode[4] = {AVC_8x8,AVC_8x4,AVC_4x8,AVC_4x4};
-    const static int map2subPartWidth[4] = {8, 8, 4, 4};
-    const static int map2subPartHeight[4] = {8, 4, 8, 4};
-    const static int map2numSubPart[4] = {1, 2, 2, 4};
-
-    for (i = 0; i < 4 ; i++)
-    {
-        sub_type = (int) sub_mb_type[i];
-        //  mblock->subMbMode[i] = map2subMbMode[sub_type];
-        mblock->NumSubMbPart[i] = map2numSubPart[sub_type];
-        mblock->SubMbPartWidth[i] = map2subPartWidth[sub_type];
-        mblock->SubMbPartHeight[i] = map2subPartHeight[sub_type];
-    }
-
-    return ;
-}
-
-void InterpretSubMBModeB(AVCMacroblock *mblock, uint *sub_mb_type)
-{
-    int i, j, sub_type;
-    /* see enum AVCMBType declaration */
-    const static AVCSubMBMode map2subMbMode[13] = {AVC_BDirect8, AVC_8x8, AVC_8x8,
-            AVC_8x8, AVC_8x4, AVC_4x8, AVC_8x4, AVC_4x8, AVC_8x4, AVC_4x8, AVC_4x4, AVC_4x4, AVC_4x4
-                                                  };
-    const static int map2subPartWidth[13] = {4, 8, 8, 8, 8, 4, 8, 4, 8, 4, 4, 4, 4};
-    const static int map2subPartHeight[13] = {4, 8, 8, 8, 4, 8, 4, 8, 4, 8, 4, 4, 4};
-    const static int map2numSubPart[13] = {1, 1, 1, 2, 2, 2, 2, 2, 2, 4, 4, 4};
-    const static int map2predMode[13] = {3, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2};
-
-    for (i = 0; i < 4 ; i++)
-    {
-        sub_type = (int) sub_mb_type[i];
-        mblock->subMbMode[i] = map2subMbMode[sub_type];
-        mblock->NumSubMbPart[i] = map2numSubPart[sub_type];
-        mblock->SubMbPartWidth[i] = map2subPartWidth[sub_type];
-        mblock->SubMbPartHeight[i] = map2subPartHeight[sub_type];
-        for (j = 0; j < 4; j++)
-        {
-            mblock->MBPartPredMode[i][j] = (AVCPredMode)map2predMode[sub_type];
-        }
-    }
-
-    return ;
-}
-
-/* see subclause 8.3.1 */
-AVCDec_Status DecodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCDecBitstream *stream)
-{
-    int intra4x4PredModeA = 0, intra4x4PredModeB = 0, predIntra4x4PredMode = 0;
-    int component, SubBlock_indx, block_x, block_y;
-    int dcOnlyPredictionFlag;
-    uint    prev_intra4x4_pred_mode_flag[16];
-    int     rem_intra4x4_pred_mode[16];
-    int bindx = 0;
-
-    for (component = 0; component < 4; component++) /* partition index */
-    {
-        block_x = ((component & 1) << 1);
-        block_y = ((component >> 1) << 1);
-
-        for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++) /* sub-partition index */
-        {
-            BitstreamRead1Bit(stream, &(prev_intra4x4_pred_mode_flag[bindx]));
-
-            if (!prev_intra4x4_pred_mode_flag[bindx])
-            {
-                BitstreamReadBits(stream, 3, (uint*)&(rem_intra4x4_pred_mode[bindx]));
-            }
-
-            dcOnlyPredictionFlag = 0;
-            if (block_x > 0)
-            {
-                intra4x4PredModeA = currMB->i4Mode[(block_y << 2) + block_x - 1 ];
-            }
-            else
-            {
-                if (video->intraAvailA)
-                {
-                    if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
-                    {
-                        intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[(block_y << 2) + 3];
-                    }
-                    else
-                    {
-                        intra4x4PredModeA = AVC_I4_DC;
-                    }
-                }
-                else
-                {
-                    dcOnlyPredictionFlag = 1;
-                }
-            }
-
-            if (block_y > 0)
-            {
-                intra4x4PredModeB = currMB->i4Mode[((block_y-1) << 2) + block_x];
-            }
-            else
-            {
-                if (video->intraAvailB)
-                {
-                    if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
-                    {
-                        intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[(3 << 2) + block_x];
-                    }
-                    else
-                    {
-                        intra4x4PredModeB = AVC_I4_DC;
-                    }
-                }
-                else
-                {
-                    dcOnlyPredictionFlag = 1;
-                }
-            }
-
-            if (dcOnlyPredictionFlag)
-            {
-                intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
-            }
-
-            predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
-            if (prev_intra4x4_pred_mode_flag[bindx])
-            {
-                currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)predIntra4x4PredMode;
-            }
-            else
-            {
-                if (rem_intra4x4_pred_mode[bindx] < predIntra4x4PredMode)
-                {
-                    currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)rem_intra4x4_pred_mode[bindx];
-                }
-                else
-                {
-                    currMB->i4Mode[(block_y<<2)+block_x] = (AVCIntra4x4PredMode)(rem_intra4x4_pred_mode[bindx] + 1);
-                }
-            }
-            bindx++;
-            block_y += (SubBlock_indx & 1) ;
-            block_x += (1 - 2 * (SubBlock_indx & 1)) ;
-        }
-    }
-    return AVCDEC_SUCCESS;
-}
-AVCDec_Status ConcealSlice(AVCDecObject *decvid, int mbnum_start, int mbnum_end)
-{
-    AVCCommonObj *video = decvid->common;
-    AVCMacroblock *currMB ;
-
-    int CurrMbAddr;
-
-    if (video->RefPicList0[0] == NULL)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    for (CurrMbAddr = mbnum_start; CurrMbAddr < mbnum_end; CurrMbAddr++)
-    {
-        currMB = video->currMB = &(video->mblock[CurrMbAddr]);
-        video->mbNum = CurrMbAddr;
-        currMB->slice_id = video->slice_id++;  //  slice
-
-        /* we can remove this check if we don't support Mbaff. */
-        /* we can wrap below into an initMB() function which will also
-        do necessary reset of macroblock related parameters. */
-
-        video->mb_x = CurrMbAddr % video->PicWidthInMbs;
-        video->mb_y = CurrMbAddr / video->PicWidthInMbs;
-
-        /* check the availability of neighboring macroblocks */
-        InitNeighborAvailability(video, CurrMbAddr);
-
-        currMB->mb_intra = FALSE;
-
-        currMB->mbMode = AVC_SKIP;
-        currMB->MbPartWidth = currMB->MbPartHeight = 16;
-
-        currMB->NumMbPart = 1;
-        currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
-                                      currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1;
-        currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
-                                        currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
-        currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
-                                         currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
-        currMB->QPy = 26;
-        currMB->QPc = 26;
-        memset(currMB->nz_coeff, 0, sizeof(uint8)*NUM_BLKS_IN_MB);
-
-        currMB->CBP = 0;
-        video->cbp4x4 = 0;
-        /* for skipped MB, always look at the first entry in RefPicList */
-        currMB->RefIdx[0] = currMB->RefIdx[1] =
-                                currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
-        InterMBPrediction(video);
-
-        video->numMBs--;
-
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
diff --git a/media/libstagefright/codecs/avc/dec/src/vlc.cpp b/media/libstagefright/codecs/avc/dec/src/vlc.cpp
deleted file mode 100644
index f531249..0000000
--- a/media/libstagefright/codecs/avc/dec/src/vlc.cpp
+++ /dev/null
@@ -1,815 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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 "avcdec_lib.h"
-#include "avcdec_bitstream.h"
-
-//#define PV_ARM_V5
-#ifdef PV_ARM_V5
-#define PV_CLZ(A,B) __asm{CLZ (A),(B)}  \
-    A -= 16;
-#else
-#define PV_CLZ(A,B) while (((B) & 0x8000) == 0) {(B) <<=1; A++;}
-#endif
-
-
-#define PV_NO_CLZ
-
-#ifndef PV_NO_CLZ
-typedef struct tagVLCNumCoeffTrail
-{
-    int trailing;
-    int total_coeff;
-    int length;
-} VLCNumCoeffTrail;
-
-typedef struct tagShiftOffset
-{
-    int shift;
-    int offset;
-} ShiftOffset;
-
-const VLCNumCoeffTrail NumCoeffTrailOnes[3][67] =
-{
-    {{0, 0, 1}, {1, 1, 2}, {2, 2, 3}, {1, 2, 6}, {0, 1, 6}, {3, 3, 5}, {3, 3, 5}, {3, 5, 7},
-        {2, 3, 7}, {3, 4, 6}, {3, 4, 6}, {3, 6, 8}, {2, 4, 8}, {1, 3, 8}, {0, 2, 8}, {3, 7, 9},
-        {2, 5, 9}, {1, 4, 9}, {0, 3, 9}, {3, 8, 10}, {2, 6, 10}, {1, 5, 10}, {0, 4, 10}, {3, 9, 11},
-        {2, 7, 11}, {1, 6, 11}, {0, 5, 11}, {0, 8, 13}, {2, 9, 13}, {1, 8, 13}, {0, 7, 13}, {3, 10, 13},
-        {2, 8, 13}, {1, 7, 13}, {0, 6, 13}, {3, 12, 14}, {2, 11, 14}, {1, 10, 14}, {0, 10, 14}, {3, 11, 14},
-        {2, 10, 14}, {1, 9, 14}, {0, 9, 14}, {3, 14, 15}, {2, 13, 15}, {1, 12, 15}, {0, 12, 15}, {3, 13, 15},
-        {2, 12, 15}, {1, 11, 15}, {0, 11, 15}, {3, 16, 16}, {2, 15, 16}, {1, 15, 16}, {0, 14, 16}, {3, 15, 16},
-        {2, 14, 16}, {1, 14, 16}, {0, 13, 16}, {0, 16, 16}, {2, 16, 16}, {1, 16, 16}, {0, 15, 16}, {1, 13, 15},
-        { -1, -1, -1}, { -1, -1, -1}, { -1, -1, -1}},
-
-    {{1, 1, 2}, {0, 0, 2}, {3, 4, 4}, {3, 3, 4}, {2, 2, 3}, {2, 2, 3}, {3, 6, 6}, {2, 3, 6},
-        {1, 3, 6}, {0, 1, 6}, {3, 5, 5}, {3, 5, 5}, {1, 2, 5}, {1, 2, 5}, {3, 7, 6}, {2, 4, 6},
-        {1, 4, 6}, {0, 2, 6}, {3, 8, 7}, {2, 5, 7}, {1, 5, 7}, {0, 3, 7}, {0, 5, 8}, {2, 6, 8},
-        {1, 6, 8}, {0, 4, 8}, {3, 9, 9}, {2, 7, 9}, {1, 7, 9}, {0, 6, 9}, {3, 11, 11}, {2, 9, 11},
-        {1, 9, 11}, {0, 8, 11}, {3, 10, 11}, {2, 8, 11}, {1, 8, 11}, {0, 7, 11}, {0, 11, 12}, {2, 11, 12},
-        {1, 11, 12}, {0, 10, 12}, {3, 12, 12}, {2, 10, 12}, {1, 10, 12}, {0, 9, 12}, {3, 14, 13}, {2, 13, 13},
-        {1, 13, 13}, {0, 13, 13}, {3, 13, 13}, {2, 12, 13}, {1, 12, 13}, {0, 12, 13}, {1, 15, 14}, {0, 15, 14},
-        {2, 15, 14}, {1, 14, 14}, {2, 14, 13}, {2, 14, 13}, {0, 14, 13}, {0, 14, 13}, {3, 16, 14}, {2, 16, 14},
-        {1, 16, 14}, {0, 16, 14}, {3, 15, 13}},
-
-    {{3, 7, 4}, {3, 6, 4}, {3, 5, 4}, {3, 4, 4}, {3, 3, 4}, {2, 2, 4}, {1, 1, 4}, {0, 0, 4},
-        {1, 5, 5}, {2, 5, 5}, {1, 4, 5}, {2, 4, 5}, {1, 3, 5}, {3, 8, 5}, {2, 3, 5}, {1, 2, 5},
-        {0, 3, 6}, {2, 7, 6}, {1, 7, 6}, {0, 2, 6}, {3, 9, 6}, {2, 6, 6}, {1, 6, 6}, {0, 1, 6},
-        {0, 7, 7}, {0, 6, 7}, {2, 9, 7}, {0, 5, 7}, {3, 10, 7}, {2, 8, 7}, {1, 8, 7}, {0, 4, 7},
-        {3, 12, 8}, {2, 11, 8}, {1, 10, 8}, {0, 9, 8}, {3, 11, 8}, {2, 10, 8}, {1, 9, 8}, {0, 8, 8},
-        {0, 12, 9}, {2, 13, 9}, {1, 12, 9}, {0, 11, 9}, {3, 13, 9}, {2, 12, 9}, {1, 11, 9}, {0, 10, 9},
-        {1, 15, 10}, {0, 14, 10}, {3, 14, 10}, {2, 14, 10}, {1, 14, 10}, {0, 13, 10}, {1, 13, 9}, {1, 13, 9},
-        {1, 16, 10}, {0, 15, 10}, {3, 15, 10}, {2, 15, 10}, {3, 16, 10}, {2, 16, 10}, {0, 16, 10}, { -1, -1, -1},
-        { -1, -1, -1}, { -1, -1, -1}, { -1, -1, -1}}
-};
-
-
-const ShiftOffset NumCoeffTrailOnes_indx[3][15] =
-{
-    {{15, -1}, {14, 0}, {13, 1}, {10, -1}, {9, 3}, {8, 7}, {7, 11}, {6, 15},
-        {5, 19}, {3, 19}, {2, 27}, {1, 35}, {0, 43}, {0, 55}, {1, 62}},
-
-    {{14, -2}, {12, -2}, {10, -2}, {10, 10}, {9, 14}, {8, 18}, {7, 22}, {5, 22},
-        {4, 30}, {3, 38}, {2, 46}, {2, 58}, {3, 65}, {16, 0}, {16, 0}},
-
-    {{12, -8}, {11, 0}, {10, 8}, {9, 16}, {8, 24}, {7, 32}, {6, 40}, {6, 52},
-        {6, 58}, {6, 61}, {16, 0}, {16, 0}, {16, 0}, {16, 0}, {16, 0}}
-};
-
-const static int nC_table[8] = {0, 0, 1, 1, 2, 2, 2, 2};
-
-#endif
-/**
-See algorithm in subclause 9.1, Table 9-1, Table 9-2. */
-AVCDec_Status ue_v(AVCDecBitstream *bitstream, uint *codeNum)
-{
-    uint temp, tmp_cnt;
-    int leading_zeros = 0;
-    BitstreamShowBits(bitstream, 16, &temp);
-    tmp_cnt = temp  | 0x1;
-
-    PV_CLZ(leading_zeros, tmp_cnt)
-
-    if (leading_zeros < 8)
-    {
-        *codeNum = (temp >> (15 - (leading_zeros << 1))) - 1;
-        BitstreamFlushBits(bitstream, (leading_zeros << 1) + 1);
-    }
-    else
-    {
-        BitstreamReadBits(bitstream, (leading_zeros << 1) + 1, &temp);
-        *codeNum = temp - 1;
-    }
-
-    return AVCDEC_SUCCESS;
-}
-
-/**
-See subclause 9.1.1, Table 9-3 */
-AVCDec_Status  se_v(AVCDecBitstream *bitstream, int *value)
-{
-    uint temp, tmp_cnt;
-    int leading_zeros = 0;
-    BitstreamShowBits(bitstream, 16, &temp);
-    tmp_cnt = temp | 0x1;
-
-    PV_CLZ(leading_zeros, tmp_cnt)
-
-    if (leading_zeros < 8)
-    {
-        temp >>= (15 - (leading_zeros << 1));
-        BitstreamFlushBits(bitstream, (leading_zeros << 1) + 1);
-    }
-    else
-    {
-        BitstreamReadBits(bitstream, (leading_zeros << 1) + 1, &temp);
-    }
-
-    *value = temp >> 1;
-
-    if (temp & 0x01)                          // lsb is signed bit
-        *value = -(*value);
-
-//  leading_zeros = temp >> 1;
-//  *value = leading_zeros - (leading_zeros*2*(temp&1));
-
-    return AVCDEC_SUCCESS;
-}
-
-AVCDec_Status  se_v32bit(AVCDecBitstream *bitstream, int32 *value)
-{
-    int leadingZeros;
-    uint32 infobits;
-    uint32 codeNum;
-
-    if (AVCDEC_SUCCESS != GetEGBitstring32bit(bitstream, &leadingZeros, &infobits))
-        return AVCDEC_FAIL;
-
-    codeNum = (1 << leadingZeros) - 1 + infobits;
-
-    *value = (codeNum + 1) / 2;
-
-    if ((codeNum & 0x01) == 0)                        // lsb is signed bit
-        *value = -(*value);
-
-    return AVCDEC_SUCCESS;
-}
-
-
-AVCDec_Status te_v(AVCDecBitstream *bitstream, uint *value, uint range)
-{
-    if (range > 1)
-    {
-        ue_v(bitstream, value);
-    }
-    else
-    {
-        BitstreamRead1Bit(bitstream, value);
-        *value = 1 - (*value);
-    }
-    return AVCDEC_SUCCESS;
-}
-
-
-
-/* This function is only used for syntax with range from -2^31 to 2^31-1 */
-/* only a few of them in the SPS and PPS */
-AVCDec_Status GetEGBitstring32bit(AVCDecBitstream *bitstream, int *leadingZeros, uint32 *infobits)
-{
-    int bit_value;
-    uint info_temp;
-
-    *leadingZeros = 0;
-
-    BitstreamRead1Bit(bitstream, (uint*)&bit_value);
-
-    while (!bit_value)
-    {
-        (*leadingZeros)++;
-        BitstreamRead1Bit(bitstream, (uint*)&bit_value);
-    }
-
-    if (*leadingZeros > 0)
-    {
-        if (sizeof(uint) == 4)  /* 32 bit machine */
-        {
-            BitstreamReadBits(bitstream, *leadingZeros, (uint*)&info_temp);
-            *infobits = (uint32)info_temp;
-        }
-        else if (sizeof(uint) == 2) /* 16 bit machine */
-        {
-            *infobits = 0;
-            if (*leadingZeros > 16)
-            {
-                BitstreamReadBits(bitstream, 16, (uint*)&info_temp);
-                (*leadingZeros) -= 16;
-                *infobits = ((uint32)info_temp) << (*leadingZeros);
-            }
-
-            BitstreamReadBits(bitstream, *leadingZeros, (uint*)&info_temp);
-            *infobits |= (uint32)info_temp ;
-        }
-    }
-    else
-        *infobits = 0;
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see Table 9-4 assignment of codeNum to values of coded_block_pattern. */
-const static uint8 MapCBP[48][2] =
-{
-    {47, 0}, {31, 16}, {15, 1}, { 0, 2}, {23, 4}, {27, 8}, {29, 32}, {30, 3}, { 7, 5}, {11, 10}, {13, 12}, {14, 15},
-    {39, 47}, {43, 7}, {45, 11}, {46, 13}, {16, 14}, { 3, 6}, { 5, 9}, {10, 31}, {12, 35}, {19, 37}, {21, 42}, {26, 44},
-    {28, 33}, {35, 34}, {37, 36}, {42, 40}, {44, 39}, { 1, 43}, { 2, 45}, { 4, 46}, { 8, 17}, {17, 18}, {18, 20}, {20, 24},
-    {24, 19}, { 6, 21}, { 9, 26}, {22, 28}, {25, 23}, {32, 27}, {33, 29}, {34, 30}, {36, 22}, {40, 25}, {38, 38}, {41, 41},
-};
-
-AVCDec_Status DecodeCBP(AVCMacroblock *currMB, AVCDecBitstream *stream)
-{
-    uint codeNum;
-    uint coded_block_pattern;
-
-    ue_v(stream, &codeNum);
-
-    if (codeNum > 47)
-    {
-        return AVCDEC_FAIL;
-    }
-
-    /* can get rid of the if _OPTIMIZE */
-    if (currMB->mbMode == AVC_I4)
-    {
-        coded_block_pattern = MapCBP[codeNum][0];
-    }
-    else
-    {
-        coded_block_pattern = MapCBP[codeNum][1];
-    }
-
-//  currMB->cbpL = coded_block_pattern&0xF;  /* modulo 16 */
-//  currMB->cbpC = coded_block_pattern>>4;   /* divide 16 */
-    currMB->CBP = coded_block_pattern;
-
-    return AVCDEC_SUCCESS;
-}
-
-
-/* TO BE OPTIMIZED !!!!! */
-AVCDec_Status ce_TotalCoeffTrailingOnes(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff, int nC)
-{
-#ifdef PV_NO_CLZ
-    const static uint8 TotCofNTrail1[75][3] = {{0, 0, 16}/*error */, {0, 0, 16}/*error */, {1, 13, 15}, {1, 13, 15}, {0, 16, 16}, {2, 16, 16}, {1, 16, 16}, {0, 15, 16},
-        {3, 16, 16}, {2, 15, 16}, {1, 15, 16}, {0, 14, 16}, {3, 15, 16}, {2, 14, 16}, {1, 14, 16}, {0, 13, 16},
-        {3, 14, 15}, {2, 13, 15}, {1, 12, 15}, {0, 12, 15}, {3, 13, 15}, {2, 12, 15}, {1, 11, 15}, {0, 11, 15},
-        {3, 12, 14}, {2, 11, 14}, {1, 10, 14}, {0, 10, 14}, {3, 11, 14}, {2, 10, 14}, {1, 9, 14}, {0, 9, 14},
-        {0, 8, 13}, {2, 9, 13}, {1, 8, 13}, {0, 7, 13}, {3, 10, 13}, {2, 8, 13}, {1, 7, 13}, {0, 6, 13},
-        {3, 9, 11}, {2, 7, 11}, {1, 6, 11}, {0, 5, 11}, {3, 8, 10},
-        {2, 6, 10}, {1, 5, 10}, {0, 4, 10}, {3, 7, 9}, {2, 5, 9}, {1, 4, 9}, {0, 3, 9}, {3, 6, 8},
-        {2, 4, 8}, {1, 3, 8}, {0, 2, 8}, {3, 5, 7}, {2, 3, 7}, {3, 4, 6}, {3, 4, 6}, {1, 2, 6},
-        {1, 2, 6}, {0, 1, 6}, {0, 1, 6}, {3, 3, 5}, {3, 3, 5}, {3, 3, 5}, {3, 3, 5}, {2, 2, 3},
-        {1, 1, 2}, {1, 1, 2}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}
-    };
-
-    const static uint8 TotCofNTrail2[84][3] = {{0, 0, 14 /* error */}, {0, 0, 14/*error */}, {3, 15, 13}, {3, 15, 13}, {3, 16, 14}, {2, 16, 14}, {1, 16, 14}, {0, 16, 14},
-        {1, 15, 14}, {0, 15, 14}, {2, 15, 14}, {1, 14, 14}, {2, 14, 13}, {2, 14, 13}, {0, 14, 13}, {0, 14, 13},
-        {3, 14, 13}, {2, 13, 13}, {1, 13, 13}, {0, 13, 13}, {3, 13, 13}, {2, 12, 13}, {1, 12, 13}, {0, 12, 13},
-        {0, 11, 12}, {2, 11, 12}, {1, 11, 12}, {0, 10, 12}, {3, 12, 12}, {2, 10, 12}, {1, 10, 12}, {0, 9, 12},
-        {3, 11, 11}, {2, 9, 11}, {1, 9, 11}, {0, 8, 11}, {3, 10, 11}, {2, 8, 11}, {1, 8, 11}, {0, 7, 11},
-        {3, 9, 9}, {2, 7, 9}, {1, 7, 9}, {0, 6, 9}, {0, 5, 8}, {0, 5, 8}, {2, 6, 8}, {2, 6, 8},
-        {1, 6, 8}, {1, 6, 8}, {0, 4, 8}, {0, 4, 8}, {3, 8, 7}, {2, 5, 7}, {1, 5, 7}, {0, 3, 7},
-        {3, 7, 6}, {3, 7, 6}, {2, 4, 6}, {2, 4, 6}, {1, 4, 6}, {1, 4, 6}, {0, 2, 6}, {0, 2, 6},
-        {3, 6, 6}, {2, 3, 6}, {1, 3, 6}, {0, 1, 6}, {3, 5, 5}, {3, 5, 5}, {1, 2, 5}, {1, 2, 5},
-        {3, 4, 4}, {3, 3, 4}, {2, 2, 3}, {2, 2, 3}, {1, 1, 2}, {1, 1, 2}, {1, 1, 2}, {1, 1, 2},
-        {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}
-    };
-
-    const static uint8 TotCofNTrail3[64][3] = {{0, 0, 10/*error*/}, {0, 16, 10}, {3, 16, 10}, {2, 16, 10}, {1, 16, 10}, {0, 15, 10}, {3, 15, 10},
-        {2, 15, 10}, {1, 15, 10}, {0, 14, 10}, {3, 14, 10}, {2, 14, 10}, {1, 14, 10}, {0, 13, 10}, {1, 13, 9},
-        {1, 13, 9}, {0, 12, 9}, {2, 13, 9}, {1, 12, 9}, {0, 11, 9}, {3, 13, 9}, {2, 12, 9}, {1, 11, 9},
-        {0, 10, 9}, {3, 12, 8}, {2, 11, 8}, {1, 10, 8}, {0, 9, 8}, {3, 11, 8}, {2, 10, 8}, {1, 9, 8},
-        {0, 8, 8}, {0, 7, 7}, {0, 6, 7}, {2, 9, 7}, {0, 5, 7}, {3, 10, 7}, {2, 8, 7}, {1, 8, 7},
-        {0, 4, 7}, {0, 3, 6}, {2, 7, 6}, {1, 7, 6}, {0, 2, 6}, {3, 9, 6}, {2, 6, 6}, {1, 6, 6},
-        {0, 1, 6}, {1, 5, 5}, {2, 5, 5}, {1, 4, 5}, {2, 4, 5}, {1, 3, 5}, {3, 8, 5}, {2, 3, 5},
-        {1, 2, 5}, {3, 7, 4}, {3, 6, 4}, {3, 5, 4}, {3, 4, 4}, {3, 3, 4}, {2, 2, 4}, {1, 1, 4},
-        {0, 0, 4}
-    };
-#endif
-    uint code;
-
-#ifdef PV_NO_CLZ
-    uint8 *pcode;
-    if (nC < 2)
-    {
-        BitstreamShowBits(stream, 16, &code);
-
-        if (code >= 8192)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>13)+65+2][0]);
-        }
-        else if (code >= 2048)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>9)+50+2][0]);
-        }
-        else if (code >= 1024)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>8)+46+2][0]);
-        }
-        else if (code >= 512)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>7)+42+2][0]);
-        }
-        else if (code >= 256)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>6)+38+2][0]);
-        }
-        else if (code >= 128)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>5)+34+2][0]);
-        }
-        else if (code >= 64)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>3)+22+2][0]);
-        }
-        else if (code >= 32)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>2)+14+2][0]);
-        }
-        else if (code >= 16)
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code>>1)+6+2][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotCofNTrail1[(code-2)+2][0]);
-        }
-
-        *TrailingOnes = pcode[0];
-        *TotalCoeff = pcode[1];
-
-        BitstreamFlushBits(stream, pcode[2]);
-    }
-    else if (nC < 4)
-    {
-        BitstreamShowBits(stream, 14, &code);
-
-        if (code >= 4096)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>10)+66+2][0]);
-        }
-        else if (code >= 2048)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>8)+54+2][0]);
-        }
-        else if (code >= 512)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>7)+46+2][0]);
-        }
-        else if (code >= 128)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>5)+34+2][0]);
-        }
-        else if (code >= 64)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>3)+22+2][0]);
-        }
-        else if (code >= 32)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>2)+14+2][0]);
-        }
-        else if (code >= 16)
-        {
-            pcode = (uint8*) & (TotCofNTrail2[(code>>1)+6+2][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotCofNTrail2[code-2+2][0]);
-        }
-        *TrailingOnes = pcode[0];
-        *TotalCoeff = pcode[1];
-
-        BitstreamFlushBits(stream, pcode[2]);
-    }
-    else if (nC < 8)
-    {
-        BitstreamShowBits(stream, 10, &code);
-
-        if (code >= 512)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>6)+47+1][0]);
-        }
-        else if (code >= 256)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>5)+39+1][0]);
-        }
-        else if (code >= 128)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>4)+31+1][0]);
-        }
-        else if (code >= 64)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>3)+23+1][0]);
-        }
-        else if (code >= 32)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>2)+15+1][0]);
-        }
-        else if (code >= 16)
-        {
-            pcode = (uint8*) & (TotCofNTrail3[(code>>1)+7+1][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotCofNTrail3[code-1+1][0]);
-        }
-        *TrailingOnes = pcode[0];
-        *TotalCoeff = pcode[1];
-
-        BitstreamFlushBits(stream, pcode[2]);
-    }
-    else
-    {
-        /* read 6 bit FLC */
-        BitstreamReadBits(stream, 6, &code);
-
-
-        *TrailingOnes = code & 3;
-        *TotalCoeff = (code >> 2) + 1;
-
-        if (*TotalCoeff > 16)
-        {
-            *TotalCoeff = 16;  // _ERROR
-        }
-
-        if (code == 3)
-        {
-            *TrailingOnes = 0;
-            (*TotalCoeff)--;
-        }
-    }
-#else
-    const VLCNumCoeffTrail *ptr;
-    const ShiftOffset *ptr_indx;
-    uint temp, leading_zeros = 0;
-
-    if (nC < 8)
-    {
-
-        BitstreamShowBits(stream, 16, &code);
-        temp = code | 1;
-
-        PV_CLZ(leading_zeros, temp)
-
-        temp = nC_table[nC];
-        ptr_indx = &NumCoeffTrailOnes_indx[temp][leading_zeros];
-        ptr = &NumCoeffTrailOnes[temp][(code >> ptr_indx->shift) + ptr_indx->offset];
-        *TrailingOnes = ptr->trailing;
-        *TotalCoeff = ptr->total_coeff;
-        BitstreamFlushBits(stream, ptr->length);
-    }
-    else
-    {
-        /* read 6 bit FLC */
-        BitstreamReadBits(stream, 6, &code);
-
-
-        *TrailingOnes = code & 3;
-        *TotalCoeff = (code >> 2) + 1;
-
-        if (*TotalCoeff > 16)
-        {
-            *TotalCoeff = 16;  // _ERROR
-        }
-
-        if (code == 3)
-        {
-            *TrailingOnes = 0;
-            (*TotalCoeff)--;
-        }
-    }
-#endif
-    return AVCDEC_SUCCESS;
-}
-
-/* TO BE OPTIMIZED !!!!! */
-AVCDec_Status ce_TotalCoeffTrailingOnesChromaDC(AVCDecBitstream *stream, int *TrailingOnes, int *TotalCoeff)
-{
-    AVCDec_Status status;
-
-    const static uint8 TotCofNTrail5[21][3] =
-    {
-        {3, 4, 7}, {3, 4, 7}, {2, 4, 8}, {1, 4, 8}, {2, 3, 7}, {2, 3, 7}, {1, 3, 7},
-        {1, 3, 7}, {0, 4, 6}, {0, 3, 6}, {0, 2, 6}, {3, 3, 6}, {1, 2, 6}, {0, 1, 6},
-        {2, 2, 3}, {0, 0, 2}, {0, 0, 2}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}
-    };
-
-    uint code;
-    uint8 *pcode;
-
-    status = BitstreamShowBits(stream, 8, &code);
-
-    if (code >= 32)
-    {
-        pcode = (uint8*) & (TotCofNTrail5[(code>>5)+13][0]);
-    }
-    else if (code >= 8)
-    {
-        pcode = (uint8*) & (TotCofNTrail5[(code>>2)+6][0]);
-    }
-    else
-    {
-        pcode = (uint8*) & (TotCofNTrail5[code][0]);
-    }
-
-    *TrailingOnes = pcode[0];
-    *TotalCoeff = pcode[1];
-
-    BitstreamFlushBits(stream, pcode[2]);
-
-    return status;
-}
-
-/* see Table 9-6 */
-AVCDec_Status ce_LevelPrefix(AVCDecBitstream *stream, uint *code)
-{
-    uint temp;
-    uint leading_zeros = 0;
-    BitstreamShowBits(stream, 16, &temp);
-    temp |= 1 ;
-
-    PV_CLZ(leading_zeros, temp)
-
-    BitstreamFlushBits(stream, leading_zeros + 1);
-    *code = leading_zeros;
-    return AVCDEC_SUCCESS;
-}
-
-/* see Table 9-7 and 9-8 */
-AVCDec_Status ce_TotalZeros(AVCDecBitstream *stream, int *code, int TotalCoeff)
-{
-    const static uint8 TotZero1[28][2] = {{15, 9}, {14, 9}, {13, 9}, {12, 8},
-        {12, 8}, {11, 8}, {11, 8}, {10, 7}, {9, 7}, {8, 6}, {8, 6}, {7, 6}, {7, 6}, {6, 5}, {6, 5},
-        {6, 5}, {6, 5}, {5, 5}, {5, 5}, {5, 5}, {5, 5}, {4, 4}, {3, 4},
-        {2, 3}, {2, 3}, {1, 3}, {1, 3}, {0, 1}
-    };
-
-    const static uint8 TotZero2n3[2][18][2] = {{{14, 6}, {13, 6}, {12, 6}, {11, 6},
-            {10, 5}, {10, 5}, {9, 5}, {9, 5}, {8, 4}, {7, 4}, {6, 4}, {5, 4}, {4, 3}, {4, 3},
-            {3, 3}, {2, 3}, {1, 3}, {0, 3}},
-
-        /*const static uint8 TotZero3[18][2]=*/{{13, 6}, {11, 6}, {12, 5}, {12, 5}, {10, 5},
-            {10, 5}, {9, 5}, {9, 5}, {8, 4}, {5, 4}, {4, 4}, {0, 4}, {7, 3}, {7, 3}, {6, 3}, {3, 3},
-            {2, 3}, {1, 3}}
-    };
-
-    const static uint8 TotZero4[17][2] = {{12, 5}, {11, 5}, {10, 5}, {0, 5}, {9, 4},
-        {9, 4}, {7, 4}, {7, 4}, {3, 4}, {3, 4}, {2, 4}, {2, 4}, {8, 3}, {6, 3}, {5, 3}, {4, 3}, {1, 3}
-    };
-
-    const static uint8 TotZero5[13][2] = {{11, 5}, {9, 5}, {10, 4}, {8, 4}, {2, 4},
-        {1, 4}, {0, 4}, {7, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}
-    };
-
-    const static uint8 TotZero6to10[5][15][2] = {{{10, 6}, {0, 6}, {1, 5}, {1, 5}, {8, 4},
-            {8, 4}, {8, 4}, {8, 4}, {9, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}, {2, 3}},
-
-        /*const static uint8 TotZero7[15][2]=*/{{9, 6}, {0, 6}, {1, 5}, {1, 5}, {7, 4},
-            {7, 4}, {7, 4}, {7, 4}, {8, 3}, {6, 3}, {4, 3}, {3, 3}, {2, 3}, {5, 2}, {5, 2}},
-
-        /*const static uint8 TotZero8[15][2]=*/{{8, 6}, {0, 6}, {2, 5}, {2, 5}, {1, 4},
-            {1, 4}, {1, 4}, {1, 4}, {7, 3}, {6, 3}, {3, 3}, {5, 2}, {5, 2}, {4, 2}, {4, 2}},
-
-        /*const static uint8 TotZero9[15][2]=*/{{1, 6}, {0, 6}, {7, 5}, {7, 5}, {2, 4},
-            {2, 4}, {2, 4}, {2, 4}, {5, 3}, {6, 2}, {6, 2}, {4, 2}, {4, 2}, {3, 2}, {3, 2}},
-
-        /*const static uint8 TotZero10[11][2]=*/{{1, 5}, {0, 5}, {6, 4}, {6, 4}, {2, 3},
-            {2, 3}, {2, 3}, {2, 3}, {5, 2}, {4, 2}, {3, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}
-    };
-
-    const static uint8 TotZero11[7][2] = {{0, 4}, {1, 4}, {2, 3}, {2, 3}, {3, 3}, {5, 3}, {4, 1}};
-
-    const static uint8 TotZero12to15[4][5][2] =
-    {
-        {{3, 1}, {2, 2}, {4, 3}, {1, 4}, {0, 4}},
-        {{2, 1}, {3, 2}, {1, 3}, {0, 3}, {0, 0}},
-        {{2, 1}, {1, 2}, {0, 2}, {0, 0}, {0, 0}},
-        {{1, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}}
-    };
-
-    uint temp, mask;
-    int indx;
-    uint8 *pcode;
-
-    if (TotalCoeff == 1)
-    {
-        BitstreamShowBits(stream, 9, &temp);
-
-        if (temp >= 256)
-        {
-            pcode = (uint8*) & (TotZero1[27][0]);
-        }
-        else if (temp >= 64)
-        {
-            pcode = (uint8*) & (TotZero1[(temp>>5)+19][0]);
-        }
-        else if (temp >= 8)
-        {
-            pcode = (uint8*) & (TotZero1[(temp>>2)+5][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero1[temp-1][0]);
-        }
-
-    }
-    else if (TotalCoeff == 2 || TotalCoeff == 3)
-    {
-        BitstreamShowBits(stream, 6, &temp);
-
-        if (temp >= 32)
-        {
-            pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][(temp>>3)+10][0]);
-        }
-        else if (temp >= 8)
-        {
-            pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][(temp>>2)+6][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero2n3[TotalCoeff-2][temp][0]);
-        }
-    }
-    else if (TotalCoeff == 4)
-    {
-        BitstreamShowBits(stream, 5, &temp);
-
-        if (temp >= 12)
-        {
-            pcode = (uint8*) & (TotZero4[(temp>>2)+9][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero4[temp][0]);
-        }
-    }
-    else if (TotalCoeff == 5)
-    {
-        BitstreamShowBits(stream, 5, &temp);
-
-        if (temp >= 16)
-        {
-            pcode = (uint8*) & (TotZero5[(temp>>2)+5][0]);
-        }
-        else if (temp >= 2)
-        {
-            pcode = (uint8*) & (TotZero5[(temp>>1)+1][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero5[temp][0]);
-        }
-    }
-    else if (TotalCoeff >= 6 && TotalCoeff <= 10)
-    {
-        if (TotalCoeff == 10)
-        {
-            BitstreamShowBits(stream, 5, &temp);
-        }
-        else
-        {
-            BitstreamShowBits(stream, 6, &temp);
-        }
-
-
-        if (temp >= 8)
-        {
-            pcode = (uint8*) & (TotZero6to10[TotalCoeff-6][(temp>>3)+7][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero6to10[TotalCoeff-6][temp][0]);
-        }
-    }
-    else if (TotalCoeff == 11)
-    {
-        BitstreamShowBits(stream, 4, &temp);
-
-
-        if (temp >= 8)
-        {
-            pcode = (uint8*) & (TotZero11[6][0]);
-        }
-        else if (temp >= 4)
-        {
-            pcode = (uint8*) & (TotZero11[(temp>>1)+2][0]);
-        }
-        else
-        {
-            pcode = (uint8*) & (TotZero11[temp][0]);
-        }
-    }
-    else
-    {
-        BitstreamShowBits(stream, (16 - TotalCoeff), &temp);
-        mask = 1 << (15 - TotalCoeff);
-        indx = 0;
-        while ((temp&mask) == 0 && indx < (16 - TotalCoeff)) /* search location of 1 bit */
-        {
-            mask >>= 1;
-            indx++;
-        }
-
-        pcode = (uint8*) & (TotZero12to15[TotalCoeff-12][indx]);
-    }
-
-    *code = pcode[0];
-    BitstreamFlushBits(stream, pcode[1]);
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see Table 9-9 */
-AVCDec_Status ce_TotalZerosChromaDC(AVCDecBitstream *stream, int *code, int TotalCoeff)
-{
-    const static uint8 TotZeroChrom1to3[3][8][2] =
-    {
-        {{3, 3}, {2, 3}, {1, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
-        {{2, 2}, {2, 2}, {1, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
-        {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}},
-    };
-
-
-    uint temp;
-    uint8 *pcode;
-
-    BitstreamShowBits(stream, 3, &temp);
-    pcode = (uint8*) & (TotZeroChrom1to3[TotalCoeff-1][temp]);
-
-    *code = pcode[0];
-
-    BitstreamFlushBits(stream, pcode[1]);
-
-    return AVCDEC_SUCCESS;
-}
-
-/* see Table 9-10 */
-AVCDec_Status ce_RunBefore(AVCDecBitstream *stream, int *code, int zerosLeft)
-{
-    const static int codlen[6] = {1, 2, 2, 3, 3, 3}; /* num bits to read */
-    const static uint8 RunBeforeTab[6][8][2] = {{{1, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
-        /*const static int RunBefore2[4][2]=*/{{2, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
-        /*const static int RunBefore3[4][2]=*/{{3, 2}, {2, 2}, {1, 2}, {0, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
-        /*const static int RunBefore4[7][2]=*/{{4, 3}, {3, 3}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {0, 2}, {0, 2}},
-        /*const static int RunBefore5[7][2]=*/{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 2}, {1, 2}, {0, 2}, {0, 2}},
-        /*const static int RunBefore6[7][2]=*/{{1, 3}, {2, 3}, {4, 3}, {3, 3}, {6, 3}, {5, 3}, {0, 2}, {0, 2}}
-    };
-
-    uint temp;
-    uint8 *pcode;
-    int indx;
-
-    if (zerosLeft <= 6)
-    {
-        BitstreamShowBits(stream, codlen[zerosLeft-1], &temp);
-
-        pcode = (uint8*) & (RunBeforeTab[zerosLeft-1][temp][0]);
-
-        *code = pcode[0];
-
-        BitstreamFlushBits(stream, pcode[1]);
-    }
-    else
-    {
-        BitstreamReadBits(stream, 3, &temp);
-        if (temp)
-        {
-            *code = 7 - temp;
-        }
-        else
-        {
-            BitstreamShowBits(stream, 9, &temp);
-            temp <<= 7;
-            temp |= 1;
-            indx = 0;
-            PV_CLZ(indx, temp)
-            *code = 7 + indx;
-            BitstreamFlushBits(stream, indx + 1);
-        }
-    }
-
-
-    return AVCDEC_SUCCESS;
-}
diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c
index dd7c26d..aa52bd9 100644
--- a/media/libstagefright/codecs/common/cmnMemory.c
+++ b/media/libstagefright/codecs/common/cmnMemory.c
@@ -21,10 +21,8 @@
 *******************************************************************************/
 #include "cmnMemory.h"
 
-#include <malloc.h>
-#if defined LINUX
+#include <stdlib.h>
 #include <string.h>
-#endif
 
 //VO_MEM_OPERATOR		g_memOP;
 
diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/libstagefright/codecs/common/include/voType.h
index 70b2e83..5f659ab 100644
--- a/media/libstagefright/codecs/common/include/voType.h
+++ b/media/libstagefright/codecs/common/include/voType.h
@@ -101,7 +101,7 @@
    since the compiler does not support the way the component was written.
 */
 #ifndef VO_SKIP64BIT
-#ifdef _WIN32
+#ifdef _MSC_VER
 /** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
 typedef unsigned __int64  VO_U64;
 /** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index 6e98559..6692533 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -2,20 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-    G711Decoder.cpp
-
-LOCAL_C_INCLUDES := \
-        frameworks/base/media/libstagefright/include \
-
-LOCAL_MODULE := libstagefright_g711dec
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
         SoftG711.cpp
 
 LOCAL_C_INCLUDES := \
diff --git a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp b/media/libstagefright/codecs/g711/dec/G711Decoder.cpp
deleted file mode 100644
index 4414e4e..0000000
--- a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp
+++ /dev/null
@@ -1,213 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "G711Decoder"
-#include <utils/Log.h>
-
-#include "G711Decoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-static const size_t kMaxNumSamplesPerFrame = 16384;
-
-namespace android {
-
-G711Decoder::G711Decoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferGroup(NULL) {
-}
-
-G711Decoder::~G711Decoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t G711Decoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    const char *mime;
-    CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
-
-    mIsMLaw = false;
-    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
-        mIsMLaw = true;
-    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)) {
-        return ERROR_UNSUPPORTED;
-    }
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(
-            new MediaBuffer(kMaxNumSamplesPerFrame * sizeof(int16_t)));
-
-    mSource->start();
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t G711Decoder::stop() {
-    CHECK(mStarted);
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> G711Decoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t numChannels;
-    int32_t sampleRate;
-
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeyChannelCount, numChannels);
-    meta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "G711Decoder");
-
-    return meta;
-}
-
-status_t G711Decoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        CHECK(seekTimeUs >= 0);
-    } else {
-        seekTimeUs = -1;
-    }
-
-    MediaBuffer *inBuffer;
-    err = mSource->read(&inBuffer, options);
-
-    if (err != OK) {
-        return err;
-    }
-
-    if (inBuffer->range_length() > kMaxNumSamplesPerFrame) {
-        LOGE("input buffer too large (%d).", inBuffer->range_length());
-
-        inBuffer->release();
-        inBuffer = NULL;
-
-        return ERROR_UNSUPPORTED;
-    }
-
-    int64_t timeUs;
-    CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
-    const uint8_t *inputPtr =
-        (const uint8_t *)inBuffer->data() + inBuffer->range_offset();
-
-    MediaBuffer *outBuffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&outBuffer), OK);
-
-    if (mIsMLaw) {
-        DecodeMLaw(
-                static_cast<int16_t *>(outBuffer->data()),
-                inputPtr, inBuffer->range_length());
-    } else {
-        DecodeALaw(
-                static_cast<int16_t *>(outBuffer->data()),
-                inputPtr, inBuffer->range_length());
-    }
-
-    // Each 8-bit byte is converted into a 16-bit sample.
-    outBuffer->set_range(0, inBuffer->range_length() * 2);
-
-    outBuffer->meta_data()->setInt64(kKeyTime, timeUs);
-
-    inBuffer->release();
-    inBuffer = NULL;
-
-    *out = outBuffer;
-
-    return OK;
-}
-
-// static
-void G711Decoder::DecodeALaw(
-        int16_t *out, const uint8_t *in, size_t inSize) {
-    while (inSize-- > 0) {
-        int32_t x = *in++;
-
-        int32_t ix = x ^ 0x55;
-        ix &= 0x7f;
-
-        int32_t iexp = ix >> 4;
-        int32_t mant = ix & 0x0f;
-
-        if (iexp > 0) {
-            mant += 16;
-        }
-
-        mant = (mant << 4) + 8;
-
-        if (iexp > 1) {
-            mant = mant << (iexp - 1);
-        }
-
-        *out++ = (x > 127) ? mant : -mant;
-    }
-}
-
-// static
-void G711Decoder::DecodeMLaw(
-        int16_t *out, const uint8_t *in, size_t inSize) {
-    while (inSize-- > 0) {
-        int32_t x = *in++;
-
-        int32_t mantissa = ~x;
-        int32_t exponent = (mantissa >> 4) & 7;
-        int32_t segment = exponent + 1;
-        mantissa &= 0x0f;
-
-        int32_t step = 4 << segment;
-
-        int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
-
-        *out++ = (x < 0x80) ? -abs : abs;
-    }
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index f1bec08..2ffa5f2 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
- 	M4vH263Decoder.cpp \
  	src/adaptive_smooth_no_mmx.cpp \
  	src/bitstream.cpp \
  	src/block_idct.cpp \
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
deleted file mode 100644
index 2bdb3ef..0000000
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ /dev/null
@@ -1,304 +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.
- */
-//#define LOG_NDEBUG 0
-#define LOG_TAG "M4vH263Decoder"
-#include <utils/Log.h>
-#include <stdlib.h> // for free
-#include "ESDS.h"
-#include "M4vH263Decoder.h"
-
-#include "mp4dec_api.h"
-
-#include <OMX_Component.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-M4vH263Decoder::M4vH263Decoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mHandle(new tagvideoDecControls),
-      mInputBuffer(NULL),
-      mNumSamplesOutput(0),
-      mTargetTimeUs(-1) {
-
-    LOGV("M4vH263Decoder");
-    memset(mHandle, 0, sizeof(tagvideoDecControls));
-    mFormat = new MetaData;
-    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
-
-    // CHECK(mSource->getFormat()->findInt32(kKeyWidth, &mWidth));
-    // CHECK(mSource->getFormat()->findInt32(kKeyHeight, &mHeight));
-
-    // We'll ignore the dimension advertised by the source, the decoder
-    // appears to require us to always start with the default dimensions
-    // of 352 x 288 to operate correctly and later react to changes in
-    // the dimensions as needed.
-    mWidth = 352;
-    mHeight = 288;
-
-    mFormat->setInt32(kKeyWidth, mWidth);
-    mFormat->setInt32(kKeyHeight, mHeight);
-    mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
-    mFormat->setCString(kKeyDecoderComponent, "M4vH263Decoder");
-}
-
-M4vH263Decoder::~M4vH263Decoder() {
-    if (mStarted) {
-        stop();
-    }
-
-    delete mHandle;
-    mHandle = NULL;
-}
-
-void M4vH263Decoder::allocateFrames(int32_t width, int32_t height) {
-    size_t frameSize =
-        (((width + 15) & - 16) * ((height + 15) & - 16) * 3) / 2;
-
-    for (uint32_t i = 0; i < 2; ++i) {
-        mFrames[i] = new MediaBuffer(frameSize);
-        mFrames[i]->setObserver(this);
-    }
-
-    PVSetReferenceYUV(
-            mHandle,
-            (uint8_t *)mFrames[1]->data());
-}
-
-status_t M4vH263Decoder::start(MetaData *) {
-    CHECK(!mStarted);
-
-    const char *mime = NULL;
-    sp<MetaData> meta = mSource->getFormat();
-    CHECK(meta->findCString(kKeyMIMEType, &mime));
-
-    MP4DecodingMode mode;
-    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
-        mode = MPEG4_MODE;
-    } else {
-        CHECK(!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime));
-        mode = H263_MODE;
-    }
-
-    uint32_t type;
-    const void *data = NULL;
-    size_t size = 0;
-    uint8_t *vol_data[1] = {0};
-    int32_t vol_size = 0;
-    if (meta->findData(kKeyESDS, &type, &data, &size)) {
-        ESDS esds((const uint8_t *)data, size);
-        CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
-        const void *codec_specific_data;
-        size_t codec_specific_data_size;
-        esds.getCodecSpecificInfo(
-                &codec_specific_data, &codec_specific_data_size);
-
-        vol_data[0] = (uint8_t *) malloc(codec_specific_data_size);
-        memcpy(vol_data[0], codec_specific_data, codec_specific_data_size);
-        vol_size = codec_specific_data_size;
-    } else {
-        vol_data[0] = NULL;
-        vol_size = 0;
-
-    }
-
-    Bool success = PVInitVideoDecoder(
-            mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode);
-    if (vol_data[0]) free(vol_data[0]);
-
-    if (success != PV_TRUE) {
-        LOGW("PVInitVideoDecoder failed. Unsupported content?");
-        return ERROR_UNSUPPORTED;
-    }
-
-    MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
-    if (mode != actualMode) {
-        PVCleanUpVideoDecoder(mHandle);
-        return UNKNOWN_ERROR;
-    }
-
-    PVSetPostProcType((VideoDecControls *) mHandle, 0);
-
-    int32_t width, height;
-    PVGetVideoDimensions(mHandle, &width, &height);
-    if (mode == H263_MODE && (width == 0 || height == 0)) {
-        width = 352;
-        height = 288;
-    }
-    allocateFrames(width, height);
-
-    mSource->start();
-
-    mNumSamplesOutput = 0;
-    mTargetTimeUs = -1;
-    mStarted = true;
-
-    return OK;
-}
-
-status_t M4vH263Decoder::stop() {
-    CHECK(mStarted);
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    mSource->stop();
-
-    releaseFrames();
-
-    mStarted = false;
-    return (PVCleanUpVideoDecoder(mHandle) == PV_TRUE)? OK: UNKNOWN_ERROR;
-}
-
-sp<MetaData> M4vH263Decoder::getFormat() {
-    return mFormat;
-}
-
-status_t M4vH263Decoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    *out = NULL;
-
-    bool seeking = false;
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        seeking = true;
-        CHECK_EQ((int)PVResetVideoDecoder(mHandle), PV_TRUE);
-    }
-
-    MediaBuffer *inputBuffer = NULL;
-    status_t err = mSource->read(&inputBuffer, options);
-    if (err != OK) {
-        return err;
-    }
-
-    if (seeking) {
-        int64_t targetTimeUs;
-        if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
-                && targetTimeUs >= 0) {
-            mTargetTimeUs = targetTimeUs;
-        } else {
-            mTargetTimeUs = -1;
-        }
-    }
-
-    uint8_t *bitstream =
-        (uint8_t *) inputBuffer->data() + inputBuffer->range_offset();
-
-    uint32_t timestamp = 0xFFFFFFFF;
-    int32_t bufferSize = inputBuffer->range_length();
-    uint32_t useExtTimestamp = 0;
-    if (PVDecodeVideoFrame(
-                mHandle, &bitstream, &timestamp, &bufferSize,
-                &useExtTimestamp,
-                (uint8_t *)mFrames[mNumSamplesOutput & 0x01]->data())
-            != PV_TRUE) {
-        LOGE("failed to decode video frame.");
-
-        inputBuffer->release();
-        inputBuffer = NULL;
-
-        return UNKNOWN_ERROR;
-    }
-
-    int32_t disp_width, disp_height;
-    PVGetVideoDimensions(mHandle, &disp_width, &disp_height);
-
-    int32_t buf_width, buf_height;
-    PVGetBufferDimensions(mHandle, &buf_width, &buf_height);
-
-    if (buf_width != mWidth || buf_height != mHeight) {
-        ++mNumSamplesOutput;  // The client will never get to see this frame.
-
-        inputBuffer->release();
-        inputBuffer = NULL;
-
-        mWidth = buf_width;
-        mHeight = buf_height;
-        mFormat->setInt32(kKeyWidth, mWidth);
-        mFormat->setInt32(kKeyHeight, mHeight);
-
-        CHECK_LE(disp_width, buf_width);
-        CHECK_LE(disp_height, buf_height);
-
-        mFormat->setRect(kKeyCropRect, 0, 0, disp_width - 1, disp_height - 1);
-
-        return INFO_FORMAT_CHANGED;
-    }
-
-    int64_t timeUs;
-    CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
-    inputBuffer->release();
-    inputBuffer = NULL;
-
-    bool skipFrame = false;
-
-    if (mTargetTimeUs >= 0) {
-        CHECK(timeUs <= mTargetTimeUs);
-
-        if (timeUs < mTargetTimeUs) {
-            // We're still waiting for the frame with the matching
-            // timestamp and we won't return the current one.
-            skipFrame = true;
-
-            LOGV("skipping frame at %lld us", timeUs);
-        } else {
-            LOGV("found target frame at %lld us", timeUs);
-
-            mTargetTimeUs = -1;
-        }
-    }
-
-    if (skipFrame) {
-        *out = new MediaBuffer(0);
-    } else {
-        *out = mFrames[mNumSamplesOutput & 0x01];
-        (*out)->add_ref();
-        (*out)->meta_data()->setInt64(kKeyTime, timeUs);
-    }
-
-    ++mNumSamplesOutput;
-
-    return OK;
-}
-
-void M4vH263Decoder::releaseFrames() {
-    for (size_t i = 0; i < sizeof(mFrames) / sizeof(mFrames[0]); ++i) {
-        MediaBuffer *buffer = mFrames[i];
-
-        buffer->setObserver(NULL);
-        buffer->release();
-
-        mFrames[i] = NULL;
-    }
-}
-
-void M4vH263Decoder::signalBufferReturned(MediaBuffer *buffer) {
-    LOGV("signalBufferReturned");
-}
-
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index cffbfb5..ddced5f 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -23,11 +23,31 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/IOMX.h>
 
 #include "mp4dec_api.h"
 
 namespace android {
 
+static const CodecProfileLevel kM4VProfileLevels[] = {
+    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 },
+    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b },
+    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 },
+    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 },
+    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 },
+};
+
+static const CodecProfileLevel kH263ProfileLevels[] = {
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 },
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 },
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 },
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
+    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level10 },
+    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level20 },
+    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level30 },
+    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level45 },
+};
+
 template<class T>
 static void InitOMXParams(T *params) {
     params->nSize = sizeof(T);
@@ -181,6 +201,39 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamVideoProfileLevelQuerySupported:
+        {
+            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+                    (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
+
+            if (profileLevel->nPortIndex != 0) {  // Input port only
+                LOGE("Invalid port index: %ld", profileLevel->nPortIndex);
+                return OMX_ErrorUnsupportedIndex;
+            }
+
+            size_t index = profileLevel->nProfileIndex;
+            if (mMode == MODE_H263) {
+                size_t nProfileLevels =
+                    sizeof(kH263ProfileLevels) / sizeof(kH263ProfileLevels[0]);
+                if (index >= nProfileLevels) {
+                    return OMX_ErrorNoMore;
+                }
+
+                profileLevel->eProfile = kH263ProfileLevels[index].mProfile;
+                profileLevel->eLevel = kH263ProfileLevels[index].mLevel;
+            } else {
+                size_t nProfileLevels =
+                    sizeof(kM4VProfileLevels) / sizeof(kM4VProfileLevels[0]);
+                if (index >= nProfileLevels) {
+                    return OMX_ErrorNoMore;
+                }
+
+                profileLevel->eProfile = kM4VProfileLevels[index].mProfile;
+                profileLevel->eLevel = kM4VProfileLevels[index].mLevel;
+            }
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalGetParameter(index, params);
     }
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 229988e..a08c9f0 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        MP3Decoder.cpp \
 	src/pvmp3_normalize.cpp \
  	src/pvmp3_alias_reduction.cpp \
  	src/pvmp3_crc.cpp \
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
deleted file mode 100644
index 0ba42ff..0000000
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ /dev/null
@@ -1,226 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MP3Decoder"
-
-#include "MP3Decoder.h"
-
-#include "include/pvmp3decoder_api.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mNumChannels(0),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mConfig(new tPVMP3DecoderExternal),
-      mDecoderBuf(NULL),
-      mAnchorTimeUs(0),
-      mNumFramesOutput(0),
-      mInputBuffer(NULL) {
-    init();
-}
-
-void MP3Decoder::init() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t sampleRate;
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
-    mMeta = new MetaData;
-    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    mMeta->setInt32(kKeyChannelCount, mNumChannels);
-    mMeta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        mMeta->setInt64(kKeyDuration, durationUs);
-    }
-
-    mMeta->setCString(kKeyDecoderComponent, "MP3Decoder");
-}
-
-MP3Decoder::~MP3Decoder() {
-    if (mStarted) {
-        stop();
-    }
-
-    delete mConfig;
-    mConfig = NULL;
-}
-
-status_t MP3Decoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(new MediaBuffer(4608 * 2));
-
-    mConfig->equalizerType = flat;
-    mConfig->crcEnabled = false;
-
-    uint32_t memRequirements = pvmp3_decoderMemRequirements();
-    mDecoderBuf = malloc(memRequirements);
-
-    pvmp3_InitDecoder(mConfig, mDecoderBuf);
-
-    mSource->start();
-
-    mAnchorTimeUs = 0;
-    mNumFramesOutput = 0;
-    mStarted = true;
-
-    return OK;
-}
-
-status_t MP3Decoder::stop() {
-    CHECK(mStarted);
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    free(mDecoderBuf);
-    mDecoderBuf = NULL;
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> MP3Decoder::getFormat() {
-    return mMeta;
-}
-
-status_t MP3Decoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        CHECK(seekTimeUs >= 0);
-
-        mNumFramesOutput = 0;
-
-        if (mInputBuffer) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-
-        // Make sure that the next buffer output does not still
-        // depend on fragments from the last one decoded.
-        pvmp3_InitDecoder(mConfig, mDecoderBuf);
-    } else {
-        seekTimeUs = -1;
-    }
-
-    if (mInputBuffer == NULL) {
-        err = mSource->read(&mInputBuffer, options);
-
-        if (err != OK) {
-            return err;
-        }
-
-        int64_t timeUs;
-        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
-            mAnchorTimeUs = timeUs;
-            mNumFramesOutput = 0;
-        } else {
-            // We must have a new timestamp after seeking.
-            CHECK(seekTimeUs < 0);
-        }
-    }
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
-    mConfig->pInputBuffer =
-        (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
-    mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
-    mConfig->inputBufferMaxLength = 0;
-    mConfig->inputBufferUsedLength = 0;
-
-    mConfig->outputFrameSize = buffer->size() / sizeof(int16_t);
-    mConfig->pOutputBuffer = static_cast<int16_t *>(buffer->data());
-
-    ERROR_CODE decoderErr;
-    if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
-            != NO_DECODING_ERROR) {
-        LOGV("mp3 decoder returned error %d", decoderErr);
-
-        if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR ||
-                mConfig->outputFrameSize == 0) {
-
-            if (mConfig->outputFrameSize == 0) {
-                LOGE("Output frame size is 0");
-            }
-            buffer->release();
-            buffer = NULL;
-
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
-            return UNKNOWN_ERROR;
-        }
-
-        // This is recoverable, just ignore the current frame and
-        // play silence instead.
-        memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
-        mConfig->inputBufferUsedLength = mInputBuffer->range_length();
-    }
-
-    buffer->set_range(
-            0, mConfig->outputFrameSize * sizeof(int16_t));
-
-    mInputBuffer->set_range(
-            mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
-            mInputBuffer->range_length() - mConfig->inputBufferUsedLength);
-
-    if (mInputBuffer->range_length() == 0) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    buffer->meta_data()->setInt64(
-            kKeyTime,
-            mAnchorTimeUs
-                + (mNumFramesOutput * 1000000) / mConfig->samplingRate);
-
-    mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
-
-    *out = buffer;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 832b885..32bbd6b 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -2,24 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        VPXDecoder.cpp  \
-
-LOCAL_MODULE := libstagefright_vpxdec
-
-LOCAL_C_INCLUDES := \
-        $(TOP)/frameworks/base/media/libstagefright/include \
-        frameworks/base/include/media/stagefright/openmax \
-        $(TOP)/external/libvpx \
-        $(TOP)/external/libvpx/vpx_codec \
-        $(TOP)/external/libvpx/vpx_ports
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
         SoftVPX.cpp
 
 LOCAL_C_INCLUDES := \
@@ -30,7 +12,6 @@
         frameworks/base/include/media/stagefright/openmax \
 
 LOCAL_STATIC_LIBRARIES := \
-        libstagefright_vpxdec \
         libvpx
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
deleted file mode 100644
index 489e5ad..0000000
--- a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
+++ /dev/null
@@ -1,277 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VPXDecoder"
-#include <utils/Log.h>
-
-#include "VPXDecoder.h"
-
-#include <OMX_Component.h>
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-#include "vpx/vpx_decoder.h"
-#include "vpx/vpx_codec.h"
-#include "vpx/vp8dx.h"
-
-namespace android {
-
-VPXDecoder::VPXDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferSize(0),
-      mCtx(NULL),
-      mBufferGroup(NULL),
-      mTargetTimeUs(-1) {
-    sp<MetaData> inputFormat = source->getFormat();
-    const char *mime;
-    CHECK(inputFormat->findCString(kKeyMIMEType, &mime));
-    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX));
-
-    CHECK(inputFormat->findInt32(kKeyWidth, &mWidth));
-    CHECK(inputFormat->findInt32(kKeyHeight, &mHeight));
-
-    mBufferSize = (mWidth * mHeight * 3) / 2;
-
-    mFormat = new MetaData;
-    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
-    mFormat->setInt32(kKeyWidth, mWidth);
-    mFormat->setInt32(kKeyHeight, mHeight);
-    mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
-    mFormat->setCString(kKeyDecoderComponent, "VPXDecoder");
-
-    int64_t durationUs;
-    if (inputFormat->findInt64(kKeyDuration, &durationUs)) {
-        mFormat->setInt64(kKeyDuration, durationUs);
-    }
-}
-
-VPXDecoder::~VPXDecoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t VPXDecoder::start(MetaData *) {
-    if (mStarted) {
-        return UNKNOWN_ERROR;
-    }
-
-    status_t err = mSource->start();
-
-    if (err != OK) {
-        return err;
-    }
-
-    mCtx = new vpx_codec_ctx_t;
-    vpx_codec_err_t vpx_err;
-    if ((vpx_err = vpx_codec_dec_init(
-                (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0))) {
-        LOGE("on2 decoder failed to initialize. (%d)", vpx_err);
-
-        mSource->stop();
-
-        return UNKNOWN_ERROR;
-    }
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-
-    mTargetTimeUs = -1;
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t VPXDecoder::stop() {
-    if (!mStarted) {
-        return UNKNOWN_ERROR;
-    }
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
-    delete (vpx_codec_ctx_t *)mCtx;
-    mCtx = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> VPXDecoder::getFormat() {
-    return mFormat;
-}
-
-status_t VPXDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    *out = NULL;
-
-    bool seeking = false;
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode seekMode;
-    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
-        seeking = true;
-    }
-
-    MediaBuffer *input;
-    status_t err = mSource->read(&input, options);
-
-    if (err != OK) {
-        return err;
-    }
-
-    LOGV("read %d bytes from source\n", input->range_length());
-
-    if (seeking) {
-        int64_t targetTimeUs;
-        if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
-                && targetTimeUs >= 0) {
-            mTargetTimeUs = targetTimeUs;
-        } else {
-            mTargetTimeUs = -1;
-        }
-    }
-
-    if (vpx_codec_decode(
-                (vpx_codec_ctx_t *)mCtx,
-                (uint8_t *)input->data() + input->range_offset(),
-                input->range_length(),
-                NULL,
-                0)) {
-        LOGE("on2 decoder failed to decode frame.");
-        input->release();
-        input = NULL;
-
-        return UNKNOWN_ERROR;
-    }
-
-    LOGV("successfully decoded 1 or more frames.");
-
-    int64_t timeUs;
-    CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs));
-
-    input->release();
-    input = NULL;
-
-    bool skipFrame = false;
-
-    if (mTargetTimeUs >= 0) {
-        CHECK(timeUs <= mTargetTimeUs);
-
-        if (timeUs < mTargetTimeUs) {
-            // We're still waiting for the frame with the matching
-            // timestamp and we won't return the current one.
-            skipFrame = true;
-
-            LOGV("skipping frame at %lld us", timeUs);
-        } else {
-            LOGV("found target frame at %lld us", timeUs);
-
-            mTargetTimeUs = -1;
-        }
-    }
-
-    if (skipFrame) {
-        *out = new MediaBuffer(0);
-        return OK;
-    }
-
-    vpx_codec_iter_t iter = NULL;
-    vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
-
-    if (img == NULL) {
-        // The VPX format supports "internal-only" frames that are
-        // referenced by future content but never actually displayed, so
-        // this is a perfectly valid scenario.
-
-        *out = new MediaBuffer(0);
-        return OK;
-    }
-
-    CHECK_EQ(img->fmt, IMG_FMT_I420);
-
-    int32_t width = img->d_w;
-    int32_t height = img->d_h;
-
-    if (width != mWidth || height != mHeight) {
-        LOGI("Image dimensions changed, width = %d, height = %d",
-             width, height);
-
-        mWidth = width;
-        mHeight = height;
-        mFormat->setInt32(kKeyWidth, width);
-        mFormat->setInt32(kKeyHeight, height);
-
-        mBufferSize = (mWidth * mHeight * 3) / 2;
-        delete mBufferGroup;
-        mBufferGroup = new MediaBufferGroup;
-        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-
-        return INFO_FORMAT_CHANGED;
-    }
-
-    MediaBuffer *output;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK);
-
-    const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
-    uint8_t *dst = (uint8_t *)output->data();
-    for (size_t i = 0; i < img->d_h; ++i) {
-        memcpy(dst, srcLine, img->d_w);
-
-        srcLine += img->stride[PLANE_Y];
-        dst += img->d_w;
-    }
-
-    srcLine = (const uint8_t *)img->planes[PLANE_U];
-    for (size_t i = 0; i < img->d_h / 2; ++i) {
-        memcpy(dst, srcLine, img->d_w / 2);
-
-        srcLine += img->stride[PLANE_U];
-        dst += img->d_w / 2;
-    }
-
-    srcLine = (const uint8_t *)img->planes[PLANE_V];
-    for (size_t i = 0; i < img->d_h / 2; ++i) {
-        memcpy(dst, srcLine, img->d_w / 2);
-
-        srcLine += img->stride[PLANE_V];
-        dst += img->d_w / 2;
-    }
-
-    output->set_range(0, (width * height * 3) / 2);
-
-    output->meta_data()->setInt64(kKeyTime, timeUs);
-
-    *out = output;
-
-    return OK;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index ec7bd1c..740c957 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -23,10 +23,30 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/IOMX.h>
 
 
 namespace android {
 
+static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1  },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3  },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5  },
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
+};
+
 template<class T>
 static void InitOMXParams(T *params) {
     params->nSize = sizeof(T);
@@ -177,6 +197,28 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamVideoProfileLevelQuerySupported:
+        {
+            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+                    (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
+
+            if (profileLevel->nPortIndex != kInputPortIndex) {
+                LOGE("Invalid port index: %ld", profileLevel->nPortIndex);
+                return OMX_ErrorUnsupportedIndex;
+            }
+
+            size_t index = profileLevel->nProfileIndex;
+            size_t nProfileLevels =
+                    sizeof(kProfileLevels) / sizeof(kProfileLevels[0]);
+            if (index >= nProfileLevels) {
+                return OMX_ErrorNoMore;
+            }
+
+            profileLevel->eProfile = kProfileLevels[index].mProfile;
+            profileLevel->eLevel = kProfileLevels[index].mLevel;
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalGetParameter(index, params);
     }
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 9251229..f33f3ac 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -2,21 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        VorbisDecoder.cpp \
-
-LOCAL_C_INCLUDES := \
-        frameworks/base/media/libstagefright/include \
-        external/tremolo \
-
-LOCAL_MODULE := libstagefright_vorbisdec
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
         SoftVorbis.cpp
 
 LOCAL_C_INCLUDES := \
@@ -24,9 +9,6 @@
         frameworks/base/media/libstagefright/include \
         frameworks/base/include/media/stagefright/openmax \
 
-LOCAL_STATIC_LIBRARIES := \
-        libstagefright_vorbisdec
-
 LOCAL_SHARED_LIBRARIES := \
         libvorbisidec libstagefright libstagefright_omx \
         libstagefright_foundation libutils
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
deleted file mode 100644
index e14fb95..0000000
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ /dev/null
@@ -1,275 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisDecoder"
-#include <utils/Log.h>
-
-#include "VorbisDecoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-extern "C" {
-    #include <Tremolo/codec_internal.h>
-
-    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
-    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
-    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
-}
-
-namespace android {
-
-VorbisDecoder::VorbisDecoder(const sp<MediaSource> &source)
-    : mSource(source),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mAnchorTimeUs(0),
-      mNumFramesOutput(0),
-      mState(NULL),
-      mVi(NULL) {
-    sp<MetaData> srcFormat = mSource->getFormat();
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
-    CHECK(srcFormat->findInt32(kKeySampleRate, &mSampleRate));
-}
-
-VorbisDecoder::~VorbisDecoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-static void makeBitReader(
-        const void *data, size_t size,
-        ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
-    buf->data = (uint8_t *)data;
-    buf->size = size;
-    buf->refcount = 1;
-    buf->ptr.owner = NULL;
-
-    ref->buffer = buf;
-    ref->begin = 0;
-    ref->length = size;
-    ref->next = NULL;
-
-    oggpack_readinit(bits, ref);
-}
-
-status_t VorbisDecoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(
-            new MediaBuffer(kMaxNumSamplesPerBuffer * sizeof(int16_t)));
-
-    mSource->start();
-
-    sp<MetaData> meta = mSource->getFormat();
-
-    mVi = new vorbis_info;
-    vorbis_info_init(mVi);
-
-    ///////////////////////////////////////////////////////////////////////////
-
-    uint32_t type;
-    const void *data;
-    size_t size;
-    CHECK(meta->findData(kKeyVorbisInfo, &type, &data, &size));
-
-    ogg_buffer buf;
-    ogg_reference ref;
-    oggpack_buffer bits;
-    makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
-    CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits));
-
-    ///////////////////////////////////////////////////////////////////////////
-
-    CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
-
-    makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
-    CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits));
-
-    ///////////////////////////////////////////////////////////////////////////
-
-    mState = new vorbis_dsp_state;
-    CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
-
-    mAnchorTimeUs = 0;
-    mNumFramesOutput = 0;
-
-    // If the source never limits the number of valid frames contained
-    // in the input data, we'll assume that all of the decoded frames are
-    // valid.
-    mNumFramesLeftOnPage = -1;
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t VorbisDecoder::stop() {
-    CHECK(mStarted);
-
-    vorbis_dsp_clear(mState);
-    delete mState;
-    mState = NULL;
-
-    vorbis_info_clear(mVi);
-    delete mVi;
-    mVi = NULL;
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    mSource->stop();
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> VorbisDecoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeyChannelCount, mNumChannels);
-    meta->setInt32(kKeySampleRate, mSampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "VorbisDecoder");
-
-    return meta;
-}
-
-int VorbisDecoder::decodePacket(MediaBuffer *packet, MediaBuffer *out) {
-    ogg_buffer buf;
-    buf.data = (uint8_t *)packet->data() + packet->range_offset();
-    buf.size = packet->range_length();
-    buf.refcount = 1;
-    buf.ptr.owner = NULL;
-
-    ogg_reference ref;
-    ref.buffer = &buf;
-    ref.begin = 0;
-    ref.length = packet->range_length();
-    ref.next = NULL;
-
-    ogg_packet pack;
-    pack.packet = &ref;
-    pack.bytes = packet->range_length();
-    pack.b_o_s = 0;
-    pack.e_o_s = 0;
-    pack.granulepos = 0;
-    pack.packetno = 0;
-
-    int numFrames = 0;
-
-    int err = vorbis_dsp_synthesis(mState, &pack, 1);
-    if (err != 0) {
-        LOGW("vorbis_dsp_synthesis returned %d", err);
-    } else {
-        numFrames = vorbis_dsp_pcmout(
-                mState, (int16_t *)out->data(), kMaxNumSamplesPerBuffer);
-
-        if (numFrames < 0) {
-            LOGE("vorbis_dsp_pcmout returned %d", numFrames);
-            numFrames = 0;
-        }
-    }
-
-    if (mNumFramesLeftOnPage >= 0) {
-        if (numFrames > mNumFramesLeftOnPage) {
-            LOGV("discarding %d frames at end of page",
-                 numFrames - mNumFramesLeftOnPage);
-            numFrames = mNumFramesLeftOnPage;
-        }
-        mNumFramesLeftOnPage -= numFrames;
-    }
-
-    out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
-
-    return numFrames;
-}
-
-status_t VorbisDecoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        CHECK(seekTimeUs >= 0);
-
-        mNumFramesOutput = 0;
-        vorbis_dsp_restart(mState);
-    } else {
-        seekTimeUs = -1;
-    }
-
-    MediaBuffer *inputBuffer;
-    err = mSource->read(&inputBuffer, options);
-
-    if (err != OK) {
-        return ERROR_END_OF_STREAM;
-    }
-
-    int64_t timeUs;
-    if (inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
-        mAnchorTimeUs = timeUs;
-        mNumFramesOutput = 0;
-    } else {
-        // We must have a new timestamp after seeking.
-        CHECK(seekTimeUs < 0);
-    }
-
-    int32_t numPageSamples;
-    if (inputBuffer->meta_data()->findInt32(
-                kKeyValidSamples, &numPageSamples)) {
-        CHECK(numPageSamples >= 0);
-        mNumFramesLeftOnPage = numPageSamples;
-    }
-
-    MediaBuffer *outputBuffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&outputBuffer), OK);
-
-    int numFrames = decodePacket(inputBuffer, outputBuffer);
-
-    inputBuffer->release();
-    inputBuffer = NULL;
-
-    outputBuffer->meta_data()->setInt64(
-            kKeyTime,
-            mAnchorTimeUs
-                + (mNumFramesOutput * 1000000ll) / mSampleRate);
-
-    mNumFramesOutput += numFrames;
-
-    *out = outputBuffer;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4ca32d..3246021 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -93,6 +93,11 @@
             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
             | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
 
+    CHECK_EQ(0,
+            native_window_set_scaling_mode(
+            mNativeWindow.get(),
+            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
+
     // Width must be multiple of 32???
     CHECK_EQ(0, native_window_set_buffers_geometry(
                 mNativeWindow.get(),
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 8ecc17c..90d64ba 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -36,11 +36,10 @@
 
 #include <ctype.h>
 #include <openssl/aes.h>
+#include <openssl/md5.h>
 
 namespace android {
 
-const int64_t LiveSession::kMaxPlaylistAgeUs = 15000000ll;
-
 LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
     : mFlags(flags),
       mUIDValid(uidValid),
@@ -59,7 +58,8 @@
       mDurationUs(-1),
       mSeekDone(false),
       mDisconnectPending(false),
-      mMonitorQueueGeneration(0) {
+      mMonitorQueueGeneration(0),
+      mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) {
     if (mUIDValid) {
         mHTTPDataSource->setUID(mUID);
     }
@@ -175,7 +175,8 @@
 
     mMasterURL = url;
 
-    sp<M3UParser> playlist = fetchPlaylist(url.c_str());
+    bool dummy;
+    sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
 
     if (playlist == NULL) {
         LOGE("unable to fetch master playlist '%s'.", url.c_str());
@@ -289,7 +290,9 @@
     return OK;
 }
 
-sp<M3UParser> LiveSession::fetchPlaylist(const char *url) {
+sp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
+    *unchanged = false;
+
     sp<ABuffer> buffer;
     status_t err = fetchFile(url, &buffer);
 
@@ -297,6 +300,38 @@
         return NULL;
     }
 
+    // MD5 functionality is not available on the simulator, treat all
+    // playlists as changed.
+
+#if defined(HAVE_ANDROID_OS)
+    uint8_t hash[16];
+
+    MD5_CTX m;
+    MD5_Init(&m);
+    MD5_Update(&m, buffer->data(), buffer->size());
+
+    MD5_Final(hash, &m);
+
+    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
+        // playlist unchanged
+
+        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
+            mRefreshState = (RefreshState)(mRefreshState + 1);
+        }
+
+        *unchanged = true;
+
+        LOGV("Playlist unchanged, refresh state is now %d",
+             (int)mRefreshState);
+
+        return NULL;
+    }
+
+    memcpy(mPlaylistHash, hash, sizeof(hash));
+
+    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
+#endif
+
     sp<M3UParser> playlist =
         new M3UParser(url, buffer->data(), buffer->size());
 
@@ -384,6 +419,63 @@
     return index;
 }
 
+bool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
+    if (mPlaylist == NULL) {
+        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
+        return true;
+    }
+
+    int32_t targetDurationSecs;
+    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+
+    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
+
+    int64_t minPlaylistAgeUs;
+
+    switch (mRefreshState) {
+        case INITIAL_MINIMUM_RELOAD_DELAY:
+        {
+            size_t n = mPlaylist->size();
+            if (n > 0) {
+                sp<AMessage> itemMeta;
+                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
+
+                int64_t itemDurationUs;
+                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+                minPlaylistAgeUs = itemDurationUs;
+                break;
+            }
+
+            // fall through
+        }
+
+        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
+        {
+            minPlaylistAgeUs = targetDurationUs / 2;
+            break;
+        }
+
+        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
+        {
+            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
+            break;
+        }
+
+        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
+        {
+            minPlaylistAgeUs = targetDurationUs * 3;
+            break;
+        }
+
+        default:
+            TRESPASS();
+            break;
+    }
+
+    return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
+}
+
 void LiveSession::onDownloadNext() {
     size_t bandwidthIndex = getBandwidthIndex();
 
@@ -392,8 +484,7 @@
 
     if (mLastPlaylistFetchTimeUs < 0
             || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
-            || (!mPlaylist->isComplete()
-                && mLastPlaylistFetchTimeUs + kMaxPlaylistAgeUs <= nowUs)) {
+            || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
         AString url;
         if (mBandwidthItems.size() > 0) {
             url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
@@ -403,11 +494,25 @@
 
         bool firstTime = (mPlaylist == NULL);
 
-        mPlaylist = fetchPlaylist(url.c_str());
-        if (mPlaylist == NULL) {
-            LOGE("failed to load playlist at url '%s'", url.c_str());
-            mDataSource->queueEOS(ERROR_IO);
-            return;
+        if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
+            // If we switch bandwidths, do not pay any heed to whether
+            // playlists changed since the last time...
+            mPlaylist.clear();
+        }
+
+        bool unchanged;
+        sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
+        if (playlist == NULL) {
+            if (unchanged) {
+                // We succeeded in fetching the playlist, but it was
+                // unchanged from the last time we tried.
+            } else {
+                LOGE("failed to load playlist at url '%s'", url.c_str());
+                mDataSource->queueEOS(ERROR_IO);
+                return;
+            }
+        } else {
+            mPlaylist = playlist;
         }
 
         if (firstTime) {
@@ -680,7 +785,10 @@
             keySource->setUID(mUID);
         }
 
-        status_t err = keySource->connect(keyURI.c_str());
+        status_t err =
+            keySource->connect(
+                    keyURI.c_str(),
+                    mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
 
         if (err == OK) {
             size_t offset = 0;
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 123fbf8..9df9f59 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -106,21 +106,38 @@
         return true;
     }
 
-    size_t n = strlen(baseURL);
-    if (baseURL[n - 1] == '/') {
-        out->setTo(baseURL);
-        out->append(url);
-    } else {
-        const char *slashPos = strrchr(baseURL, '/');
+    if (url[0] == '/') {
+        // URL is an absolute path.
 
-        if (slashPos > &baseURL[6]) {
-            out->setTo(baseURL, slashPos - baseURL);
+        char *protocolEnd = strstr(baseURL, "//") + 2;
+        char *pathStart = strchr(protocolEnd, '/');
+
+        if (pathStart != NULL) {
+            out->setTo(baseURL, pathStart - baseURL);
         } else {
             out->setTo(baseURL);
         }
 
-        out->append("/");
         out->append(url);
+    } else {
+        // URL is a relative path
+
+        size_t n = strlen(baseURL);
+        if (baseURL[n - 1] == '/') {
+            out->setTo(baseURL);
+            out->append(url);
+        } else {
+            const char *slashPos = strrchr(baseURL, '/');
+
+            if (slashPos > &baseURL[6]) {
+                out->setTo(baseURL, slashPos - baseURL);
+            } else {
+                out->setTo(baseURL);
+            }
+
+            out->append("/");
+            out->append(url);
+        }
     }
 
     LOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index e069b4d..95f2ae8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -291,7 +291,7 @@
     void finishSeekIfNecessary(int64_t videoTimeUs);
     void ensureCacheIsFetching_l();
 
-    status_t startAudioPlayer_l();
+    status_t startAudioPlayer_l(bool sendErrorNotification = true);
     void postAudioSeekComplete_l();
 
     void shutdownVideoDecoder_l();
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index d833e2e..18f8913 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -51,6 +51,8 @@
 
     virtual String8 getMIMEType() const;
 
+    virtual status_t reconnectAtOffset(off64_t offset);
+
 protected:
     virtual ~ChromiumHTTPDataSource();
 
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 2e25dd9..0e9af69 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -53,6 +53,8 @@
 
     static sp<HTTPBase> Create(uint32_t flags = 0);
 
+    static void RegisterSocketUser(int s, uid_t uid);
+
 protected:
     void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
 
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
deleted file mode 100644
index 88ba9d6..0000000
--- a/media/libstagefright/include/HTTPStream.h
+++ /dev/null
@@ -1,91 +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 HTTP_STREAM_H_
-
-#define HTTP_STREAM_H_
-
-#include <sys/types.h>
-
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class HTTPStream {
-public:
-    HTTPStream();
-    ~HTTPStream();
-
-    void setUID(uid_t uid);
-
-    status_t connect(const char *server, int port = -1, bool https = false);
-    status_t disconnect();
-
-    status_t send(const char *data, size_t size);
-
-    // Assumes data is a '\0' terminated string.
-    status_t send(const char *data);
-
-    // Receive up to "size" bytes of data.
-    ssize_t receive(void *data, size_t size);
-
-    status_t receive_header(int *http_status);
-
-    // The header key used to retrieve the status line.
-    static const char *kStatusKey;
-
-    bool find_header_value(
-            const AString &key, AString *value) const;
-
-    // Pass a negative value to disable the timeout.
-    void setReceiveTimeout(int seconds);
-
-    // Receive a line of data terminated by CRLF, line will be '\0' terminated
-    // _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,
-        CONNECTING,
-        CONNECTED
-    };
-
-    State mState;
-    Mutex mLock;
-
-    bool mUIDValid;
-    uid_t mUID;
-
-    int mSocket;
-
-    KeyedVector<AString, AString> mHeaders;
-
-    void *mSSLContext;
-    void *mSSL;
-
-    HTTPStream(const HTTPStream &);
-    HTTPStream &operator=(const HTTPStream &);
-};
-
-}  // namespace android
-
-#endif  // HTTP_STREAM_H_
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 188ef5e..116ed0e 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -62,8 +62,6 @@
         kMaxNumRetries         = 5,
     };
 
-    static const int64_t kMaxPlaylistAgeUs;
-
     enum {
         kWhatConnect        = 'conn',
         kWhatDisconnect     = 'disc',
@@ -106,6 +104,16 @@
 
     int32_t mMonitorQueueGeneration;
 
+    enum RefreshState {
+        INITIAL_MINIMUM_RELOAD_DELAY,
+        FIRST_UNCHANGED_RELOAD_ATTEMPT,
+        SECOND_UNCHANGED_RELOAD_ATTEMPT,
+        THIRD_UNCHANGED_RELOAD_ATTEMPT
+    };
+    RefreshState mRefreshState;
+
+    uint8_t mPlaylistHash[16];
+
     void onConnect(const sp<AMessage> &msg);
     void onDisconnect();
     void onDownloadNext();
@@ -113,7 +121,7 @@
     void onSeek(const sp<AMessage> &msg);
 
     status_t fetchFile(const char *url, sp<ABuffer> *out);
-    sp<M3UParser> fetchPlaylist(const char *url);
+    sp<M3UParser> fetchPlaylist(const char *url, bool *unchanged);
     size_t getBandwidthIndex();
 
     status_t decryptBuffer(
@@ -121,6 +129,8 @@
 
     void postMonitorQueue(int64_t delayUs = 0);
 
+    bool timeToRefreshPlaylist(int64_t nowUs) const;
+
     static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *);
 
     DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 2d6cb84..22b2855 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -77,6 +77,10 @@
         kWhatRead       = 'read',
     };
 
+    enum {
+        kMaxNumRetries = 10,
+    };
+
     sp<DataSource> mSource;
     sp<AHandlerReflector<NuCachedSource2> > mReflector;
     sp<ALooper> mLooper;
@@ -93,6 +97,8 @@
     bool mFetching;
     int64_t mLastFetchTimeUs;
 
+    int32_t mNumRetriesLeft;
+
     void onMessageReceived(const sp<AMessage> &msg);
     void onFetch();
     void onRead(const sp<AMessage> &msg);
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
deleted file mode 100644
index c265b3a..0000000
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ /dev/null
@@ -1,114 +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 NU_HTTP_DATA_SOURCE_H_
-
-#define NU_HTTP_DATA_SOURCE_H_
-
-#include <utils/List.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-
-#include "HTTPStream.h"
-#include "include/HTTPBase.h"
-
-namespace android {
-
-struct NuHTTPDataSource : public HTTPBase {
-    NuHTTPDataSource(uint32_t flags = 0);
-
-    virtual status_t connect(
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL,
-            off64_t offset = 0);
-
-    virtual void disconnect();
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-    virtual status_t getSize(off64_t *size);
-    virtual uint32_t flags();
-
-    virtual sp<DecryptHandle> DrmInitialization();
-    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
-    virtual String8 getUri();
-
-    virtual String8 getMIMEType() const;
-
-protected:
-    virtual ~NuHTTPDataSource();
-
-private:
-    enum State {
-        DISCONNECTED,
-        CONNECTING,
-        CONNECTED
-    };
-
-    Mutex mLock;
-
-    uint32_t mFlags;
-
-    State mState;
-
-    String8 mHost;
-    unsigned mPort;
-    String8 mPath;
-    bool mHTTPS;
-    String8 mHeaders;
-    String8 mUri;
-
-    HTTPStream mHTTP;
-    off64_t mOffset;
-    off64_t mContentLength;
-    bool mContentLengthValid;
-    bool mHasChunkedTransferEncoding;
-
-    String8 mContentType;
-
-    // The number of data bytes in the current chunk before any subsequent
-    // chunk header (or -1 if no more chunks).
-    ssize_t mChunkDataBytesLeft;
-
-    sp<DecryptHandle> mDecryptHandle;
-    DrmManagerClient *mDrmManagerClient;
-
-    status_t connect(
-            const char *uri, const String8 &headers, off64_t offset);
-
-    status_t connect(
-            const char *host, unsigned port, const char *path,
-            bool https,
-            const String8 &headers,
-            off64_t offset);
-
-    // Read up to "size" bytes of data, respect transfer encoding.
-    ssize_t internalRead(void *data, size_t size);
-
-    void applyTimeoutResponse();
-
-    static void MakeFullHeaders(
-            const KeyedVector<String8, String8> *overrides,
-            String8 *headers);
-
-    NuHTTPDataSource(const NuHTTPDataSource &);
-    NuHTTPDataSource &operator=(const NuHTTPDataSource &);
-};
-
-}  // namespace android
-
-#endif  // NU_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index ec3e5fa..d54b1c1 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -121,6 +121,7 @@
     virtual ~OMX();
 
 private:
+    struct CallbackDispatcherThread;
     struct CallbackDispatcher;
 
     Mutex mLock;
diff --git a/media/libstagefright/include/ThreadedSource.h b/media/libstagefright/include/ThreadedSource.h
deleted file mode 100644
index c67295c..0000000
--- a/media/libstagefright/include/ThreadedSource.h
+++ /dev/null
@@ -1,73 +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 THREADED_SOURCE_H_
-
-#define THREADED_SOURCE_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/AHandlerReflector.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/MediaSource.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct ThreadedSource : public MediaSource {
-    ThreadedSource(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
-    virtual ~ThreadedSource();
-
-private:
-    enum {
-        kWhatDecodeMore = 'deco',
-        kWhatSeek       = 'seek',
-    };
-
-    sp<MediaSource> mSource;
-    sp<AHandlerReflector<ThreadedSource> > mReflector;
-    sp<ALooper> mLooper;
-
-    Mutex mLock;
-    Condition mCondition;
-    List<MediaBuffer *> mQueue;
-    status_t mFinalResult;
-    bool mDecodePending;
-    bool mStarted;
-
-    int64_t mSeekTimeUs;
-    ReadOptions::SeekMode mSeekMode;
-
-    void postDecodeMore_l();
-    void clearQueue_l();
-
-    DISALLOW_EVIL_CONSTRUCTORS(ThreadedSource);
-};
-
-}  // namespace android
-
-#endif  // THREADED_SOURCE_H_
diff --git a/media/libstagefright/include/XINGSeeker.h b/media/libstagefright/include/XINGSeeker.h
index d5a484e..ec5bd9b 100644
--- a/media/libstagefright/include/XINGSeeker.h
+++ b/media/libstagefright/include/XINGSeeker.h
@@ -37,7 +37,7 @@
     int32_t mSizeBytes;
 
     // TOC entries in XING header. Skip the first one since it's always 0.
-    char mTableOfContents[99];
+    unsigned char mTableOfContents[99];
 
     XINGSeeker();
 
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index d23aa3a..bc24dbb 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -20,8 +20,6 @@
 
 #include <dlfcn.h>
 
-#include <sys/prctl.h>
-
 #include "../include/OMX.h"
 
 #include "../include/OMXNodeInstance.h"
@@ -38,11 +36,32 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+// This provides the underlying Thread used by CallbackDispatcher.
+// Note that deriving CallbackDispatcher from Thread does not work.
+
+struct OMX::CallbackDispatcherThread : public Thread {
+    CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+        : mDispatcher(dispatcher) {
+    }
+
+private:
+    CallbackDispatcher *mDispatcher;
+
+    bool threadLoop();
+
+    CallbackDispatcherThread(const CallbackDispatcherThread &);
+    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
 struct OMX::CallbackDispatcher : public RefBase {
     CallbackDispatcher(OMXNodeInstance *owner);
 
     void post(const omx_message &msg);
 
+    bool loop();
+
 protected:
     virtual ~CallbackDispatcher();
 
@@ -54,13 +73,10 @@
     Condition mQueueChanged;
     List<omx_message> mQueue;
 
-    pthread_t mThread;
+    sp<CallbackDispatcherThread> mThread;
 
     void dispatch(const omx_message &msg);
 
-    static void *ThreadWrapper(void *me);
-    void threadEntry();
-
     CallbackDispatcher(const CallbackDispatcher &);
     CallbackDispatcher &operator=(const CallbackDispatcher &);
 };
@@ -68,13 +84,8 @@
 OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
     : mOwner(owner),
       mDone(false) {
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-    pthread_create(&mThread, &attr, ThreadWrapper, this);
-
-    pthread_attr_destroy(&attr);
+    mThread = new CallbackDispatcherThread(this);
+    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_AUDIO);
 }
 
 OMX::CallbackDispatcher::~CallbackDispatcher() {
@@ -85,11 +96,14 @@
         mQueueChanged.signal();
     }
 
-    // Don't call join on myself
-    CHECK(mThread != pthread_self());
-
-    void *dummy;
-    pthread_join(mThread, &dummy);
+    // A join on self can happen if the last ref to CallbackDispatcher
+    // is released within the CallbackDispatcherThread loop
+    status_t status = mThread->join();
+    if (status != WOULD_BLOCK) {
+        // Other than join to self, the only other error return codes are
+        // whatever readyToRun() returns, and we don't override that
+        CHECK_EQ(status, NO_ERROR);
+    }
 }
 
 void OMX::CallbackDispatcher::post(const omx_message &msg) {
@@ -107,17 +121,7 @@
     mOwner->onMessage(msg);
 }
 
-// static
-void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
-    static_cast<CallbackDispatcher *>(me)->threadEntry();
-
-    return NULL;
-}
-
-void OMX::CallbackDispatcher::threadEntry() {
-    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
-    prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
-
+bool OMX::CallbackDispatcher::loop() {
     for (;;) {
         omx_message msg;
 
@@ -137,6 +141,14 @@
 
         dispatch(msg);
     }
+
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool OMX::CallbackDispatcherThread::threadLoop() {
+    return mDispatcher->loop();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 504d470..c8278ab 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -57,6 +57,9 @@
     typedef OMXPluginBase *(*CreateOMXPluginFunc)();
     CreateOMXPluginFunc createOMXPlugin =
         (CreateOMXPluginFunc)dlsym(
+                mVendorLibHandle, "createOMXPlugin");
+    if (!createOMXPlugin)
+        createOMXPlugin = (CreateOMXPluginFunc)dlsym(
                 mVendorLibHandle, "_ZN7android15createOMXPluginEv");
 
     if (createOMXPlugin) {
@@ -96,11 +99,19 @@
 void OMXMaster::clearPlugins() {
     Mutex::Autolock autoLock(mLock);
 
+    typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
+    DestroyOMXPluginFunc destroyOMXPlugin =
+        (DestroyOMXPluginFunc)dlsym(
+                mVendorLibHandle, "destroyOMXPlugin");
+
     mPluginByComponentName.clear();
 
     for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
-         it != mPlugins.end(); ++it) {
-        delete *it;
+            it != mPlugins.end(); ++it) {
+        if (destroyOMXPlugin)
+            destroyOMXPlugin(*it);
+        else
+            delete *it;
         *it = NULL;
     }
 
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 02b1c8e..1e33f05f 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -38,7 +38,6 @@
     { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
     { "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },
     { "OMX.google.h264.decoder", "h264dec", "video_decoder.avc" },
-    { "OMX.google.avc.decoder", "avcdec", "video_decoder.avc" },
     { "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" },
     { "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },
     { "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 072d6b2..b398c9d 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -34,7 +34,7 @@
 #include <openssl/md5.h>
 #include <sys/socket.h>
 
-#include "HTTPStream.h"
+#include "HTTPBase.h"
 
 namespace android {
 
@@ -251,7 +251,7 @@
     mSocket = socket(AF_INET, SOCK_STREAM, 0);
 
     if (mUIDValid) {
-        HTTPStream::RegisterSocketUser(mSocket, mUID);
+        HTTPBase::RegisterSocketUser(mSocket, mUID);
     }
 
     MakeSocketBlocking(mSocket, false);
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 3188959..71d68f61 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -40,7 +40,7 @@
 #include <sys/socket.h>
 #include <netdb.h>
 
-#include "HTTPStream.h"
+#include "HTTPBase.h"
 
 // If no access units are received within 5 secs, assume that the rtp
 // stream has ended and signal end of stream.
@@ -1181,8 +1181,8 @@
                     &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
 
             if (mUIDValid) {
-                HTTPStream::RegisterSocketUser(info->mRTPSocket, mUID);
-                HTTPStream::RegisterSocketUser(info->mRTCPSocket, mUID);
+                HTTPBase::RegisterSocketUser(info->mRTPSocket, mUID);
+                HTTPBase::RegisterSocketUser(info->mRTCPSocket, mUID);
             }
 
             request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
new file mode 100644
index 0000000..3ea8f39
--- /dev/null
+++ b/media/libstagefright/tests/Android.mk
@@ -0,0 +1,53 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_MODULE := SurfaceMediaSource_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+    SurfaceMediaSource_test.cpp \
+	DummyRecorder.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libEGL \
+	libGLESv2 \
+	libandroid \
+	libbinder \
+	libcutils \
+	libgui \
+	libstlport \
+	libui \
+	libutils \
+	libstagefright \
+	libstagefright_omx \
+	libstagefright_foundation \
+
+LOCAL_STATIC_LIBRARIES := \
+	libgtest \
+	libgtest_main \
+
+LOCAL_C_INCLUDES := \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport \
+	frameworks/base/media/libstagefright \
+	frameworks/base/media/libstagefright/include \
+	$(TOP)/frameworks/base/include/media/stagefright/openmax \
+
+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/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp
new file mode 100644
index 0000000..8d75d6b
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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_TAG "DummyRecorder"
+// #define LOG_NDEBUG 0
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include "DummyRecorder.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+void *DummyRecorder::threadWrapper(void *pthis) {
+    LOGV("ThreadWrapper: %p", pthis);
+    DummyRecorder *writer = static_cast<DummyRecorder *>(pthis);
+    writer->readFromSource();
+    return NULL;
+}
+
+
+status_t DummyRecorder::start() {
+    LOGV("Start");
+    mStarted = true;
+
+    mSource->start();
+
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    int err = pthread_create(&mThread, &attr, threadWrapper, this);
+    pthread_attr_destroy(&attr);
+
+    if (err) {
+        LOGE("Error creating thread!");
+        return -ENODEV;
+    }
+    return OK;
+}
+
+
+status_t DummyRecorder::stop() {
+    LOGV("Stop");
+    mStarted = false;
+
+    mSource->stop();
+    void *dummy;
+    pthread_join(mThread, &dummy);
+    status_t err = (status_t) dummy;
+
+    LOGV("Ending the reading thread");
+    return err;
+}
+
+// pretend to read the source buffers
+void DummyRecorder::readFromSource() {
+    LOGV("ReadFromSource");
+    if (!mStarted) {
+        return;
+    }
+
+    status_t err = OK;
+    MediaBuffer *buffer;
+    LOGV("A fake writer accessing the frames");
+    while (mStarted && (err = mSource->read(&buffer)) == OK){
+        // if not getting a valid buffer from source, then exit
+        if (buffer == NULL) {
+            return;
+        }
+        buffer->release();
+        buffer = NULL;
+    }
+}
+
+
+} // end of namespace android
diff --git a/media/libstagefright/tests/DummyRecorder.h b/media/libstagefright/tests/DummyRecorder.h
new file mode 100644
index 0000000..1cbea1b
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.h
@@ -0,0 +1,58 @@
+/*
+ * 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 DUMMY_RECORDER_H_
+#define DUMMY_RECORDER_H_
+
+#include <pthread.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+
+namespace android {
+
+class MediaSource;
+class MediaBuffer;
+
+class DummyRecorder {
+    public:
+    // The media source from which this will receive frames
+    sp<MediaSource> mSource;
+    bool mStarted;
+    pthread_t mThread;
+
+    status_t start();
+    status_t stop();
+
+    // actual entry point for the thread
+    void readFromSource();
+
+    // static function to wrap the actual thread entry point
+    static void *threadWrapper(void *pthis);
+
+    DummyRecorder(const sp<MediaSource> &source) : mSource(source)
+                                                    , mStarted(false) {}
+    ~DummyRecorder( ) {}
+
+    private:
+
+    DISALLOW_EVIL_CONSTRUCTORS(DummyRecorder);
+};
+
+} // end of namespace android
+#endif
+
+
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
new file mode 100644
index 0000000..dc6f2c9
--- /dev/null
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -0,0 +1,348 @@
+/*
+ * 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_TAG "SurfaceMediaSource_test"
+// #define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+
+#include <media/stagefright/SurfaceMediaSource.h>
+
+#include <gui/SurfaceTextureClient.h>
+#include <ui/GraphicBuffer.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
+#include <binder/ProcessState.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <OMX_Component.h>
+
+#include "DummyRecorder.h"
+
+namespace android {
+
+
+class SurfaceMediaSourceTest : public ::testing::Test {
+public:
+
+    SurfaceMediaSourceTest( ): mYuvTexWidth(64), mYuvTexHeight(66) { }
+    sp<MPEG4Writer>  setUpWriter(OMXClient &client );
+    void oneBufferPass(int width, int height );
+    static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ;
+    static void fillYV12BufferRect(uint8_t* buf, int w, int h,
+                        int stride, const android_native_rect_t& rect) ;
+protected:
+
+    virtual void SetUp() {
+        mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+        mSMS->setSynchronousMode(true);
+        mSTC = new SurfaceTextureClient(mSMS);
+        mANW = mSTC;
+
+    }
+
+
+    virtual void TearDown() {
+        mSMS.clear();
+        mSTC.clear();
+        mANW.clear();
+    }
+
+    const int mYuvTexWidth;
+    const int mYuvTexHeight;
+
+    sp<SurfaceMediaSource> mSMS;
+    sp<SurfaceTextureClient> mSTC;
+    sp<ANativeWindow> mANW;
+
+};
+
+void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
+    LOGV("One Buffer Pass");
+    ANativeWindowBuffer* anb;
+    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_TRUE(anb != NULL);
+
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+    // Fill the buffer with the a checkerboard pattern
+    uint8_t* img = NULL;
+    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
+    buf->unlock();
+
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+}
+
+sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) {
+    // Writing to a file
+    const char *fileName = "/sdcard/outputSurfEnc.mp4";
+    sp<MetaData> enc_meta = new MetaData;
+    enc_meta->setInt32(kKeyBitRate, 300000);
+    enc_meta->setInt32(kKeyFrameRate, 30);
+
+    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+
+    sp<MetaData> meta = mSMS->getFormat();
+
+    int32_t width, height, stride, sliceHeight, colorFormat;
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+    CHECK(meta->findInt32(kKeyStride, &stride));
+    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
+    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
+
+    enc_meta->setInt32(kKeyWidth, width);
+    enc_meta->setInt32(kKeyHeight, height);
+    enc_meta->setInt32(kKeyIFramesInterval, 1);
+    enc_meta->setInt32(kKeyStride, stride);
+    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
+    // TODO: overwriting the colorformat since the format set by GRAlloc
+    // could be wrong or not be read by OMX
+    enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+
+
+    sp<MediaSource> encoder =
+        OMXCodec::Create(
+                client.interface(), enc_meta, true /* createEncoder */, mSMS);
+
+    sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
+    writer->addSource(encoder);
+
+    return writer;
+}
+
+// Fill a YV12 buffer with a multi-colored checkerboard pattern
+void SurfaceMediaSourceTest::fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int yuvTexOffsetY = 0;
+    int yuvTexStrideY = stride;
+    int yuvTexOffsetV = yuvTexStrideY * h;
+    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+    int yuvTexStrideU = yuvTexStrideV;
+    for (int x = 0; x < w; x++) {
+        for (int y = 0; y < h; y++) {
+            int parityX = (x / blockWidth) & 1;
+            int parityY = (y / blockHeight) & 1;
+            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+            if (x < w / 2 && y < h / 2) {
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
+                if (x * 2 < w / 2 && y * 2 < h / 2) {
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
+                        intensity;
+                }
+            }
+        }
+    }
+}
+
+// Fill a YV12 buffer with red outside a given rectangle and green inside it.
+void SurfaceMediaSourceTest::fillYV12BufferRect(uint8_t* buf, int w,
+                  int h, int stride, const android_native_rect_t& rect) {
+    const int yuvTexOffsetY = 0;
+    int yuvTexStrideY = stride;
+    int yuvTexOffsetV = yuvTexStrideY * h;
+    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+    int yuvTexStrideU = yuvTexStrideV;
+    for (int x = 0; x < w; x++) {
+        for (int y = 0; y < h; y++) {
+            bool inside = rect.left <= x && x < rect.right &&
+                    rect.top <= y && y < rect.bottom;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
+            if (x < w / 2 && y < h / 2) {
+                bool inside = rect.left <= 2*x && 2*x < rect.right &&
+                        rect.top <= 2*y && 2*y < rect.bottom;
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
+                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
+                                                inside ? 16 : 255;
+            }
+        }
+    }
+}  ///////// End of class SurfaceMediaSourceTest
+
+///////////////////////////////////////////////////////////////////
+// Class to imitate the recording     /////////////////////////////
+// ////////////////////////////////////////////////////////////////
+struct SimpleDummyRecorder {
+        sp<MediaSource> mSource;
+
+        SimpleDummyRecorder
+                (const sp<MediaSource> &source): mSource(source) {}
+
+        status_t start() { return mSource->start();}
+        status_t stop()  { return mSource->stop();}
+
+        // fakes reading from a media source
+        status_t readFromSource() {
+            MediaBuffer *buffer;
+            status_t err = mSource->read(&buffer);
+            if (err != OK) {
+                return err;
+            }
+            buffer->release();
+            buffer = NULL;
+            return OK;
+        }
+};
+
+///////////////////////////////////////////////////////////////////
+//           TESTS
+// Just pass one buffer from the native_window to the SurfaceMediaSource
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
+    LOGV("Testing OneBufferPass ******************************");
+
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+}
+
+// Pass the buffer with the wrong height and weight and should not be accepted
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
+    LOGV("Testing Wrong size BufferPass ******************************");
+
+    // setting the client side buffer size different than the server size
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+             10, 10, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    ANativeWindowBuffer* anb;
+
+    // make sure we get an error back when dequeuing!
+    ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+}
+
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder *********************");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    SimpleDummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount < 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+        ASSERT_EQ(NO_ERROR, writer.readFromSource());
+
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// Delayed pass of multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    SimpleDummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 1;
+    const int FRAMES_LAG = mSMS->getBufferCount() - 1;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+        // Forcing the writer to lag behind a few frames
+        if (nFramesCount > FRAMES_LAG) {
+            ASSERT_EQ(NO_ERROR, writer.readFromSource());
+        }
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassThreaded) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    DummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// Test to examine the actual encoding. Temporarily disabled till the
+// colorformat and encoding from GRAlloc data is resolved
+TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
+    LOGV("Testing the whole pipeline with actual Recorder");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    OMXClient client;
+    CHECK_EQ(OK, client.connect());
+
+    sp<MPEG4Writer> writer = setUpWriter(client);
+    int64_t start = systemTime();
+    CHECK_EQ(OK, writer->start());
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+        nFramesCount++;
+    }
+
+    CHECK_EQ(OK, writer->stop());
+    writer.clear();
+    int64_t end = systemTime();
+    client.disconnect();
+}
+
+
+} // namespace android
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 817eac05..20225ba 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -345,56 +345,28 @@
 
 #ifdef MTP_DEVICE 
 int MtpDataPacket::read(int fd) {
-    // first read the header
-    int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
-    if (ret != MTP_CONTAINER_HEADER_SIZE)
+    int ret = ::read(fd, mBuffer, mBufferSize);
+    if (ret < MTP_CONTAINER_HEADER_SIZE)
         return -1;
-    // then the following data
-    int total = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
-    allocate(total);
-    int remaining = total - MTP_CONTAINER_HEADER_SIZE;
-    ret = ::read(fd, &mBuffer[0] + MTP_CONTAINER_HEADER_SIZE, remaining);
-    if (ret != remaining)
-        return -1;
-
-    mPacketSize = total;
+    mPacketSize = ret;
     mOffset = MTP_CONTAINER_HEADER_SIZE;
-    return total;
-}
-
-int MtpDataPacket::readDataHeader(int fd) {
-    int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
-    if (ret > 0)
-        mPacketSize = ret;
-    else
-        mPacketSize = 0;
     return ret;
 }
 
 int MtpDataPacket::write(int fd) {
     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-    // send header separately from data
-    int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
-    if (ret == MTP_CONTAINER_HEADER_SIZE)
-        ret = ::write(fd, mBuffer + MTP_CONTAINER_HEADER_SIZE,
-                        mPacketSize - MTP_CONTAINER_HEADER_SIZE);
-    return (ret < 0 ? ret : 0);
-}
-
-int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
-    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
-    MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-    int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
+    int ret = ::write(fd, mBuffer, mPacketSize);
     return (ret < 0 ? ret : 0);
 }
 
 int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
-    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length + MTP_CONTAINER_HEADER_SIZE);
+    allocate(length);
+    memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);
+    length += MTP_CONTAINER_HEADER_SIZE;
+    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-    int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
-    if (ret == MTP_CONTAINER_HEADER_SIZE)
-        ret = ::write(fd, data, length);
+    int ret = ::write(fd, mBuffer, length);
     return (ret < 0 ? ret : 0);
 }
 
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 8a08948..2b81063 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -41,6 +41,7 @@
     void                setOperationCode(MtpOperationCode code);
     void                setTransactionID(MtpTransactionID id);
 
+    inline const uint8_t*     getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
     inline uint8_t      getUInt8() { return (uint8_t)mBuffer[mOffset++]; }
     inline int8_t       getInt8() { return (int8_t)mBuffer[mOffset++]; }
     uint16_t            getUInt16();
@@ -95,11 +96,9 @@
 #ifdef MTP_DEVICE
     // fill our buffer with data from the given file descriptor
     int                 read(int fd);
-    int                 readDataHeader(int fd);
 
     // write our data to the given file descriptor
     int                 write(int fd);
-    int                 writeDataHeader(int fd, uint32_t length);
     int                 writeData(int fd, void* data, uint32_t length);
 #endif
 
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 4047e2e..a9b539b 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -731,14 +731,12 @@
     }
     mfr.offset = 0;
     mfr.length = fileLength;
-
-    // send data header
-    mData.setOperationCode(mRequest.getOperationCode());
-    mData.setTransactionID(mRequest.getTransactionID());
-    mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE);
+    mfr.command = mRequest.getOperationCode();
+    mfr.transaction_id = mRequest.getTransactionID();
 
     // then transfer the file
-    int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr);
+    int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
+    LOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
     close(mfr.fd);
     if (ret < 0) {
         if (errno == ECANCELED)
@@ -798,15 +796,13 @@
     }
     mfr.offset = offset;
     mfr.length = length;
+    mfr.command = mRequest.getOperationCode();
+    mfr.transaction_id = mRequest.getTransactionID();
     mResponse.setParameter(1, length);
 
-    // send data header
-    mData.setOperationCode(mRequest.getOperationCode());
-    mData.setTransactionID(mRequest.getTransactionID());
-    mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE);
-
-    // then transfer the file
-    int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr);
+    // transfer the file
+    int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
+    LOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
     close(mfr.fd);
     if (ret < 0) {
         if (errno == ECANCELED)
@@ -918,7 +914,7 @@
         return MTP_RESPONSE_GENERAL_ERROR;
     MtpResponseCode result = MTP_RESPONSE_OK;
     mode_t mask;
-    int ret;
+    int ret, initialData;
 
     if (mSendObjectHandle == kInvalidObjectHandle) {
         LOGE("Expected SendObjectInfo before SendObject");
@@ -926,12 +922,13 @@
         goto done;
     }
 
-    // read the header
-    ret = mData.readDataHeader(mFD);
-    // FIXME - check for errors here.
-
-    // reset so we don't attempt to send this back
-    mData.reset();
+    // read the header, and possibly some data
+    ret = mData.read(mFD);
+    if (ret < MTP_CONTAINER_HEADER_SIZE) {
+        result = MTP_RESPONSE_GENERAL_ERROR;
+        goto done;
+    }
+    initialData = ret - MTP_CONTAINER_HEADER_SIZE;
 
     mtp_file_range  mfr;
     mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC);
@@ -945,16 +942,20 @@
     fchmod(mfr.fd, mFilePermission);
     umask(mask);
 
-    mfr.offset = 0;
-    mfr.length = mSendObjectFileSize;
+    if (initialData > 0)
+        ret = write(mfr.fd, mData.getData(), initialData);
 
-    LOGV("receiving %s\n", (const char *)mSendObjectFilePath);
-    // transfer the file
-    ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+    if (mSendObjectFileSize - initialData > 0) {
+        mfr.offset = initialData;
+        mfr.length = mSendObjectFileSize - initialData;
+
+        LOGV("receiving %s\n", (const char *)mSendObjectFilePath);
+        // transfer the file
+        ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+        LOGV("MTP_RECEIVE_FILE returned %d\n", ret);
+    }
     close(mfr.fd);
 
-    LOGV("MTP_RECEIVE_FILE returned %d", ret);
-
     if (ret < 0) {
         unlink(mSendObjectFilePath);
         if (errno == ECANCELED)
@@ -964,6 +965,9 @@
     }
 
 done:
+    // reset so we don't attempt to send the data back
+    mData.reset();
+
     mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
             result == MTP_RESPONSE_OK);
     mSendObjectHandle = kInvalidObjectHandle;
@@ -1096,23 +1100,31 @@
         return MTP_RESPONSE_GENERAL_ERROR;
     }
 
-    // read the header
-    int ret = mData.readDataHeader(mFD);
-    // FIXME - check for errors here.
-
-    // reset so we don't attempt to send this back
-    mData.reset();
-
     const char* filePath = (const char *)edit->mPath;
-    LOGV("receiving partial %s %lld %ld\n", filePath, offset, length);
-    mtp_file_range  mfr;
-    mfr.fd = edit->mFD;
-    mfr.offset = offset;
-    mfr.length = length;
+    LOGV("receiving partial %s %lld %lld\n", filePath, offset, length);
 
-    // transfer the file
-    ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
-    LOGV("MTP_RECEIVE_FILE returned %d", ret);
+    // read the header, and possibly some data
+    int ret = mData.read(mFD);
+    if (ret < MTP_CONTAINER_HEADER_SIZE)
+        return MTP_RESPONSE_GENERAL_ERROR;
+    int initialData = ret - MTP_CONTAINER_HEADER_SIZE;
+
+    if (initialData > 0) {
+        ret = write(edit->mFD, mData.getData(), initialData);
+        offset += initialData;
+        length -= initialData;
+    }
+
+    if (length > 0) {
+        mtp_file_range  mfr;
+        mfr.fd = edit->mFD;
+        mfr.offset = offset;
+        mfr.length = length;
+
+        // transfer the file
+        ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+        LOGV("MTP_RECEIVE_FILE returned %d", ret);
+    }
     if (ret < 0) {
         mResponse.setParameter(1, 0);
         if (errno == ECANCELED)
@@ -1120,6 +1132,9 @@
         else
             return MTP_RESPONSE_GENERAL_ERROR;
     }
+
+    // reset so we don't attempt to send this back
+    mData.reset();
     mResponse.setParameter(1, length);
     uint64_t end = offset + length;
     if (end > edit->mSize) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java
index 59783e5..4d517db 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java
@@ -91,8 +91,12 @@
         assertEquals("AudioType Mismatch ", audioCodecType, mvi.getAudioType());
         assertEquals("Audio Sampling " + mvi.getAudioSamplingFrequency(),
             audioSamplingFrequency, mvi.getAudioSamplingFrequency());
-        assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel,
-            mvi.getAudioChannels());
+        // PV SW AAC codec always returns number of channels as Stereo.
+        // So we do not assert for number of audio channels for AAC_LC
+        if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
+            assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel,
+                mvi.getAudioChannels());
+        }
     }
 
     protected void validateAudioProperties(int audioCodecType, int duration,
@@ -103,8 +107,12 @@
             duration, aT.getDuration(), 10));
         assertEquals("Audio Sampling " + aT.getAudioSamplingFrequency(),
             audioSamplingFrequency, aT.getAudioSamplingFrequency());
-        assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel,
-            aT.getAudioChannels());
+        // PV SW AAC codec always returns number of channels as Stereo.
+        // So we do not assert for number of audio channels for AAC_LC
+        if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
+            assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel,
+                aT.getAudioChannels());
+        }
     }
 
     protected void validateImageProperties(int aspectRatio, int fileType,
diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp
index 2c0e88e..36fc9bf 100644
--- a/native/android/native_window.cpp
+++ b/native/android/native_window.cpp
@@ -76,44 +76,22 @@
 
 int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width,
         int32_t height, int32_t format) {
-    return native_window_set_buffers_geometry(window, width, height, format);
+    int32_t err = native_window_set_buffers_geometry(window, width, height, format);
+    if (!err) {
+        int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+        if (width && height) {
+            mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+        }
+        err = native_window_set_scaling_mode(window, mode);
+    }
+    return err;
 }
 
 int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
         ARect* inOutDirtyBounds) {
-    int type = -1;
-    if (window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &type) != 0 ||
-            type != NATIVE_WINDOW_SURFACE) {
-        return BAD_VALUE;
-    }
-
-    Region dirtyRegion;
-    Region* dirtyParam = NULL;
-    if (inOutDirtyBounds != NULL) {
-        dirtyRegion.set(*(Rect*)inOutDirtyBounds);
-        dirtyParam = &dirtyRegion;
-    }
-    
-    Surface::SurfaceInfo info;
-    status_t res = static_cast<Surface*>(window)->lock(&info, dirtyParam);
-    if (res != OK) {
-        return -1;
-    }
-    
-    outBuffer->width = (int32_t)info.w;
-    outBuffer->height = (int32_t)info.h;
-    outBuffer->stride = (int32_t)info.s;
-    outBuffer->format = (int32_t)info.format;
-    outBuffer->bits = info.bits;
-    
-    if (inOutDirtyBounds != NULL) {
-        *inOutDirtyBounds = dirtyRegion.getBounds();
-    }
-    
-    return 0;
+    return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds);
 }
 
 int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) {
-    status_t res = static_cast<Surface*>(window)->unlockAndPost();
-    return res == android::OK ? 0 : -1;
+    return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
 }
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 0d8ea28..7a0dcd3 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -415,8 +415,7 @@
     AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
     AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
     AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
-    AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER = 4,
-    AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS = 5,
+    AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
 };
 
 /*
diff --git a/native/include/android/native_window.h b/native/include/android/native_window.h
index 337fa96..2f4f2d3 100644
--- a/native/include/android/native_window.h
+++ b/native/include/android/native_window.h
@@ -99,10 +99,16 @@
  * width and height must be either both zero or both non-zero.
  *
  */
-int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format);
+int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
+        int32_t width, int32_t height, int32_t format);
 
 /**
  * Lock the window's next drawing surface for writing.
+ * inOutDirtyBounds is used as an in/out parameter, upon entering the
+ * function, it contains the dirty region, that is, the region the caller
+ * intends to redraw. When the function returns, inOutDirtyBounds is updated
+ * with the actual area the caller needs to redraw -- this region is often
+ * extended by ANativeWindow_lock.
  */
 int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
         ARect* inOutDirtyBounds);
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index e0c38b1..99cbb86 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -67,7 +67,11 @@
 
     /** get service handles */
     private static void initService() {
-        sService = sAdapter.getNfcAdapterExtrasInterface();
+        final INfcAdapterExtras service = sAdapter.getNfcAdapterExtrasInterface();
+        if (service != null) {
+            // Leave stale rather than receive a null value.
+            sService = service;
+        }
     }
 
     /**
@@ -84,18 +88,19 @@
             if (sSingleton == null) {
                 try {
                     sAdapter = adapter;
-                    sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
                     sSingleton = new NfcAdapterExtras();
                     sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
+                    sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
                     sRouteOnWhenScreenOn = new CardEmulationRoute(
                             CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
                     initService();
                 } finally {
-                    if (sSingleton == null) {
-                        sService = null;
-                        sEmbeddedEe = null;
-                        sRouteOff = null;
+                    if (sService == null) {
                         sRouteOnWhenScreenOn = null;
+                        sRouteOff = null;
+                        sEmbeddedEe = null;
+                        sSingleton = null;
+                        sAdapter = null;
                     }
                 }
             }
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 1123e16..6a199db 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -226,7 +226,7 @@
 #ifndef EGL_ANDROID_image_native_buffer
 #define EGL_ANDROID_image_native_buffer 1
 struct ANativeWindowBuffer;
-#define EGL_NATIVE_BUFFER_ANDROID       0x3140  /* eglCreateImageKHR target */
+#define EGL_NATIVE_BUFFER_ANDROID               0x3140  /* eglCreateImageKHR target */
 #endif
 
 #ifndef EGL_ANDROID_swap_rectangle
@@ -237,6 +237,11 @@
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
 #endif
 
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID                  0x3142  /* EGLConfig attribute */
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/specs/EGL_ANDROID_recordable.txt b/opengl/specs/EGL_ANDROID_recordable.txt
index cf44465..8dbd26f 100644
--- a/opengl/specs/EGL_ANDROID_recordable.txt
+++ b/opengl/specs/EGL_ANDROID_recordable.txt
@@ -55,7 +55,7 @@
     Accepted by the <attribute> parameter of eglGetConfigAttrib and
     the <attrib_list> parameter of eglChooseConfig:
 
-        EGL_RECORDABLE_ANDROID                      0xXXXX
+        EGL_RECORDABLE_ANDROID                      0x3142
 
 Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
 
@@ -103,11 +103,38 @@
 
     RESOLVED: It should not affect sorting.  Some implementations may not have
     any drawback associated with using a recordable EGLConfig.  Such
-    implementations should not have to double-up some of their configs to  one sort earlier than .
-    Implementations that do have drawbacks can use the existing caveat
-    mechanism to report this drawback to the client.
+    implementations should not have to double-up some of their configs to  one
+    sort earlier than .  Implementations that do have drawbacks can use the
+    existing caveat mechanism to report this drawback to the client.
+
+    3. How is this extension expected to be implemented?
+
+    RESPONSE: There are two basic approaches to implementing this extension
+    that were considered during its design.  In both cases it is assumed that a
+    color space conversion must be performed at some point because most video
+    encoding formats use a YUV color space.  The two approaches are
+    distinguished by the point at which this color space conversion is
+    performed.
+
+    One approach involves performing the color space conversion as part of the
+    eglSwapBuffers call before queuing the rendered image to the ANativeWindow.
+    In this case, the VisualID of the EGLConfig would correspond to a YUV
+    Android HAL pixel format from which the video encoder can read.  The
+    EGLConfig would likely have the EGL_SLOW_CONFIG caveat because using that
+    config to render normal window contents would result in an RGB -> YUV color
+    space conversion when rendering the frame as well as a YUV -> RGB
+    conversion when compositing the window.
+
+    The other approach involves performing the color space conversion in the
+    video encoder.  In this case, the VisualID of the EGLConfig would
+    correspond to an RGB HAL pixel format from which the video encoder can
+    read.  The EGLConfig would likely not need to have any caveat set, as using
+    this config for normal window rendering would not have any added cost.
 
 Revision History
 
+#2 (Jamie Gennis, July 15, 2011)
+    - Added issue 3.
+
 #1 (Jamie Gennis, July 8, 2011)
     - Initial draft.
diff --git a/opengl/tests/gl2_copyTexImage/Android.mk b/opengl/tests/gl2_copyTexImage/Android.mk
new file mode 100644
index 0000000..bef1f90
--- /dev/null
+++ b/opengl/tests/gl2_copyTexImage/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	gl2_copyTexImage.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv2 \
+    libui
+
+LOCAL_MODULE:= test-opengl-gl2_copyTexImage
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
new file mode 100644
index 0000000..c2bfdec
--- /dev/null
+++ b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
@@ -0,0 +1,467 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Timers.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+static void printGLString(const char *name, GLenum s) {
+    // fprintf(stderr, "printGLString %s, %d\n", name, s);
+    const char *v = (const char *) glGetString(s);
+    // int error = glGetError();
+    // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+    //        (unsigned int) v);
+    // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
+    //    fprintf(stderr, "GL %s = %s\n", name, v);
+    // else
+    //    fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
+    fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+    "void main() {\n"
+    "  gl_Position = vPosition;\n"
+    "}\n";
+
+static const char gFragmentShader[] = "precision mediump float;\n"
+    "void main() {\n"
+    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 0.5);\n"
+    "}\n";
+
+GLuint loadShader(GLenum shaderType, const char* pSource) {
+    GLuint shader = glCreateShader(shaderType);
+    if (shader) {
+        glShaderSource(shader, 1, &pSource, NULL);
+        glCompileShader(shader);
+        GLint compiled = 0;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+                    fprintf(stderr, "Could not compile shader %d:\n%s\n",
+                            shaderType, buf);
+                    free(buf);
+                }
+                glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+    }
+    return shader;
+}
+
+GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+    if (!vertexShader) {
+        return 0;
+    }
+
+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+    if (!pixelShader) {
+        return 0;
+    }
+
+    GLuint program = glCreateProgram();
+    if (program) {
+        glAttachShader(program, vertexShader);
+        checkGlError("glAttachShader");
+        glAttachShader(program, pixelShader);
+        checkGlError("glAttachShader");
+        glLinkProgram(program);
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(program, bufLength, NULL, buf);
+                    fprintf(stderr, "Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = 0;
+        }
+    }
+    return program;
+}
+
+GLuint gProgram;
+GLuint gTextureProgram;
+GLuint gvPositionHandle;
+GLuint gvTexturePositionHandle;
+GLuint gvTextureTexCoordsHandle;
+GLuint gvTextureSamplerHandle;
+GLuint gFbo;
+GLuint gTexture;
+GLuint gBufferTexture;
+
+static const char gSimpleVS[] =
+    "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";
+static const char gSimpleFS[] =
+    "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";
+
+bool setupGraphics(int w, int h) {
+    gProgram = createProgram(gVertexShader, gFragmentShader);
+    if (!gProgram) {
+        return false;
+    }
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    checkGlError("glGetAttribLocation");
+    fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle);
+
+    gTextureProgram = createProgram(gSimpleVS, gSimpleFS);
+    if (!gTextureProgram) {
+        return false;
+    }
+    gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position");
+    checkGlError("glGetAttribLocation");
+    gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords");
+    checkGlError("glGetAttribLocation");
+    gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture");
+    checkGlError("glGetAttribLocation");
+
+    glActiveTexture(GL_TEXTURE0);
+
+    glGenTextures(1, &gTexture);
+    glBindTexture(GL_TEXTURE_2D, gTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    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);
+
+    glGenTextures(1, &gBufferTexture);
+    glBindTexture(GL_TEXTURE_2D, gBufferTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    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);
+
+    glGenFramebuffers(1, &gFbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gTexture, 0);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+        0.5f, -0.5f };
+
+const GLint FLOAT_SIZE_BYTES = 4;
+const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+const GLfloat gTriangleVerticesData[] = {
+    // 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,
+};
+
+void renderFrame(GLint w, GLint h) {
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    checkGlError("glClearColor");
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    // Bind FBO and draw into it
+    glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
+    checkGlError("glBindFramebuffer");
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    checkGlError("glClearColor");
+    glClear(GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    glUseProgram(gProgram);
+    checkGlError("glUseProgram");
+
+    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(gvPositionHandle);
+    checkGlError("glEnableVertexAttribArray");
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    checkGlError("glDrawArrays");
+
+    // Copy content of FBO into a texture
+    glBindTexture(GL_TEXTURE_2D, gBufferTexture);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w / 2, h / 2);
+    checkGlError("glCopyTexSubImage2D");
+
+    // Back to the display
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    checkGlError("glBindFramebuffer");
+
+    // Draw copied content on the screen
+    glUseProgram(gTextureProgram);
+    checkGlError("glUseProgram");
+
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+    glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE,
+            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData);
+    checkGlError("glVertexAttribPointer");
+    glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE,
+            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(gvTexturePositionHandle);
+    glEnableVertexAttribArray(gvTextureTexCoordsHandle);
+    checkGlError("glEnableVertexAttribArray");
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    checkGlError("glDrawArrays");
+}
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    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) {
+            printf(" %s: ", names[j].name);
+            printf("%d (0x%x)", value, value);
+        }
+    }
+    printf("\n");
+}
+
+int printEGLConfigurations(EGLDisplay dpy) {
+    EGLint numConfig = 0;
+    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        return false;
+    }
+
+    printf("Number of EGL configuration: %d\n", numConfig);
+
+    EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
+    if (! configs) {
+        printf("Could not allocate configs.\n");
+        return false;
+    }
+
+    returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        free(configs);
+        return false;
+    }
+
+    for(int i = 0; i < numConfig; i++) {
+        printf("Configuration %d\n", i);
+        printEGLConfiguration(dpy, configs[i]);
+    }
+
+    free(configs);
+    return true;
+}
+
+int main(int argc, char** argv) {
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+
+    EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLint s_configAttribs[] = {
+            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 };
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLSurface surface;
+    EGLint w, h;
+
+    EGLDisplay dpy;
+
+    checkEglError("<init>");
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (dpy == EGL_NO_DISPLAY) {
+        printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
+        return 0;
+    }
+
+    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
+    if (returnValue != EGL_TRUE) {
+        printf("eglInitialize failed\n");
+        return 0;
+    }
+
+    if (!printEGLConfigurations(dpy)) {
+        printf("printEGLConfigurations failed\n");
+        return 0;
+    }
+
+    checkEglError("printEGLConfigurations");
+
+    EGLNativeWindowType window = android_createDisplaySurface();
+    EGLint numConfigs = -1, n = 0;
+    eglChooseConfig(dpy, s_configAttribs, 0, 0, &numConfigs);
+    if (numConfigs) {
+        EGLConfig* const configs = new EGLConfig[numConfigs];
+        eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
+        myConfig = configs[0];
+        delete[] configs;
+    }
+
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    printf("Chose this configuration:\n");
+    printEGLConfiguration(dpy, myConfig);
+
+    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (surface == EGL_NO_SURFACE) {
+        printf("gelCreateWindowSurface failed.\n");
+        return 0;
+    }
+
+    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        printf("eglCreateContext failed\n");
+        return 0;
+    }
+    returnValue = eglMakeCurrent(dpy, surface, surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        return 0;
+    }
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+    checkEglError("eglQuerySurface");
+    GLint dim = w < h ? w : h;
+
+    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    if(!setupGraphics(w, h)) {
+        fprintf(stderr, "Could not set up graphics.\n");
+        return 0;
+    }
+
+    for (;;) {
+        renderFrame(w, h);
+        eglSwapBuffers(dpy, surface);
+        checkEglError("eglSwapBuffers");
+    }
+
+    return 0;
+}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 15c1653..626cc86 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -515,34 +515,7 @@
 
         // Check all the native files that need to be copied and add that to the
         // container size.
-        ZipFile zipFile;
-        final List<Pair<ZipEntry, String>> nativeFiles;
-        try {
-            zipFile = new ZipFile(apkFile);
-
-            if (outFiles != null) {
-                nativeFiles = outFiles;
-            } else {
-                nativeFiles = new ArrayList<Pair<ZipEntry, String>>();
-            }
-
-            NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
-
-            final int N = nativeFiles.size();
-            for (int i = 0; i < N; i++) {
-                final Pair<ZipEntry, String> entry = nativeFiles.get(i);
-
-                /*
-                 * Note a 1MB padding is added to the claimed size, so we don't
-                 * have to worry about block alignment here.
-                 */
-                sizeBytes += entry.first.getSize();
-            }
-        } catch (ZipException e) {
-            Log.w(TAG, "Failed to extract data from package file", e);
-        } catch (IOException e) {
-            Log.w(TAG, "Failed to cache package shared libs", e);
-        }
+        sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
 
         int sizeMb = (int) (sizeBytes >> 20);
         if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) {
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index 61f3d11..cb5a781 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4567566098528588863">" Izilungiselelo zokugcina"</string>
+    <string name="app_label" msgid="4567566098528588863">"Izilungiselelo zesitoreji"</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index afe4246..a5022e9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -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 = 66;
+    private static final int DATABASE_VERSION = 67;
 
     private Context mContext;
 
@@ -861,6 +861,36 @@
             upgradeVersion = 66;
         }
 
+        if (upgradeVersion == 66) {
+            // This upgrade makes sure that MODE_RINGER_STREAMS_AFFECTED and
+            // NOTIFICATIONS_USE_RING_VOLUME settings are set according to device voice capability
+             db.beginTransaction();
+             try {
+                 int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
+                                                 (1 << AudioManager.STREAM_NOTIFICATION) |
+                                                 (1 << AudioManager.STREAM_SYSTEM) |
+                                                 (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
+                 if (!mContext.getResources().getBoolean(
+                         com.android.internal.R.bool.config_voice_capable)) {
+                     ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
+
+                     db.execSQL("DELETE FROM system WHERE name='"
+                             + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "'");
+                     db.execSQL("INSERT INTO system ('name', 'value') values ('"
+                             + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "', '1')");
+                 }
+                 db.execSQL("DELETE FROM system WHERE name='"
+                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
+                 db.execSQL("INSERT INTO system ('name', 'value') values ('"
+                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
+                         + String.valueOf(ringerModeAffectedStreams) + "')");
+                 db.setTransactionSuccessful();
+             } finally {
+                 db.endTransaction();
+             }
+             upgradeVersion = 67;
+         }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1121,12 +1151,22 @@
     
             loadVibrateSetting(db, false);
     
-            // By default, only the ring/notification, system and music streams are affected
+            // By default:
+            // - ringtones, notification, system and music streams are affected by ringer mode
+            // on non voice capable devices (tablets)
+            // - ringtones, notification and system streams are affected by ringer mode
+            // on voice capable devices (phones)
+            int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
+                                            (1 << AudioManager.STREAM_NOTIFICATION) |
+                                            (1 << AudioManager.STREAM_SYSTEM) |
+                                            (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
+            if (!mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_voice_capable)) {
+                ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
+            }
             loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
-                    (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) |
-                    (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED) |
-                    (1 << AudioManager.STREAM_MUSIC));
-    
+                    ringerModeAffectedStreams);
+
             loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
                     ((1 << AudioManager.STREAM_MUSIC) |
                      (1 << AudioManager.STREAM_RING) |
@@ -1232,8 +1272,13 @@
                     R.bool.def_vibrate_in_silent);
 
             // Set notification volume to follow ringer volume by default
-            loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
-                    R.bool.def_notifications_use_ring_volume);
+            if (mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_voice_capable)) {
+                loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
+                        R.bool.def_notifications_use_ring_volume);
+            } else {
+                loadSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME, "1");
+            }
 
             loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
                     R.integer.def_pointer_speed);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 26ea225..ba9b5b0 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -30,6 +30,15 @@
         <service android:name=".screenshot.TakeScreenshotService"
             android:exported="false" />
 
+        <service android:name=".LoadAverageService"
+                android:exported="true" />
+
+        <receiver android:name=".BootReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
         <activity android:name=".usb.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
@@ -73,5 +82,17 @@
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
+
+        <!-- started from NetworkPolicyManagerService -->
+        <activity
+            android:name=".net.NetworkOverLimitActivity"
+            android:exported="true"
+            android:permission="android.permission.MANAGE_NETWORK_POLICY"
+            android:theme="@android:style/Theme.Holo.Panel"
+            android:finishOnCloseSystemDialogs="true"
+            android:launchMode="singleTop"
+            android:taskAffinity="com.android.systemui.net"
+            android:excludeFromRecents="true" />
+
     </application>
 </manifest>
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 48f6122..2aeb84a 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_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index 1439ece..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 06c3369..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a1a712f..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 313f0f5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 75def49..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index efbd535..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e0dca0b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 54ee2e6..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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 686158b..2aeb84a 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_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
deleted file mode 100644
index 76170a8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 97d35f3..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 17423d2..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index ae58b57..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 00e5bb8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b036a89..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index bdae6fb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 2b7d95f..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
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 6e5f131..35d0a06 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-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index 0cfdca0..d52cb1a 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_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index 7bbfbd1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 60b75ef..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 0fba69d..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index da8a957..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e19bf64..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 8387514..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 35f7741..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a8820e9..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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 b65df27..d52cb1a 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_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
deleted file mode 100644
index 0478d70..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e78a0b1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 24c75ec..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 7027dc4..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b0e83dc..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 01945ff..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 725a507..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 193af25..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
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
index 22215ab..79da092 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.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
index ec4f934..726f7ad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
+++ 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_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index fb98eef..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b86d47a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 7269f96..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index f57e62d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 3d513fb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 32556f9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index afac648..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 60c0e7f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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
index 0df470a..726f7ad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.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
deleted file mode 100644
index d8d5e8f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 2b0b54f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 85c65b4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a7e9aaf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 21aba7e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 41db8dc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index ae95d26..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 4ad2c5c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml b/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml
deleted file mode 100644
index 0e58e12..0000000
--- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
-	android:exitFadeDuration="@android:integer/config_mediumAnimTime">
-
-    <item android:state_window_focused="false" android:drawable="@android:color/transparent" />
-
-    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
-    <item android:state_focused="true"                                android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" />
-    <item android:state_focused="false"                               android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" />
-    <item android:state_focused="true"                                                             android:drawable="@drawable/recents_thumbnail_bg_holo" />
-</selector>
-
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml
similarity index 69%
copy from core/res/res/layout/text_edit_suggestions_bottom_window.xml
copy to packages/SystemUI/res/drawable/recents_thumbnail_layers.xml
index 588bfbd..6cae2c4 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml
@@ -4,20 +4,16 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
-
-</LinearLayout>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:drawable="@drawable/recents_thumbnail_bg" android:id="@+id/base_layer"/>
+    <item android:drawable="@drawable/recents_thumbnail_overlay" android:id="@+id/overlay_layer"/>
+</layer-list>
\ No newline at end of file
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml
similarity index 69%
copy from core/res/res/layout/text_edit_suggestions_bottom_window.xml
copy to packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml
index 588bfbd..200bac4 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml
@@ -4,20 +4,16 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
-
-</LinearLayout>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/recents_thumbnail_bg_press" android:state_pressed="true" />
+    <item android:drawable="@*android:color/transparent"/>
+</selector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_battery.xml b/packages/SystemUI/res/drawable/stat_sys_battery.xml
new file mode 100644
index 0000000..744ab93
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_battery.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_0" />
+    <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_15" />
+    <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_28" />
+    <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_43" />
+    <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_57" />
+    <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_71" />
+    <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_85" />
+    <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_100" />
+</level-list>
+
diff --git a/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml
new file mode 100644
index 0000000..6918eb2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml
@@ -0,0 +1,31 @@
+<?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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_charge_anim0" />
+    <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_charge_anim15" />
+    <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_charge_anim28" />
+    <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_charge_anim43" />
+    <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_charge_anim57" />
+    <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_charge_anim71" />
+    <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_charge_anim85" />
+    <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_charge_anim100" />
+</level-list>
+
+
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index be4f1d7..8c29042 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -24,14 +24,15 @@
     android:layout_height="wrap_content"
     android:layout_width="@dimen/status_bar_recents_thumbnail_view_width">
 
-    <ImageView android:id="@+id/app_thumbnail"
+    <FrameLayout android:id="@+id/app_thumbnail"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
-        android:background="@drawable/recents_thumbnail_bg_selector"
+        android:clickable="true"
+        android:background="@drawable/recents_thumbnail_layers"
     />
 
     <ImageView android:id="@+id/app_icon"
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 efdd9ac..20ef7cf 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -51,7 +51,6 @@
                 android:fadingEdge="horizontal"
                 android:scrollbars="none"
                 android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
-                android:listSelector="@drawable/recents_thumbnail_bg_selector"
                 android:layout_gravity="bottom|left"
                 android:orientation="horizontal"
                 android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index 76965c9..c705a69 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -24,13 +24,15 @@
     android:layout_height="wrap_content"
     android:layout_width="@dimen/status_bar_recents_thumbnail_view_width">
 
-    <ImageView android:id="@+id/app_thumbnail"
+    <FrameLayout android:id="@+id/app_thumbnail"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
+        android:clickable="true"
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
+        android:background="@drawable/recents_thumbnail_layers"
     />
 
     <ImageView android:id="@+id/app_icon"
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 28ef239..c680b8e 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -48,7 +48,6 @@
                 android:fadingEdge="vertical"
                 android:scrollbars="none"
                 android:fadingEdgeLength="@*android:dimen/status_bar_height"
-                android:listSelector="@drawable/recents_thumbnail_bg_selector"
                 android:layout_gravity="bottom|left"
                 android:clipToPadding="false"
                 android:clipChildren="false">
diff --git a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
index d29e495..a354336 100644
--- a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
+++ b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
@@ -43,6 +43,7 @@
         android:layout_height="wrap_content"
         android:layout_centerInParent="true"
         android:src="@drawable/compat_mode_help_diagram"
+        android:contentDescription="@string/accessibility_compatibility_zoom_example"
         />
     <RelativeLayout
         android:orientation="horizontal"
@@ -61,6 +62,7 @@
             android:layout_alignParentRight="true"
             android:layout_centerVertical="true"
             android:src="@drawable/compat_mode_help_icon"
+            android:contentDescription="@string/accessibility_compatibility_zoom_button"
             />
         <TextView
             android:id="@+id/explanation"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index d9f3f23..a2a6473 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -49,6 +49,7 @@
                 android:src="@drawable/ic_sysbar_back"
                 android:layout_alignParentLeft="true"
                 systemui:keyCode="4"
+                android:contentDescription="@string/accessibility_back"
                 />
             <LinearLayout
                 android:id="@+id/navigationArea"
@@ -62,11 +63,13 @@
                     android:layout_height="match_parent"
                     android:src="@drawable/ic_sysbar_home"
                     systemui:keyCode="3"
+                    android:contentDescription="@string/accessibility_home"
                     />
                 <ImageView android:id="@+id/recent_apps"
                     android:layout_width="80dip"
                     android:layout_height="match_parent"
                     android:src="@drawable/ic_sysbar_recent"
+                    android:contentDescription="@string/accessibility_menu"
                     />
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                     android:layout_width="80dip"
@@ -74,6 +77,7 @@
                     android:src="@drawable/ic_sysbar_menu"
                     systemui:keyCode="82"
                     android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_menu"
                     />
             </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
index 3fef7e0..41a20fb 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
@@ -53,7 +53,8 @@
                 android:id="@+id/item_icon"
                 android:layout_width="@android:dimen/app_icon_size"
                 android:layout_height="wrap_content"
-                android:scaleType="fitCenter" />
+                android:scaleType="fitCenter"
+                android:contentDescription="@null" />
             <LinearLayout
                 android:orientation="vertical"
                 android:layout_width="0px"
@@ -94,7 +95,8 @@
             android:visibility="visible"
             android:clickable="true"
             android:focusable="true"
-            android:background="?android:attr/selectableItemBackground" />
+            android:background="?android:attr/selectableItemBackground"
+            android:contentDescription="@string/accessibility_settings_button" />
     </LinearLayout>
     <View
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
index fecfe7f..17fa653 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
@@ -16,7 +16,7 @@
 -->
 
 <!-- notification icons & panel access -->
-<LinearLayout
+<com.android.systemui.statusbar.tablet.NotificationArea
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/notificationArea"
@@ -40,6 +40,7 @@
             android:layout_marginLeft="8dip"
             android:src="@drawable/ic_sysbar_ime_default"
             android:visibility="gone"
+            android:contentDescription="@string/accessibility_ime_switch_button"
             />
 
         <com.android.systemui.statusbar.policy.CompatModeButton
@@ -49,6 +50,7 @@
             android:layout_marginLeft="8dip"
             android:src="@drawable/ic_sysbar_zoom"
             android:visibility="gone"
+            android:contentDescription="@string/accessibility_compatibility_zoom_button"
             />
 
         <com.android.systemui.statusbar.tablet.NotificationIconArea
@@ -124,27 +126,10 @@
                 android:layout_width="wrap_content"
                 android:visibility="gone"
                 />
-            <FrameLayout
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:layout_marginRight="4dp"
-                >
-                <ImageView
-                    android:id="@+id/network_signal"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    />
-                <ImageView
-                    android:id="@+id/network_type"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    />
-                <ImageView
-                    android:id="@+id/network_direction"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    />
-            </FrameLayout>
+            <include layout="@layout/stacked_signal_icons" 
+                android:layout_width="32dp"
+                android:layout_height="24dp"
+                />
             <ImageView
                 android:id="@+id/battery"
                 android:layout_height="wrap_content"
@@ -152,4 +137,4 @@
                 />
         </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</com.android.systemui.statusbar.tablet.NotificationArea>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
index 543f4ed..bbb2bc6 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
@@ -14,15 +14,17 @@
   limitations under the License.
 -->
 
-<RelativeLayout
+<com.android.systemui.statusbar.tablet.NotificationPanelTitle
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/title_area"
-    android:layout_width="0dp"
-    android:layout_height="0dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:clickable="true"
     android:orientation="vertical"
     android:background="@drawable/notify_panel_clock_bg"
     >
+
     <LinearLayout
         android:id="@+id/icons"
         android:layout_width="wrap_content"
@@ -34,6 +36,7 @@
         android:layout_marginTop="16dp"
         android:layout_marginBottom="16dp"
         >
+
         <ImageView
             android:id="@+id/bluetooth"
             android:layout_height="32dp"
@@ -41,6 +44,7 @@
             android:scaleType="centerInside"
             android:baseline="22dp"
             android:visibility="gone"
+            android:contentDescription="@null"
             />
 
         <FrameLayout
@@ -49,21 +53,28 @@
             android:layout_width="32dp"
             android:layout_marginRight="4dp"
             >
+
             <ImageView
                 android:id="@+id/network_signal"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
             <ImageView
                 android:id="@+id/network_type"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
             <ImageView
                 android:id="@+id/network_direction"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
         </FrameLayout>
             
         <TextView
@@ -86,6 +97,7 @@
             android:layout_toRightOf="@id/network_text"
             android:layout_alignBaseline="@id/network_signal"
             android:baseline="22dp"
+            android:contentDescription="@null"
             />
 
         <TextView
@@ -110,6 +122,7 @@
         android:paddingRight="16dp"
         android:src="@drawable/ic_sysbar_quicksettings"
         android:baseline="21dp"
+        android:contentDescription="@string/accessibility_settings_button"
         />
 
     <ImageView
@@ -122,6 +135,7 @@
         android:src="@drawable/ic_notification_open"
         android:baseline="21dp"
         android:visibility="invisible"
+        android:contentDescription="@string/accessibility_notifications_button"
         />
 
     <View
@@ -138,7 +152,7 @@
     <com.android.systemui.statusbar.tablet.HoloClock
         android:id="@+id/clock"
         android:layout_height="wrap_content"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_alignParentRight="true"
         android:layout_above="@id/title_divider"
         android:layout_marginRight="6dip"
@@ -164,19 +178,11 @@
         android:id="@+id/date"
         style="@style/StatusBarNotificationText"
         android:layout_height="wrap_content"
-        android:layout_width="120dp"
+        android:layout_width="wrap_content"
         android:layout_alignBottom="@id/clock"
         android:layout_alignParentLeft="true"
         android:gravity="left"
         android:layout_marginLeft="32dp"
         />
 
-    <view
-        class="com.android.systemui.statusbar.tablet.NotificationPanel$ModeToggle"
-        android:id="@+id/mode_toggle"
-        android:background="@null"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clickable="true"
-        />
-</RelativeLayout>
+</com.android.systemui.statusbar.tablet.NotificationPanelTitle>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index 9687866..386ce30 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -24,13 +24,15 @@
     android:layout_height="wrap_content"
     android:layout_width="@dimen/status_bar_recents_thumbnail_view_width">
 
-    <ImageView android:id="@+id/app_thumbnail"
+    <FrameLayout android:id="@+id/app_thumbnail"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
+        android:clickable="true"
+        android:background="@drawable/recents_thumbnail_layers"
     />
 
     <ImageView android:id="@+id/app_icon"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
index 75fdc67..2c9a152 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
@@ -56,7 +56,6 @@
                 android:scrollbars="none"
                 android:fadingEdgeLength="20dip"
                 android:layout_gravity="bottom|left"
-                android:listSelector="@drawable/recents_thumbnail_bg_selector"
                 android:clipToPadding="false"
                 android:clipChildren="false">
 
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 51e7d97..5d7e8de 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -54,6 +54,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_width="80dp"
@@ -66,6 +67,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_home"
                 />
             <ImageView android:id="@+id/recent_apps"
                 android:layout_width="80dp"
@@ -80,6 +82,7 @@
                 systemui:keyCode="82"
                 android:layout_weight="0"
                 android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
                 />
         </LinearLayout>
 
@@ -124,6 +127,7 @@
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_menu"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_height="80dp"
@@ -131,11 +135,13 @@
                 android:src="@drawable/ic_sysbar_home_default_land"
                 systemui:keyCode="3"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_home"
                 />
             <View 
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                 android:layout_height="80dp"
@@ -148,6 +154,7 @@
                 android:layout_height="40dp"
                 android:layout_width="match_parent"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_menu"
                 />
         </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/stacked_signal_icons.xml b/packages/SystemUI/res/layout/stacked_signal_icons.xml
new file mode 100644
index 0000000..fdeb74b
--- /dev/null
+++ b/packages/SystemUI/res/layout/stacked_signal_icons.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** 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.
+*/
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    >
+    <ImageView
+        android:id="@+id/mobile_signal"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignLeft="@+id/wifi_signal"
+        android:layout_alignWithParentIfMissing="true"
+        />
+    <ImageView
+        android:id="@+id/network_type"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_alignRight="@id/mobile_signal"
+        android:layout_centerVertical="true"
+        />
+    <ImageView
+        android:id="@+id/wifi_signal"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        android:scaleType="center"
+        android:paddingLeft="7dp"
+        />
+    <ImageView
+        android:id="@+id/network_direction"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index c8f5772..0f5aa93 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -46,10 +46,29 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_alignParentRight="true"
-            android:paddingRight="6dip"
             android:gravity="center_vertical"
             android:orientation="horizontal"/>    
 
+        <LinearLayout
+            android:id="@+id/signal_battery_cluster"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dp"
+            android:orientation="horizontal"
+            android:gravity="center"
+            >
+            <include layout="@layout/stacked_signal_icons" 
+                android:layout_width="24dp"
+                android:layout_height="match_parent"
+                />
+            <ImageView
+                android:id="@+id/battery"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:paddingLeft="6dip"
+                />
+        </LinearLayout>
+
         <com.android.systemui.statusbar.policy.Clock
             android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml b/packages/SystemUI/res/menu/recent_popup_menu.xml
similarity index 70%
rename from packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml
rename to packages/SystemUI/res/menu/recent_popup_menu.xml
index f9bba2a..eecfb9a 100644
--- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml
+++ b/packages/SystemUI/res/menu/recent_popup_menu.xml
@@ -17,7 +17,7 @@
 ** limitations under the License.
 */
 -->
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/recents_thumbnail_bg_press"/>
-    <item android:drawable="@drawable/recents_thumbnail_bg_press"/>
-</transition>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/recent_remove_item" android:title="@string/status_bar_recent_remove_item_title" />
+    <item android:id="@+id/recent_inspect_item" android:title="@string/status_bar_recent_inspect_item_title" />
+</menu>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index bf18e3b..116d6a0 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Maak skoon"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Moenie steur nie"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Wys kennisgewings"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
     <skip />
     <!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
     <skip />
     <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <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) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7e15fe0..740fb2a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"አይረብሹ"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"ማሳወቂያዎች አሳይ"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
     <skip />
     <!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
     <skip />
     <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <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) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d8aa61f..5b1d492 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"محو"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"عدم الإزعاج"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"إظهار التنبيهات"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ليس هناك أي تنبيهات"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"مستمر"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"التنبيهات"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"تم حفظ لقطة الشاشة إلى المعرض."</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"تعذر حفظ لقطة الشاشة."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"خيارات نقل الملفات عبر USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"تحميل كمشغل وسائط (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"تحميل ككاميرا (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"تثبيت تطبيق Android File Transfer لـ Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 20748ee..4890c0d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Изчистване"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не ме безпокойте"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показване на известията"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Няма известия"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"В момента"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Екранната снимка е запазена в галерията"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Екранната снимка не можа да бъде запазена"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Свързване като камера (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Инсталиране на Android File Transfer за Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index c346184..417987c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Esborra"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molesteu"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostra notificacions"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Cap notificació"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla desada a la galeria"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"No es pot desar la captura de pantalla"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instal·la aplic. transf. fitxers Android per a Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 692dd4c..7544876 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazat"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nerušit"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Zobrazit upozornění"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žádná oznámení"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímek obrazovky byl uložen do Galerie"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Snímek obrazovky se nepodařilo uložit"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Připojit jako fotoaparát (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalovat aplikaci Android File Transfer pro Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index bd1bd02..89c6b64 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ryd"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Forstyr ikke"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Vis meddelelser"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelelser"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skærmbilledet gemmes i Galleri"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Skærmbilledet kunne ikke gemmes"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Isæt som et kamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer appen Android File Transfer Manager til Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index ed0bfa4..dc68c22 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Löschen"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Bitte nicht stören"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Benachrichtigungen zeigen"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot in Galerie gespeichert"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Screenshot konnte nicht gespeichert werden."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"App \"Android File Transfer\" für Mac installieren"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1d907c5..29d84cb 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Μην ενοχλείτε"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Εμφάνιση ειδοποιήσεων"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Δεν υπάρχουν ειδοποιήσεις"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Το στιγμιότυπο οθόνης αποθηκεύτηκε στη συλλογή"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Δεν ήταν δυνατή η αποθήκευση του στιγμιοτύπου οθόνης"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Προσάρτηση ως κάμερας (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Εγκατάσταση της εφαρμογής μεταφοράς αρχείων Android για Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index cda0718..2d8c737 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Clear"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Do not disturb"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Show notifications"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -57,8 +61,104 @@
     <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 screenshot_saving_toast (8592630119048713208) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot saved to Gallery"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Could not save screenshot"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Install Android File Transfer application for Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index fd16ccf..7ce69b6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la Galería"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"No se pudo guardar la captura de pantalla."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar la aplicación para transferir archivos de Android para Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a57258a..1ee4fed 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la galería"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"No se ha podido guardar la captura de pantalla."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar la aplicación para transferir archivos de Android para Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 95f1c75..dbdcbb6 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"پاک کردن"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"مزاحم نشوید"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"نمایش اعلان ها"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"اعلانی موجود نیست"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان ها"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"تصویر از صفحه در گالری ذخیره شد"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"ذخیره تصویر صفحه ممکن نیست"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"گزینه های انتقال فایل USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"نصب به عنوان دستگاه پخش رسانه (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"تصب به عنوان دوربین (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"نصب برنامه انتقال فایل Android برای Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 7bf504f..bef79a5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Tyhjennä"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Varattu"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Näytä ilmoitukset"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ei ilmoituksia"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Kuvakaappaus on tallennettu galleriaan"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Kuvakaappausta ei voitu tallentaa"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Asenna Android File Transfer -sovellus Macille"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c1daaa5..9815664 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne pas déranger"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Afficher les notifications"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Capture d\'écran enregistrée dans la galerie."</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Impossible d\'enregistrer la capture d\'écran."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer en tant qu\'appareil photo (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer application Android File Transfer pour Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index decaacd..45d2edc 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Očisti"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne uznemiravaj"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Prikaži obavijesti"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bez obavijesti"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snimak zaslona spremljen u Galeriju"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Ne mogu spremiti snimak zaslona"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Učitaj kao fotoaparat (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalacija aplikacije Android File Transfer za Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 696566f..468b875 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Törlés"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne zavarjanak"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Értesítések megjelenítése"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nincs értesítés"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Képernyőkép mentve a galériába"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Nem sikerült menteni a képernyőképet"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Csatlakoztatás kameraként (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Android fájlátviteli alkalmazás telepítése Machez"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 78f29c1..9da6e73 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Bersihkan"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Jangan ganggu"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Tampilkan pemberitahuan"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tidak ada pemberitahuan"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan layar disimpan ke Galeri"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak dapat menyimpan tangkapan layar"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer berkas USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Pasang aplikasi Transfer Berkas Android untuk Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8c6cd6d..476f190 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Cancella"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Non disturbare"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostra notifiche"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot salvato nella galleria"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Impossibile salvare lo screenshot"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Monta come videocamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Installa l\'applicazione Android File Transfer per Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 511d49e..4552f23 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"נקה"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"נא לא להפריע"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"הצג התראות"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"אין התראות"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתבצע"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"התראות"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"צילום המסך נשמר בגלריה"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"לא ניתן לשמור את צילום המסך"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"אפשרויות העברת קבצים ב-USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"טען כנגן מדיה (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"טען כמצלמה (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"התקן את יישום העברת הקבצים של Android עבור Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 88611dd..abee692 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"通知を消去"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"通知を非表示"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"通知を表示"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"通知なし"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"スクリーンショットがギャラリーに保存されました"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"スクリーンショットを保存できませんでした"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"カメラ(PTP)としてマウント"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac版Android File Transferアプリのインストール"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4cc668a..c34f0e4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"지우기"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"응답 거부"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"알림 표시"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"알림 없음"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"캡쳐화면이 갤러리에 저장되었습니다."</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"캡쳐화면을 저장하지 못했습니다."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"카메라로 마운트(PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac용 Android 파일 전송 애플리케이션 설치"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-large/strings.xml b/packages/SystemUI/res/values-large/strings.xml
index 35be532..f04dc04 100644
--- a/packages/SystemUI/res/values-large/strings.xml
+++ b/packages/SystemUI/res/values-large/strings.xml
@@ -21,29 +21,9 @@
          all of the currently visible notifications. [CHAR LIMIT=10]-->
     <string name="status_bar_clear_all_button">Clear all</string>
 
-    <!-- System panel ("Quick Settings") -->
-
-    <!-- Text to display underneath the graphical signal strength meter when
-         no connection is available. [CHAR LIMIT=20] -->
-    <string name="status_bar_settings_signal_meter_disconnected">
-        No Internet connection
-    </string>
-
-    <!-- Text to display underneath the graphical signal strength meter when
-         it is displaying Wi-Fi status and Wi-Fi is connected to a network
-         whose SSID is not available.
-         [CHAR LIMIT=20] -->
-    <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string>
-
     <!-- Separator for PLMN and SPN in network name. -->
     <string name="status_bar_network_name_separator" translatable="false">" – "</string>
 
-    <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] -->
-    <string name="gps_notification_searching_text">Searching for GPS</string>
-
-    <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
-    <string name="gps_notification_found_text">Location set by GPS</string>
-
     <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
          mode) -->
     <string name="notifications_off_title">Notifications off</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index fbdba57..040c74d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Išvalyti"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netrukdyti"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rodyti pranešimus"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nėra įspėjimų"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Įspėjimai"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrano kopija išsaugota galerijoje"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Nepavyko išsaugoti ekrano kopijos"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos grotuvą (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Įdiegti „Mac“ skirtą „Android“ failų perd. progr."</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 37e3f92..4c9b4b4 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Notīrīt"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netraucēt"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rādīt paziņojumus"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nav paziņojumu"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrānuzņēmums ir saglabāts galerijā."</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Nevarēja saglabāt ekrānuzņēmumu."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Pievienot kā kameru (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalēt Android failu pārsūt. liet. Mac datoram"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms-large/strings.xml b/packages/SystemUI/res/values-ms-large/strings.xml
new file mode 100644
index 0000000..4897656
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-large/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Ksgkn smua"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Tiada smbg Internet"</string>
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Wi-Fi disambungkan"</string>
+    <string name="gps_notification_searching_text" msgid="4467935186864208249">"Mencari GPS"</string>
+    <string name="gps_notification_found_text" msgid="6270628388918822956">"Lokasi ditetapkan oleh GPS"</string>
+    <string name="notifications_off_title" msgid="1860117696034775851">"Pemberitahuan dimatikan"</string>
+    <string name="notifications_off_text" msgid="1439152806320786912">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index c24a8fb..eef7926 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Pdm bersih"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Jangan ganggu"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Tunjukkan pemberitahuan"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tiada pemberitahuan"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sedang berlangsung"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
@@ -53,16 +57,108 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Keserasian Zum"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Apabila apl direka untuk skrin yang lebih kecil, kawalan zum akan muncul di tepi jam."</string>
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan skrin disimpan ke Galeri"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak boleh menyimpan tangkapan skrin"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Lekapkan sebagai kamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Pasang aplikasi Pemindahan Fail Android untuk Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
     <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
     <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
     <skip />
-    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index df92a70..589a6ab 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Fjern"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ikke forstyrr"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Vis varslinger"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varslinger"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skjermdump ble lagret i galleriet"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Lagring av skjermdump mislyktes"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Sett inn som kamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer Android File Transfer for Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 518402f..ab44aafe 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wissen"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Niet storen"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Meldingen weergeven"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Schermafbeelding is opgeslagen in de galerij"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Schermafbeelding is niet opgeslagen"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Koppelen als camera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Applicatie Android File Transfer voor Mac installeren"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c59df62..977ba60 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wyczyść"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nie przeszkadzać"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Pokaż powiadomienia"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Zrzut ekranu został zapisany w galerii."</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Nie można zapisać zrzutu ekranu."</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Podłącz jako aparat (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Zainstaluj aplikację Android File Transfer dla Mac OS"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ee79283..2c6d283 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Não incomodar"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificações"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecrã guardada na Galeria"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível guardar a captura de ecrã"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar a ap. Trans. de Fic. do Android para Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 447cce1..29aa510 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Não perturbe"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificações"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"A captura de tela foi salva na Galeria"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível salvar a captura de tela"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar aplic. Android File Transfer para Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 2f23275..b2c8b50 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -26,6 +26,10 @@
     <skip />
     <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
     <skip />
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nagins avis"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actual"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Avis"</string>
@@ -91,4 +95,106 @@
     <skip />
     <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <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) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 07394ab..5128088 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ştergeţi"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nu deranjaţi"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Afişaţi notificări"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nicio notificare"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfăşurare"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecran a fost salvată în Galerie"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Captura de ecran nu a putut fi salvată"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opţiuni pentru transferul de fişiere prin USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Montaţi ca player media (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Montaţi drept cameră foto (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalaţi aplicaţia Transfer de fişiere Android pentru Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e4f3e83..2f22ab4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не беспокоить"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нет уведомлений"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Скриншот сохранен в галерее"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Не удалось сохранить скриншот"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Установить Android File Transfer для Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f720662..9701572 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazať"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nerušiť"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Zobraziť upozornenia"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žiadne upozornenia"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímka obrazovky bola uložená do Galérie"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Snímku obrazovky sa nepodarilo uložiť"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Pripojiť ako fotoaparát (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Inštalovať aplikáciu Prenos súborov Android pre systém Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 37ecf50..2b89f88 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Počisti"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne moti"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Pokaži obvestila"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ni obvestil"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Posnetek zaslona je shranjen v galerijo"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Posnetka zaslona ni bilo mogoče shraniti"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Vpni kot fotoaparat (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Namestite program Android File Transfer za Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7290f4c..fcd612f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Обриши"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не узнемиравај"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Приказуј упозорења"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нема обавештења"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текуће"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Снимак екрана је сачуван у Галерији"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Није могуће сачувати снимак екрана"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Прикључи као камеру (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Инсталирај апликацију Android File Transfer за Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 19c9a09..6f3b2bb 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ta bort"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Stör ej"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Visa aviseringar"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skärmdumpen sparades i galleriet"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Det gick inte att spara skärmdumpen"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Montera som kamera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Installera Android-filöverföringsapp för Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 17ec8a1..450157c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Futa"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Usisumbue"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Onyesha arifa"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
     <skip />
     <!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
     <skip />
     <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <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) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index b4fd8ab..a5bea5c7 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -64,4 +64,10 @@
     <!-- Where to place the app icon over the thumbnail -->
     <dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen>
     <dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen>
+
+    <!-- size at which Notification icons will be drawn in the status bar -->
+    <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+
+    <!-- opacity at which Notification icons will be drawn in the status bar -->
+    <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..6736c1a
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp/dimens.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.
+*/
+-->
+<resources>
+    <!-- size at which Notification icons will be drawn in the status bar -->
+    <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+
+    <!-- opacity at which Notification icons will be drawn in the status bar -->
+    <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
+</resources>
+
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 15f3007..a5315c6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"ล้างข้อมูล"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"ห้ามรบกวน"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"แสดงการแจ้งเตือน"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ไม่มีการแจ้งเตือน"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ดำเนินอยู่"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"บันทึกภาพหน้าจอในแกลเลอรีแล้ว"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"ไม่สามารถบันทึกภาพหน้าจอ"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"ติดตั้งแอปพลิเคชัน Android File Transfer ของ Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 93fdb6a..d44f82e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"I-clear"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Huwag gambalain"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Magpakita ng notification"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Walang mga notification"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Na-save ang screenshot sa Gallery"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Hindi ma-save ang screenshot"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"I-mount bilang camera (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"I-install Android File Transfer para sa Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5ec11b6..308c434 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Temizle"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Rahatsız etmeyin"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Bildirimleri göster"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildirim yok"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekran görüntüsü Galeri\'ye kaydedildi"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Ekran görüntüsü kaydedilemedi"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera olarak ekle (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac için Android Dosya Aktarımı uygulamasını yükle"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 759acdc..6687d0c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очист."</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не турбувати"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показувати сповіщення"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Немає сповіщень"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Знімок екрана збережено в Галереї"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Неможливо зберегти знімок екрана"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Підключити як камеру (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Установити програму Android File Transfer для Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index af44600..5bca34b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xoá"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Không làm phiền"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Hiển thị thông báo"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Không có thông báo nào"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"Đã lưu ảnh chụp màn hình vào Thư viện"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"Không thể lưu ảnh chụp màn hình"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"Gắn như một máy ảnh (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"Cài đặt ứng dụng Truyền tệp của Android dành cho Mac"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 201ecfa..dfab6d7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"请勿打扰"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"显示通知"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"屏幕截图已保存到“图库”"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"无法保存屏幕截图"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB 文件传输选项"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器 (MTP) 装载"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"作为摄像头 (PTP) 装载"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"安装适用于苹果机的“Android 文件传输”应用程序"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a46a909..854d89d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"勿干擾"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"顯示通知"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"沒有通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -57,8 +61,104 @@
     <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) -->
+    <string name="screenshot_saving_toast" msgid="8592630119048713208">"螢幕擷取畫面已儲存至圖片庫"</string>
+    <string name="screenshot_failed_toast" msgid="655180965533683356">"無法儲存螢幕擷取畫面"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
+    <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
+    <string name="installer_cd_button_title" msgid="8485631662288445893">"安裝適用於 Mac 的「Android 檔案傳輸」"</string>
+    <!-- no translation found for accessibility_back (567011538994429120) -->
     <skip />
-    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 01db97f..05268bf 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -23,6 +23,10 @@
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Sula"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ungaphazamisi"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Bonisa izaziso"</string>
+    <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+    <skip />
     <!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
     <skip />
     <!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
     <skip />
     <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <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) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5298f2e..d7d7817 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -34,7 +34,7 @@
     <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
 
     <!-- Whether or not we show the number in the bar. -->
-    <bool name="config_statusBarShowNumber">true</bool>
+    <bool name="config_statusBarShowNumber">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. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index da28e1e..b02015d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -48,5 +48,13 @@
 
     <!-- thickness (height) of each notification row, including any separators or padding -->
     <dimen name="notification_height">65dp</dimen>
-</resources>
 
+    <!-- Height of notification icons in the status bar -->
+    <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
+
+    <!-- size at which Notification icons will be drawn in the status bar -->
+    <dimen name="status_bar_icon_drawing_size">18dip</dimen>
+
+    <!-- opacity at which Notification icons will be drawn in the status bar -->
+    <item type="dimen" name="status_bar_icon_drawing_alpha">40%</item>
+</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 882455e..5ca77fc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -35,6 +35,14 @@
          shown again. [CHAR LIMIT=25] -->
     <string name="status_bar_please_disturb_button">Show notifications</string>
 
+    <!-- Title shown in recents popup for removing an application from the list -->
+    <string name="status_bar_recent_remove_item_title">Remove</string>
+
+    <!-- Title shown in recents popup for inspecting an application's properties -->
+    <string name="status_bar_recent_inspect_item_title">Inspect</string>
+
+
+
 
     <!-- The label in the bar at the top of the status bar when there are no notifications
          showing.  [CHAR LIMIT=40]-->
@@ -150,7 +158,7 @@
     <!-- Checkbox label for application compatibility mode OFF (normal mode on tablets).
          [CHAR LIMIT=25] -->
     <string name="compat_mode_off">Stretch to fill screen</string>
-    
+
     <!-- Compatibility mode help screen: header text. [CHAR LIMIT=50] -->
     <string name="compat_mode_help_header">Compatibility Zoom</string>
 
@@ -160,5 +168,167 @@
     <!-- 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>
+    <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string>
+
+    <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
+    <string name="usb_preference_title">USB file transfer options</string>
+    <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
+    <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
+    <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
+
+    <!-- Content description of the back button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_back">Back</string>
+    <!-- Content description of the home button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_home">Home</string>
+    <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_menu">Menu</string>
+
+    <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ime_switch_button">Switch input method button.</string>
+    <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
+
+    <!-- Content description of picture of the compatibility zoom example for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_compatibility_zoom_example">Zoom smaller to larger screen.</string>
+
+    <!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
+    <!-- Content description of the bluetooth icon when connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_disconnected">Bluetooth disconnected.</string>
+
+    <!-- Content description of the battery when no battery for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_battery">No battery.</string>
+    <!-- Content description of the battery when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_one_bar">Battery one bar.</string>
+    <!-- Content description of the battery when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_two_bars">Battery two bars.</string>
+     <!-- Content description of the battery when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_three_bars">Battery three bars.</string>
+    <!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_full">Battery full.</string>
+
+    <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_phone">No phone.</string>
+    <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_one_bar">Phone one bar.</string>
+    <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_two_bars">Phone two bars.</string>
+    <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_three_bars">Phone three bars.</string>
+    <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_signal_full">Phone signal full.</string>
+
+    <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_data">No data.</string>
+    <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_one_bar">Data one bar.</string>
+    <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_two_bars">Data two bars.</string>
+    <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_three_bars">Data three bars.</string>
+    <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_signal_full">Data signal full.</string>
+
+    <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_wifi">No WiFi.</string>
+    <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_one_bar">WiFi one bar.</string>
+    <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_two_bars">WiFi two bars.</string>
+    <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_three_bars">WiFi three bars.</string>
+    <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_signal_full">WiFi signal full.</string>
+
+    <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_gprs">GPRS</string>
+
+    <!-- Content description of the data connection type 3G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_3g">3G</string>
+
+    <!-- Content description of the data connection type 3.5G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_3.5g">3.5G</string>
+
+    <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_4g">4G</string>
+
+    <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_cdma">CDMA</string>
+
+    <!-- Content description of the data connection type Edge for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_edge">Edge</string>
+
+    <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_wifi">WiFi</string>
+
+    <!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_sim">No SIM.</string>
+
+    <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
+
+    <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_airplane_mode">Airplane mode.</string>
+
+    <!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
+
+    <!-- Content description of the button for showing a settings panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_settings_button">Settings button.</string>
+
+    <!-- Content description of the button for showing a notifications panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_notifications_button">Notifications button.</string>
+
+    <!-- Content description of the button for removing a notification in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_remove_notification">Remove notification.</string>
+
+    <!-- Content description of the enabled GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_gps_enabled">GPS enabled.</string>
+
+    <!-- Content description of the acquiring GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_gps_acquiring">GPS acquiring.</string>
+
+    <!-- Content description of the TeleTypewriter(TTY) enabled icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_tty_enabled">TeleTypewriter enabled.</string>
+
+    <!-- Content description of the ringer vibrate icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ringer_vibrate">Ringer vibrate.</string>
+
+    <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ringer_silent">Ringer silent.</string>
+
+    <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
+    <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_4g_title">4G data disabled</string>
+    <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_mobile_title">Mobile data disabled</string>
+    <!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_title">Data disabled</string>
+    <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
+    <string name="data_usage_disabled_dialog">The specified data usage limit has been reached.\n\nAdditional data use may incur carrier charges.</string>
+    <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
+    <string name="data_usage_disabled_dialog_enable">Re-enable data</string>
+
+    <!-- Text to display underneath the graphical signal strength meter when
+         no connection is available. [CHAR LIMIT=20] -->
+    <string name="status_bar_settings_signal_meter_disconnected">
+        No Internet connection
+    </string>
+
+    <!-- Text to display underneath the graphical signal strength meter when
+         it is displaying Wi-Fi status and Wi-Fi is connected to a network
+         whose SSID is not available.
+         [CHAR LIMIT=20] -->
+    <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string>
+
+    <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] -->
+    <string name="gps_notification_searching_text">Searching for GPS</string>
+
+    <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
+    <string name="gps_notification_found_text">Location set by GPS</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
new file mode 100644
index 0000000..de005aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Performs a number of miscellaneous, non-system-critical actions
+ * after the system has finished booting.
+ */
+public class BootReceiver extends BroadcastReceiver {
+    private static final String TAG = "SystemUIBootReceiver";
+
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        try {
+            // Start the load average overlay, if activated
+            ContentResolver res = context.getContentResolver();
+            if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
+                Intent loadavg = new Intent(context, com.android.systemui.LoadAverageService.class);
+                context.startService(loadavg);
+            }
+        } catch (Exception e) {
+            Slog.e(TAG, "Can't start load average service", e);
+        }
+    }
+}
diff --git a/services/java/com/android/server/LoadAverageService.java b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
similarity index 80%
rename from services/java/com/android/server/LoadAverageService.java
rename to packages/SystemUI/src/com/android/systemui/LoadAverageService.java
index da9fc99..67dc3cd 100644
--- a/services/java/com/android/server/LoadAverageService.java
+++ b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.systemui;
+
+import com.android.internal.os.ProcessStats;
 
 import android.app.Service;
 import android.content.Context;
@@ -28,7 +30,6 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 
 public class LoadAverageService extends Service {
     private View mView;
@@ -91,32 +92,46 @@
             setPadding(4, 4, 4, 4);
             //setBackgroundResource(com.android.internal.R.drawable.load_average_background);
 
+            // Need to scale text size by density...  but we won't do it
+            // linearly, because with higher dps it is nice to squeeze the
+            // text a bit to fit more of it.  And with lower dps, trying to
+            // go much smaller will result in unreadable text.
+            int textSize = 10;
+            float density = c.getResources().getDisplayMetrics().density;
+            if (density < 1) {
+                textSize = 9;
+            } else {
+                textSize = (int)(10*density);
+                if (textSize < 10) {
+                    textSize = 10;
+                }
+            }
             mLoadPaint = new Paint();
             mLoadPaint.setAntiAlias(true);
-            mLoadPaint.setTextSize(10);
+            mLoadPaint.setTextSize(textSize);
             mLoadPaint.setARGB(255, 255, 255, 255);
 
             mAddedPaint = new Paint();
             mAddedPaint.setAntiAlias(true);
-            mAddedPaint.setTextSize(10);
+            mAddedPaint.setTextSize(textSize);
             mAddedPaint.setARGB(255, 128, 255, 128);
 
             mRemovedPaint = new Paint();
             mRemovedPaint.setAntiAlias(true);
             mRemovedPaint.setStrikeThruText(true);
-            mRemovedPaint.setTextSize(10);
+            mRemovedPaint.setTextSize(textSize);
             mRemovedPaint.setARGB(255, 255, 128, 128);
 
             mShadowPaint = new Paint();
             mShadowPaint.setAntiAlias(true);
-            mShadowPaint.setTextSize(10);
+            mShadowPaint.setTextSize(textSize);
             //mShadowPaint.setFakeBoldText(true);
             mShadowPaint.setARGB(192, 0, 0, 0);
             mLoadPaint.setShadowLayer(4, 0, 0, 0xff000000);
 
             mShadow2Paint = new Paint();
             mShadow2Paint.setAntiAlias(true);
-            mShadow2Paint.setTextSize(10);
+            mShadow2Paint.setTextSize(textSize);
             //mShadow2Paint.setFakeBoldText(true);
             mShadow2Paint.setARGB(192, 0, 0, 0);
             mLoadPaint.setShadowLayer(2, 0, 0, 0xff000000);
@@ -153,14 +168,16 @@
         }
 
         @Override
-        protected void onMeasure(int widthMeasureSpect, int heightMeasureSpec) {
-            setMeasuredDimension(mNeededWidth, mNeededHeight);
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
+                    resolveSize(mNeededHeight, heightMeasureSpec));
         }
 
         @Override
         public void onDraw(Canvas canvas) {
             super.onDraw(canvas);
-            final int W = getWidth();
+            final int W = mNeededWidth;
+            final int RIGHT = getWidth()-1;
 
             final Stats stats = mStats;
             final int userTime = stats.getLastUserTime();
@@ -178,7 +195,7 @@
             int systemW = (systemTime*W)/totalTime;
             int irqW = ((iowaitTime+irqTime+softIrqTime)*W)/totalTime;
 
-            int x = W - mPaddingRight;
+            int x = RIGHT - mPaddingRight;
             int top = mPaddingTop + 2;
             int bottom = mPaddingTop + mFH - 2;
 
@@ -196,15 +213,15 @@
             }
 
             int y = mPaddingTop - (int)mAscent;
-            canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth-1,
+            canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
                     y-1, mShadowPaint);
-            canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth-1,
+            canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
                     y+1, mShadowPaint);
-            canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth+1,
+            canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
                     y-1, mShadow2Paint);
-            canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth+1,
+            canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
                     y+1, mShadow2Paint);
-            canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth,
+            canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth,
                     y, mLoadPaint);
 
             int N = stats.countWorkingStats();
@@ -216,7 +233,7 @@
 
                 userW = (st.rel_utime*W)/totalTime;
                 systemW = (st.rel_stime*W)/totalTime;
-                x = W - mPaddingRight;
+                x = RIGHT - mPaddingRight;
                 if (systemW > 0) {
                     canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
                     x -= systemW;
@@ -226,18 +243,18 @@
                     x -= userW;
                 }
 
-                canvas.drawText(st.name, W-mPaddingRight-st.nameWidth-1,
+                canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
                         y-1, mShadowPaint);
-                canvas.drawText(st.name, W-mPaddingRight-st.nameWidth-1,
+                canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
                         y+1, mShadowPaint);
-                canvas.drawText(st.name, W-mPaddingRight-st.nameWidth+1,
+                canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
                         y-1, mShadow2Paint);
-                canvas.drawText(st.name, W-mPaddingRight-st.nameWidth+1,
+                canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
                         y+1, mShadow2Paint);
                 Paint p = mLoadPaint;
                 if (st.added) p = mAddedPaint;
                 if (st.removed) p = mRemovedPaint;
-                canvas.drawText(st.name, W-mPaddingRight-st.nameWidth, y, p);
+                canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth, y, p);
             }
         }
 
@@ -270,7 +287,7 @@
         super.onCreate();
         mView = new LoadView(this);
         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
-            WindowManager.LayoutParams.WRAP_CONTENT,
+            WindowManager.LayoutParams.MATCH_PARENT,
             WindowManager.LayoutParams.WRAP_CONTENT,
             WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
new file mode 100644
index 0000000..eaffd1a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -0,0 +1,317 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.graphics.RectF;
+import android.util.Log;
+import android.view.animation.LinearInterpolator;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+
+public class SwipeHelper {
+    static final String TAG = "com.android.systemui.SwipeHelper";
+    private static final boolean DEBUG = true;
+    private static final boolean DEBUG_INVALIDATE = false;
+    private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
+
+    public static final int X = 0;
+    public static final int Y = 1;
+
+    private boolean CONSTRAIN_SWIPE = true;
+    private boolean FADE_OUT_DURING_SWIPE = true;
+    private boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true;
+
+    private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
+    private int MAX_ESCAPE_ANIMATION_DURATION = 500; // ms
+    private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms
+
+    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
+
+    private float mPagingTouchSlop;
+    private Callback mCallback;
+    private int mSwipeDirection;
+    private VelocityTracker mVelocityTracker;
+
+    private float mInitialTouchPos;
+    private boolean mDragging;
+    private View mCurrView;
+    private float mDensityScale;
+
+    public SwipeHelper(int swipeDirection, Callback callback, float densityScale,
+            float pagingTouchSlop) {
+        mCallback = callback;
+        mSwipeDirection = swipeDirection;
+        mVelocityTracker = VelocityTracker.obtain();
+        mDensityScale = densityScale;
+        mPagingTouchSlop = pagingTouchSlop;
+    }
+
+    public void setDensityScale(float densityScale) {
+        mDensityScale = densityScale;
+    }
+
+    public void setPagingTouchSlop(float pagingTouchSlop) {
+        mPagingTouchSlop = pagingTouchSlop;
+    }
+
+    private float getPos(MotionEvent ev) {
+        return mSwipeDirection == X ? ev.getX() : ev.getY();
+    }
+
+    private float getPos(View v) {
+        return mSwipeDirection == X ? v.getX() : v.getY();
+    }
+
+    private float getVelocity(VelocityTracker vt) {
+        return mSwipeDirection == X ? vt.getXVelocity() :
+                vt.getYVelocity();
+    }
+
+    private ObjectAnimator createTranslationAnimation(View v, float newPos) {
+        ObjectAnimator anim = ObjectAnimator.ofFloat(v,
+                mSwipeDirection == X ? "translationX" : "translationY", newPos);
+        return anim;
+    }
+
+    private float getPerpendicularVelocity(VelocityTracker vt) {
+        return mSwipeDirection == X ? vt.getYVelocity() :
+                vt.getXVelocity();
+    }
+
+    private void setTranslation(View v, float translate) {
+        if (mSwipeDirection == X) {
+            v.setTranslationX(translate);
+        } else {
+            v.setTranslationY(translate);
+        }
+    }
+
+    private float getSize(View v) {
+        return mSwipeDirection == X ? v.getMeasuredWidth() :
+                v.getMeasuredHeight();
+    }
+
+    private float getContentSize(View v) {
+        View content = mCallback.getChildContentView(v);
+        return getSize(content);
+    }
+
+    private float getAlphaForOffset(View view, float thumbSize) {
+        final float fadeSize = ALPHA_FADE_END * thumbSize;
+        float result = 1.0f;
+        float pos = getPos(view);
+        if (pos >= thumbSize * ALPHA_FADE_START) {
+            result = 1.0f - (pos - thumbSize * ALPHA_FADE_START) / fadeSize;
+        } else if (pos < thumbSize * (1.0f - ALPHA_FADE_START)) {
+            result = 1.0f + (thumbSize * ALPHA_FADE_START + pos) / fadeSize;
+        }
+        return result;
+    }
+
+    void invalidateGlobalRegion(View view) {
+        RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view
+                .getBottom());
+        childBounds.offset(view.getX(), view.getY());
+        if (DEBUG_INVALIDATE)
+            Log.v(TAG, "-------------");
+        while (view.getParent() != null && view.getParent() instanceof View) {
+            view = (View) view.getParent();
+            view.getMatrix().mapRect(childBounds);
+            view.invalidate((int) Math.floor(childBounds.left),
+                            (int) Math.floor(childBounds.top),
+                            (int) Math.ceil(childBounds.right),
+                            (int) Math.ceil(childBounds.bottom));
+            if (DEBUG_INVALIDATE) {
+                Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
+                        + "," + (int) Math.floor(childBounds.top)
+                        + "," + (int) Math.ceil(childBounds.right)
+                        + "," + (int) Math.ceil(childBounds.bottom));
+            }
+        }
+    }
+
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mDragging = false;
+                mCurrView = mCallback.getChildAtPosition(ev);
+                mVelocityTracker.clear();
+                mVelocityTracker.addMovement(ev);
+                mInitialTouchPos = getPos(ev);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mCurrView != null) {
+                    mVelocityTracker.addMovement(ev);
+                    float pos = getPos(ev);
+                    float delta = pos - mInitialTouchPos;
+                    if (Math.abs(delta) > mPagingTouchSlop) {
+                        mCallback.onBeginDrag(mCurrView);
+                        mDragging = true;
+                        mInitialTouchPos = getPos(ev) - getPos(mCurrView);
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                mDragging = false;
+                mCurrView = null;
+                break;
+        }
+        return mDragging;
+    }
+
+    public void dismissChild(final View animView, float velocity) {
+        float newPos;
+        if (velocity < 0 || (velocity == 0 && getPos(animView) < 0)) {
+            newPos = -getSize(animView);
+        } else {
+            newPos = getSize(animView);
+        }
+        int duration = MAX_ESCAPE_ANIMATION_DURATION;
+        if (velocity != 0) {
+            duration = Math.min(duration,
+                                (int) (Math.abs(newPos - getPos(animView)) * 1000f / Math
+                                        .abs(velocity)));
+        }
+        ObjectAnimator anim = createTranslationAnimation(animView, newPos);
+        anim.setInterpolator(new LinearInterpolator());
+        anim.setDuration(duration);
+        anim.addListener(new AnimatorListener() {
+            public void onAnimationStart(Animator animation) {
+            }
+
+            public void onAnimationRepeat(Animator animation) {
+            }
+
+            public void onAnimationEnd(Animator animation) {
+                mCallback.onChildDismissed(animView);
+            }
+
+            public void onAnimationCancel(Animator animation) {
+                mCallback.onChildDismissed(animView);
+            }
+        });
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                if (FADE_OUT_DURING_SWIPE) {
+                    animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView)));
+                }
+                invalidateGlobalRegion(animView);
+            }
+        });
+        anim.start();
+    }
+
+    public void snapChild(final View animView, float velocity) {
+        ObjectAnimator anim = createTranslationAnimation(animView, 0);
+        int duration = SNAP_ANIM_LEN;
+        anim.setDuration(duration);
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                if (FADE_OUT_DURING_SWIPE) {
+                    animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView)));
+                }
+                invalidateGlobalRegion(animView);
+            }
+        });
+        anim.start();
+    }
+
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (!mDragging) {
+            return false;
+        }
+
+        mVelocityTracker.addMovement(ev);
+        final int action = ev.getAction();
+        switch (action) {
+            case MotionEvent.ACTION_OUTSIDE:
+            case MotionEvent.ACTION_MOVE:
+                if (mCurrView != null) {
+                    float delta = getPos(ev) - mInitialTouchPos;
+                    // don't let items that can't be dismissed be dragged more than
+                    // maxScrollDistance
+                    if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
+                        float size = getSize(mCurrView);
+                        float maxScrollDistance = 0.15f * size;
+                        if (Math.abs(delta) >= size) {
+                            delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
+                        } else {
+                            delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
+                        }
+                    }
+                    setTranslation(mCurrView, delta);
+                    if (FADE_OUT_DURING_SWIPE) {
+                        mCurrView.setAlpha(getAlphaForOffset(mCurrView, getContentSize(mCurrView)));
+                    }
+                    invalidateGlobalRegion(mCurrView);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                if (mCurrView != null) {
+                    float maxVelocity = 1000; // px/sec
+                    mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity);
+                    float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
+                    float velocity = getVelocity(mVelocityTracker);
+                    float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+
+                    // Decide whether to dismiss the current view
+                    boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
+                            Math.abs(getPos(mCurrView)) > 0.4 * getSize(mCurrView);
+                    boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
+                            (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
+                            (velocity > 0) == (getPos(mCurrView) > 0);
+
+                    boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) &&
+                            (childSwipedFastEnough || childSwipedFarEnough);
+
+                    if (dismissChild) {
+                        // flingadingy
+                        dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
+                    } else {
+                        // snappity
+                        snapChild(mCurrView, velocity);
+                    }
+                }
+                break;
+        }
+        return true;
+    }
+
+    public interface Callback {
+        View getChildAtPosition(MotionEvent ev);
+
+        View getChildContentView(View v);
+
+        boolean canChildBeDismissed(View v);
+
+        void onBeginDrag(View v);
+
+        void onChildDismissed(View v);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
new file mode 100644
index 0000000..723e338
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
@@ -0,0 +1,98 @@
+/*
+ * 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.net;
+
+import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
+import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
+import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
+import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.INetworkPolicyManager;
+import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+/**
+ * Notify user that a {@link NetworkTemplate} is over its
+ * {@link NetworkPolicy#limitBytes}, giving them the choice of acknowledging or
+ * "snoozing" the limit.
+ */
+public class NetworkOverLimitActivity extends Activity {
+    private static final String TAG = "NetworkOverLimitActivity";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        final NetworkTemplate template = getIntent().getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setTitle(getLimitedDialogTitleForTemplate(template));
+        builder.setMessage(R.string.data_usage_disabled_dialog);
+
+        builder.setPositiveButton(android.R.string.ok, null);
+        builder.setNegativeButton(
+                R.string.data_usage_disabled_dialog_enable, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        snoozePolicy(template);
+                    }
+                });
+
+        final Dialog dialog = builder.create();
+        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+            public void onDismiss(DialogInterface dialog) {
+                finish();
+            }
+        });
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void snoozePolicy(NetworkTemplate template) {
+        final INetworkPolicyManager policyService = INetworkPolicyManager.Stub.asInterface(
+                ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
+        try {
+            policyService.snoozePolicy(template);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "problem snoozing network policy", e);
+        }
+    }
+
+    private static int getLimitedDialogTitleForTemplate(NetworkTemplate template) {
+        switch (template.getMatchRule()) {
+            case MATCH_MOBILE_3G_LOWER:
+                return R.string.data_usage_disabled_dialog_3g_title;
+            case MATCH_MOBILE_4G:
+                return R.string.data_usage_disabled_dialog_4g_title;
+            case MATCH_MOBILE_ALL:
+                return R.string.data_usage_disabled_dialog_mobile_title;
+            default:
+                return R.string.data_usage_disabled_dialog_title;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index a549f51..fe7d5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -45,6 +45,8 @@
 public class PowerUI extends SystemUI {
     static final String TAG = "PowerUI";
 
+    static final boolean DEBUG = false;
+
     Handler mHandler = new Handler();
 
     int mBatteryLevel = 100;
@@ -122,7 +124,7 @@
                 int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                 int bucket = findBatteryLevelBucket(mBatteryLevel);
 
-                if (false) {
+                if (DEBUG) {
                     Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
                             + " .. " + mLowBatteryReminderLevels[0]
                             + " .. " + mLowBatteryReminderLevels[1]);
@@ -149,8 +151,12 @@
                         && (bucket < oldBucket || oldPlugged)
                         && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
                         && bucket < 0) {
-                    Slog.i(TAG, "showing low battery warning: level=" + mBatteryLevel);
                     showLowBatteryWarning();
+
+                    // only play SFX when the dialog comes up or the bucket changes
+                    if (bucket != oldBucket || oldPlugged) {
+                        playLowBatterySound();
+                    }
                 } else if (plugged || (bucket > oldBucket && bucket > 0)) {
                     dismissLowBatteryWarning();
                 } else if (mBatteryLevelTextView != null) {
@@ -170,6 +176,11 @@
     }
 
     void showLowBatteryWarning() {
+        Slog.i(TAG,
+                ((mBatteryLevelTextView == null) ? "showing" : "updating")
+                + " low battery warning: level=" + mBatteryLevel
+                + " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
+
         CharSequence levelText = mContext.getString(
                 R.string.battery_low_percent_format, mBatteryLevel);
 
@@ -198,9 +209,7 @@
                         new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
                         mContext.startActivity(intent);
-                        if (mLowBatteryDialog != null) {
-                            mLowBatteryDialog.dismiss();
-                        }
+                        dismissLowBatteryWarning();
                     }
                 });
             }
@@ -216,6 +225,12 @@
             d.show();
             mLowBatteryDialog = d;
         }
+    }
+
+    void playLowBatterySound() {
+        if (DEBUG) {
+            Slog.i(TAG, "playing low battery sound. WOMP-WOMP!");
+        }
 
         final ContentResolver cr = mContext.getContentResolver();
         if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
@@ -236,12 +251,13 @@
 
     void dismissInvalidChargerDialog() {
         if (mInvalidChargerDialog != null) {
-            Slog.d(TAG, "closing invalid charger warning");
             mInvalidChargerDialog.dismiss();
         }
     }
 
     void showInvalidChargerDialog() {
+        Slog.d(TAG, "showing invalid charger dialog");
+
         dismissLowBatteryWarning();
 
         AlertDialog.Builder b = new AlertDialog.Builder(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 37a9913..2d327c4 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -53,8 +53,6 @@
     void createAnimation(boolean appearing) {
         float start, end;
 
-        if (RecentsPanelView.DEBUG) Log.e(TAG, "createAnimation()", new Exception());
-
         // 0: on-screen
         // height: off-screen
         float y = mContentView.getTranslationY();
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
index 5d29e2a..5609ead 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
@@ -25,6 +25,6 @@
     static final int SWIPE_DOWN = 3;
 
     void handleOnClick(View selectedView);
-    void handleSwipe(View selectedView, int direction);
-    void handleLongPress(View selectedView);
+    void handleSwipe(View selectedView);
+    void handleLongPress(View selectedView, View anchorView);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index f984aac..14efdd0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -16,47 +16,38 @@
 
 package com.android.systemui.recent;
 
-import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
-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;
 import android.util.Log;
-import android.view.LayoutInflater;
 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;
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
 
 public class RecentsHorizontalScrollView extends HorizontalScrollView
-        implements View.OnClickListener, View.OnTouchListener {
-    private static final boolean DEBUG_INVALIDATE = false;
+    implements SwipeHelper.Callback {
     private static final String TAG = RecentsPanelView.TAG;
     private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
     protected int mLastScrollPosition;
-    private View mCurrentView;
-    private float mLastY;
-    private boolean mDragging;
-    private VelocityTracker mVelocityTracker;
-    private float mDensityScale;
-    private float mPagingTouchSlop;
+    private SwipeHelper mSwipeHelper;
+    private OnLongClickListener mOnLongClick = new OnLongClickListener() {
+        public boolean onLongClick(View v) {
+            final View anchorView = v.findViewById(R.id.app_description);
+            mCallback.handleLongPress(v, anchorView);
+            return true;
+        }
+    };
 
     public RecentsHorizontalScrollView(Context context) {
         this(context, null);
@@ -64,21 +55,29 @@
 
     public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
-        mDensityScale = getResources().getDisplayMetrics().density;
-        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        float densityScale = getResources().getDisplayMetrics().density;
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop);
     }
 
     private int scrollPositionOfMostRecent() {
         return mLinearLayout.getWidth() - getWidth();
     }
 
-    public void update() {
+    private void update() {
         mLinearLayout.removeAllViews();
         for (int i = 0; i < mAdapter.getCount(); i++) {
-            View view = mAdapter.getView(i, null, mLinearLayout);
-            view.setClickable(true);
-            view.setOnClickListener(this);
-            view.setOnTouchListener(this);
+            final View view = mAdapter.getView(i, null, mLinearLayout);
+            view.setLongClickable(true);
+            view.setOnLongClickListener(mOnLongClick);
+
+            final View thumbnail = getChildContentView(view);
+            // thumbnail is set to clickable in the layout file
+            thumbnail.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mCallback.handleOnClick(view);
+                }
+            });
             mLinearLayout.addView(view);
         }
         // Scroll to end after layout.
@@ -91,158 +90,60 @@
     }
 
     @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-        mVelocityTracker.addMovement(ev);
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mDragging = false;
-                mLastY = ev.getY();
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                float delta = ev.getY() - mLastY;
-                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
-                if (Math.abs(delta) > mPagingTouchSlop) {
-                    mDragging = true;
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-                mDragging = false;
-                break;
-        }
-        return mDragging ? true : super.onInterceptTouchEvent(ev);
+    public void removeViewInLayout(final View view) {
+        dismissChild(view);
     }
 
-    private float getAlphaForOffset(View view, float thumbHeight) {
-        final float fadeHeight = Constants.ALPHA_FADE_END * thumbHeight;
-        float result = 1.0f;
-        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;
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
+        return mSwipeHelper.onInterceptTouchEvent(ev) ||
+            super.onInterceptTouchEvent(ev);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (!mDragging) {
-            return super.onTouchEvent(ev);
-        }
+        return mSwipeHelper.onTouchEvent(ev) ||
+            super.onTouchEvent(ev);
+    }
 
-        mVelocityTracker.addMovement(ev);
-
-        final View animView = mCurrentView;
-        // TODO: Cache thumbnail
-        final View thumb = animView.findViewById(R.id.app_thumbnail);
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_MOVE:
-                if (animView != null) {
-                    final float delta = ev.getY() - mLastY;
-                    animView.setY(animView.getY() + delta);
-                    animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
-                    invalidateGlobalRegion(animView);
-                }
-                mLastY = ev.getY();
-                break;
-
-            case MotionEvent.ACTION_UP:
-                final ObjectAnimator anim;
-                if (animView != null) {
-                    final VelocityTracker velocityTracker = mVelocityTracker;
-                    velocityTracker.computeCurrentVelocity(1000, 10000);
-                    final float velocityX = velocityTracker.getXVelocity();
-                    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) > maxVelocity
-                            && (velocityY >= 0.0f) == (animView.getY() >= 0)) {
-                        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 ?
-                                RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
-                        anim.addListener(new AnimatorListener() {
-                            public void onAnimationStart(Animator animation) {
-                            }
-                            public void onAnimationRepeat(Animator animation) {
-                            }
-                            public void onAnimationEnd(Animator animation) {
-                                mLinearLayout.removeView(mCurrentView);
-                                mCallback.handleSwipe(animView, swipeDirection);
-                            }
-                            public void onAnimationCancel(Animator animation) {
-                                mLinearLayout.removeView(mCurrentView);
-                                mCallback.handleSwipe(animView, swipeDirection);
-                            }
-                        });
-                        anim.setDuration(duration);
-                    } else { // Animate back to position
-                        long duration = Math.abs(velocityY) > 0.0f ?
-                                (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
-                                : 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);
-                    }
-
-                    anim.addUpdateListener(new AnimatorUpdateListener() {
-                        public void onAnimationUpdate(ValueAnimator animation) {
-                            animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
-                            invalidateGlobalRegion(animView);
-                        }
-                    });
-                    anim.start();
-                }
-
-                mVelocityTracker.recycle();
-                mVelocityTracker = null;
-                break;
-        }
+    public boolean canChildBeDismissed(View v) {
         return true;
     }
 
-    void invalidateGlobalRegion(View view) {
-        RectF childBounds
-                = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
-        childBounds.offset(view.getX(), view.getY());
-        if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
-        while (view.getParent() != null && view.getParent() instanceof View) {
-            view = (View) view.getParent();
-            view.getMatrix().mapRect(childBounds);
-            view.invalidate((int) Math.floor(childBounds.left),
-                    (int) Math.floor(childBounds.top),
-                    (int) Math.ceil(childBounds.right),
-                    (int) Math.ceil(childBounds.bottom));
-            if (DEBUG_INVALIDATE) {
-                Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
-                        + "," + (int) Math.floor(childBounds.top)
-                        + "," + (int) Math.ceil(childBounds.right)
-                        + "," + (int) Math.ceil(childBounds.bottom));
+    public void dismissChild(View v) {
+        mSwipeHelper.dismissChild(v, 0);
+    }
+
+    public void onChildDismissed(View v) {
+        mLinearLayout.removeView(v);
+        mCallback.handleSwipe(v);
+    }
+
+    public void onBeginDrag(View v) {
+    }
+
+    public View getChildAtPosition(MotionEvent ev) {
+        final float x = ev.getX() + getScrollX();
+        final float y = ev.getY() + getScrollY();
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View item = mLinearLayout.getChildAt(i);
+            if (x >= item.getLeft() && x < item.getRight()
+                && y >= item.getTop() && y < item.getBottom()) {
+                return item;
             }
         }
+        return null;
+    }
+
+    public View getChildContentView(View v) {
+        return v.findViewById(R.id.app_thumbnail);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        LayoutInflater inflater = (LayoutInflater)
-                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
         setScrollbarFadingEnabled(true);
-
         mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout);
-
         final int leftPadding = mContext.getResources()
             .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
         setOverScrollEffectPadding(leftPadding, 0);
@@ -251,8 +152,10 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mDensityScale = getResources().getDisplayMetrics().density;
-        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        float densityScale = getResources().getDisplayMetrics().density;
+        mSwipeHelper.setDensityScale(densityScale);
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
     }
 
     private void setOverScrollEffectPadding(int leftPadding, int i) {
@@ -306,16 +209,7 @@
         mLinearLayout.setLayoutTransition(transition);
     }
 
-    public void onClick(View view) {
-        mCallback.handleOnClick(view);
-    }
-
     public void setCallback(RecentsCallback callback) {
         mCallback = callback;
     }
-
-    public boolean onTouch(View v, MotionEvent event) {
-        mCurrentView = v;
-        return false;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index a55fe9c..e988b68 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -39,16 +39,23 @@
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.net.Uri;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
+import android.widget.Button;
 import android.widget.ImageView;
+import android.widget.PopupMenu;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
@@ -69,7 +76,7 @@
     private int mIconDpi;
     private View mRecentsScrim;
     private View mRecentsGlowView;
-    private View mRecentsContainer;
+    private ViewGroup mRecentsContainer;
     private Bitmap mGlowBitmap;
     // TODO: add these widgets attributes to the layout file
     private int mGlowBitmapPaddingLeftPx;
@@ -105,10 +112,20 @@
             position = _pos;
             packageName = _packageName;
         }
-    };
+    }
+
+    private final class OnLongClickDelegate implements View.OnLongClickListener {
+        View mOtherView;
+        OnLongClickDelegate(View other) {
+            mOtherView = other;
+        }
+        public boolean onLongClick(View v) {
+            return mOtherView.performLongClick();
+        }
+    }
 
     /* package */ final static class ViewHolder {
-        ImageView thumbnailView;
+        View thumbnailView;
         ImageView iconView;
         TextView labelView;
         TextView descriptionView;
@@ -139,7 +156,7 @@
             if (convertView == null) {
                 convertView = mInflater.inflate(R.layout.status_bar_recent_item, null);
                 holder = new ViewHolder();
-                holder.thumbnailView = (ImageView) convertView.findViewById(R.id.app_thumbnail);
+                holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
                 holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
                 holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
                 holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -153,11 +170,12 @@
 
             final ActivityDescription activityDescription = mActivityDescriptions.get(activityId);
             final Bitmap thumb = activityDescription.thumbnail;
-            holder.thumbnailView.setImageBitmap(compositeBitmap(mGlowBitmap, thumb));
+            updateDrawable(holder.thumbnailView, compositeBitmap(mGlowBitmap, thumb));
             holder.iconView.setImageDrawable(activityDescription.icon);
             holder.labelView.setText(activityDescription.label);
             holder.descriptionView.setText(activityDescription.description);
             holder.thumbnailView.setTag(activityDescription);
+            holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
             holder.activityDescription = activityDescription;
 
             return convertView;
@@ -174,6 +192,20 @@
         return x >= l && x < r && y >= t && y < b;
     }
 
+    private void updateDrawable(View thumbnailView, Bitmap bitmap) {
+        Drawable d = thumbnailView.getBackground();
+        if (d instanceof LayerDrawable) {
+            LayerDrawable layerD = (LayerDrawable) d;
+            Drawable thumb = layerD.findDrawableByLayerId(R.id.base_layer);
+            if (thumb != null) {
+                layerD.setDrawableByLayerId(R.id.base_layer,
+                        new BitmapDrawable(getResources(), bitmap));
+                return;
+            }
+        }
+        Log.w(TAG, "Failed to update drawable");
+    }
+
     public void show(boolean show, boolean animate) {
         if (animate) {
             if (mShowing != show) {
@@ -220,6 +252,19 @@
         mChoreo.setPanelHeight(mRecentsContainer.getHeight());
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     /**
      * Whether the panel is showing, or, if it's animating, whether it will be
      * when the animation is done.
@@ -260,7 +305,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mRecentsContainer = findViewById(R.id.recents_container);
+        mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container);
         mListAdapter = new ActivityDescriptionAdapter(mContext);
         if (mRecentsContainer instanceof RecentsListView) {
             RecentsListView listView = (RecentsListView) mRecentsContainer;
@@ -484,7 +529,7 @@
         handleOnClick(view);
     }
 
-    public void handleSwipe(View view, int direction) {
+    public void handleSwipe(View view) {
         ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
         if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
         mActivityDescriptions.remove(ad);
@@ -503,7 +548,35 @@
         am.removeTask(ad.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
     }
 
-    public void handleLongPress(View selectedView) {
-        // TODO show context menu : "Remove from list", "Show properties"
+    private void startApplicationDetailsActivity(String packageName) {
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                Uri.fromParts("package", packageName, null));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getContext().startActivity(intent);
+    }
+
+    public void handleLongPress(final View selectedView, final View anchorView) {
+        PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView);
+        popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());
+        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+            public boolean onMenuItemClick(MenuItem item) {
+                if (item.getItemId() == R.id.recent_remove_item) {
+                    mRecentsContainer.removeViewInLayout(selectedView);
+                } else if (item.getItemId() == R.id.recent_inspect_item) {
+                    ViewHolder viewHolder = (ViewHolder) selectedView.getTag();
+                    if (viewHolder != null) {
+                        final ActivityDescription ad = viewHolder.activityDescription;
+                        startApplicationDetailsActivity(ad.packageName);
+                        mBar.animateCollapse();
+                    } else {
+                        throw new IllegalStateException("Oops, no tag on view " + selectedView);
+                    }
+                } else {
+                    return false;
+                }
+                return true;
+            }
+        });
+        popup.show();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 27bb0b5..1bcc413 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -16,47 +16,38 @@
 
 package com.android.systemui.recent;
 
-import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
-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;
 import android.util.Log;
-import android.view.LayoutInflater;
 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;
 import android.widget.ScrollView;
 
 import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
 
-public class RecentsVerticalScrollView extends ScrollView
-        implements View.OnClickListener, View.OnTouchListener {
+public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper.Callback {
     private static final String TAG = RecentsPanelView.TAG;
-    private static final boolean DEBUG_INVALIDATE = false;
     private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
     protected int mLastScrollPosition;
-    private View mCurrentView;
-    private float mLastX;
-    private boolean mDragging;
-    private VelocityTracker mVelocityTracker;
-    private float mDensityScale;
-    private float mPagingTouchSlop;
+    private SwipeHelper mSwipeHelper;
+
+    private OnLongClickListener mOnLongClick = new OnLongClickListener() {
+        public boolean onLongClick(View v) {
+            final View anchorView = v.findViewById(R.id.app_description);
+            mCallback.handleLongPress(v, anchorView);
+            return true;
+        }
+    };
 
     public RecentsVerticalScrollView(Context context) {
         this(context, null);
@@ -64,21 +55,30 @@
 
     public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
-        mDensityScale = getResources().getDisplayMetrics().density;
-        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        float densityScale = getResources().getDisplayMetrics().density;
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
     }
 
     private int scrollPositionOfMostRecent() {
         return mLinearLayout.getHeight() - getHeight();
     }
 
-    public void update() {
+    private void update() {
         mLinearLayout.removeAllViews();
         for (int i = 0; i < mAdapter.getCount(); i++) {
-            View view = mAdapter.getView(i, null, mLinearLayout);
+            final View view = mAdapter.getView(i, null, mLinearLayout);
             view.setClickable(true);
-            view.setOnClickListener(this);
-            view.setOnTouchListener(this);
+            view.setOnLongClickListener(mOnLongClick);
+
+            final View thumbnail = getChildContentView(view);
+            // thumbnail is set to clickable in the layout file
+            thumbnail.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mCallback.handleOnClick(view);
+                }
+            });
+
             mLinearLayout.addView(view);
         }
         // Scroll to end after layout.
@@ -91,158 +91,60 @@
     }
 
     @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-        mVelocityTracker.addMovement(ev);
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mDragging = false;
-                mLastX = ev.getX();
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                float delta = ev.getX() - mLastX;
-                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
-                if (Math.abs(delta) > mPagingTouchSlop) {
-                    mDragging = true;
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-                mDragging = false;
-                break;
-        }
-        return mDragging ? true : super.onInterceptTouchEvent(ev);
+    public void removeViewInLayout(final View view) {
+        dismissChild(view);
     }
 
-    private float getAlphaForOffset(View view, float thumbWidth) {
-        final float fadeWidth = Constants.ALPHA_FADE_END * thumbWidth;
-        float result = 1.0f;
-        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;
-        }
-        if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
-        return result;
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
+        return mSwipeHelper.onInterceptTouchEvent(ev) ||
+            super.onInterceptTouchEvent(ev);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (!mDragging) {
-            return super.onTouchEvent(ev);
-        }
+        return mSwipeHelper.onTouchEvent(ev) ||
+            super.onTouchEvent(ev);
+    }
 
-        mVelocityTracker.addMovement(ev);
-
-        final View animView = mCurrentView;
-        // TODO: Cache thumbnail
-        final View thumb = animView.findViewById(R.id.app_thumbnail);
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_MOVE:
-                if (animView != null) {
-                    final float delta = ev.getX() - mLastX;
-                    animView.setX(animView.getX() + delta);
-                    animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
-                    invalidateGlobalRegion(animView);
-                }
-                mLastX = ev.getX();
-                break;
-
-            case MotionEvent.ACTION_UP:
-                final ObjectAnimator anim;
-                if (animView != null) {
-                    final VelocityTracker velocityTracker = mVelocityTracker;
-                    velocityTracker.computeCurrentVelocity(1000, 10000);
-                    final float velocityX = velocityTracker.getXVelocity();
-                    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) > maxVelocity
-                            && (velocityX > 0.0f) == (animView.getX() >= 0)) {
-                        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 ?
-                                RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
-                        anim.addListener(new AnimatorListener() {
-                            public void onAnimationStart(Animator animation) {
-                            }
-                            public void onAnimationRepeat(Animator animation) {
-                            }
-                            public void onAnimationEnd(Animator animation) {
-                                mLinearLayout.removeView(mCurrentView);
-                                mCallback.handleSwipe(animView, swipeDirection);
-                            }
-                            public void onAnimationCancel(Animator animation) {
-                                mLinearLayout.removeView(mCurrentView);
-                                mCallback.handleSwipe(animView, swipeDirection);
-                            }
-                        });
-                        anim.setDuration(duration);
-                    } else { // Animate back to position
-                        long duration = Math.abs(velocityX) > 0.0f ?
-                                (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
-                                : 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);
-                    }
-
-                    anim.addUpdateListener(new AnimatorUpdateListener() {
-                        public void onAnimationUpdate(ValueAnimator animation) {
-                            animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
-                            invalidateGlobalRegion(animView);
-                        }
-                    });
-                    anim.start();
-                }
-
-                mVelocityTracker.recycle();
-                mVelocityTracker = null;
-                break;
-        }
+    public boolean canChildBeDismissed(View v) {
         return true;
     }
 
-    void invalidateGlobalRegion(View view) {
-        RectF childBounds
-                = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
-        childBounds.offset(view.getX(), view.getY());
-        if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
-        while (view.getParent() != null && view.getParent() instanceof View) {
-            view = (View) view.getParent();
-            view.getMatrix().mapRect(childBounds);
-            view.invalidate((int) Math.floor(childBounds.left),
-                    (int) Math.floor(childBounds.top),
-                    (int) Math.ceil(childBounds.right),
-                    (int) Math.ceil(childBounds.bottom));
-            if (DEBUG_INVALIDATE) {
-                Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
-                        + "," + (int) Math.floor(childBounds.top)
-                        + "," + (int) Math.ceil(childBounds.right)
-                        + "," + (int) Math.ceil(childBounds.bottom));
+    public void dismissChild(View v) {
+        mSwipeHelper.dismissChild(v, 0);
+    }
+
+    public void onChildDismissed(View v) {
+        mLinearLayout.removeView(v);
+        mCallback.handleSwipe(v);
+    }
+
+    public void onBeginDrag(View v) {
+    }
+
+    public View getChildAtPosition(MotionEvent ev) {
+        final float x = ev.getX() + getScrollX();
+        final float y = ev.getY() + getScrollY();
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View item = mLinearLayout.getChildAt(i);
+            if (x >= item.getLeft() && x < item.getRight()
+                && y >= item.getTop() && y < item.getBottom()) {
+                return item;
             }
         }
+        return null;
+    }
+
+    public View getChildContentView(View v) {
+        return v.findViewById(R.id.app_thumbnail);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        LayoutInflater inflater = (LayoutInflater)
-                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
         setScrollbarFadingEnabled(true);
-
         mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout);
-
         final int leftPadding = mContext.getResources()
             .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
         setOverScrollEffectPadding(leftPadding, 0);
@@ -251,8 +153,10 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mDensityScale = getResources().getDisplayMetrics().density;
-        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        float densityScale = getResources().getDisplayMetrics().density;
+        mSwipeHelper.setDensityScale(densityScale);
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
     }
 
     private void setOverScrollEffectPadding(int leftPadding, int i) {
@@ -306,16 +210,7 @@
         mLinearLayout.setLayoutTransition(transition);
     }
 
-    public void onClick(View view) {
-        mCallback.handleOnClick(view);
-    }
-
     public void setCallback(RecentsCallback callback) {
         mCallback = callback;
     }
-
-    public boolean onTouch(View v, MotionEvent event) {
-        mCurrentView = v;
-        return false;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 83a5578..3a47e6e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -24,6 +24,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.graphics.Bitmap;
@@ -78,7 +79,8 @@
         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";
+    private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+    private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
 
     @Override
     protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
@@ -87,34 +89,41 @@
         Context context = params[0].context;
         Bitmap image = params[0].image;
 
-        try{
+        try {
             long currentTime = System.currentTimeMillis();
-            String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
+            String date = new SimpleDateFormat("yyyy-MM-dd-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);
+            String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date);
+            String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
+                    SCREENSHOTS_DIR_NAME, imageFileName);
 
             // Save the screenshot to the MediaStore
             ContentValues values = new ContentValues();
+            ContentResolver resolver = context.getContentResolver();
             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.TITLE, imageFileName);
+            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName);
             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);
+            Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
 
-            OutputStream out = context.getContentResolver().openOutputStream(uri);
+            OutputStream out = resolver.openOutputStream(uri);
             image.compress(Bitmap.CompressFormat.PNG, 100, out);
             out.flush();
             out.close();
 
+            // update file size in the database
+            values.clear();
+            values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length());
+            resolver.update(uri, values, null, null);
+
             params[0].result = 0;
-        }catch(IOException e){
+        } catch (Exception e) {
+            // IOException/UnsupportedOperationException may be thrown if external storage is not
+            // mounted
             params[0].result = 1;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
index 64ec063..6419777 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Slog;
-import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
 public class LatestItemView extends FrameLayout {
@@ -27,7 +27,22 @@
         super(context, attrs);
     }
 
+    @Override
     public void setOnClickListener(OnClickListener l) {
         super.setOnClickListener(l);
     }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // Add a record for the entire layout since its content is somehow small.
+            // The event comes from a leaf view that is interacted with.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d9d9c06..1e27233 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.app.Notification;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
@@ -23,11 +24,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.Log;
-import android.view.View;
 import android.view.ViewDebug;
-import android.widget.FrameLayout;
+import android.view.accessibility.AccessibilityEvent;
 
 import java.text.NumberFormat;
 
@@ -45,8 +46,9 @@
     private int mNumberX;
     private int mNumberY;
     private String mNumberText;
+    private Notification mNotification;
 
-    public StatusBarIconView(Context context, String slot) {
+    public StatusBarIconView(Context context, String slot, Notification notification) {
         super(context);
         final Resources res = context.getResources();
         mSlot = slot;
@@ -54,6 +56,16 @@
         mNumberPain.setTextAlign(Paint.Align.CENTER);
         mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
         mNumberPain.setAntiAlias(true);
+        mNotification = notification;
+        setContentDescription(notification);
+
+        final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+        final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+        final float scale = (float)imageBounds / (float)outerBounds;
+        setScaleX(scale);
+        setScaleY(scale);
+        final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
+        setAlpha(alpha);
     }
 
     private static boolean streq(String a, String b) {
@@ -83,6 +95,7 @@
         final boolean numberEquals = mIcon != null
                 && mIcon.number == icon.number;
         mIcon = icon.clone();
+        setContentDescription(icon.contentDescription);
         if (!iconEquals) {
             Drawable drawable = getIcon(icon);
             if (drawable == null) {
@@ -94,6 +107,7 @@
         if (!levelEquals) {
             setImageLevel(icon.iconLevel);
         }
+
         if (!numberEquals) {
             if (icon.number > 0 && mContext.getResources().getBoolean(
                         R.bool.config_statusBarShowNumber)) {
@@ -159,6 +173,15 @@
         return mIcon;
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mNotification != null) {
+            event.setParcelableData(mNotification);
+        }
+    }
+
+    @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         if (mNumberBackground != null) {
@@ -166,6 +189,7 @@
         }
     }
 
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
@@ -175,6 +199,7 @@
         }
     }
 
+    @Override
     protected void debug(int depth) {
         super.debug(depth);
         Log.d("View", debugIndent(depth) + "slot=" + mSlot);
@@ -213,4 +238,13 @@
         mNumberY = h-r.bottom-((dh-r.top-th-r.bottom)/2);
         mNumberBackground.setBounds(w-dw, h-dh, w, h);
     }
+
+    private void setContentDescription(Notification notification) {
+        if (notification != null) {
+            CharSequence tickerText = notification.tickerText;
+            if (!TextUtils.isEmpty(tickerText)) {
+                setContentDescription(tickerText);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index e1d17a8..f6aa159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -33,7 +33,8 @@
 
     private int mIconSize;
     private StatusBarIconView mMoreView;
-    private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0);
+    private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0, 0,
+            null);
 
     public IconMerger(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -41,7 +42,7 @@
         mIconSize = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size);
 
-        mMoreView = new StatusBarIconView(context, "more");
+        mMoreView = new StatusBarIconView(context, "more", null);
         mMoreView.set(mMoreIcon);
         addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b50fd81..21b774c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -82,7 +82,9 @@
 import com.android.systemui.statusbar.StatusBar;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.policy.DateView;
-
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
 
 public class PhoneStatusBar extends StatusBar {
     static final String TAG = "PhoneStatusBar";
@@ -107,6 +109,11 @@
 
     PhoneStatusBarPolicy mIconPolicy;
 
+    // These are no longer handled by the policy, because we need custom strategies for them
+    BatteryController mBatteryController;
+    LocationController mLocationController;
+    NetworkController mNetworkController;
+    
     int mIconSize;
     Display mDisplay;
 
@@ -306,6 +313,32 @@
         setAreThereNotifications();
         mDateView.setVisibility(View.INVISIBLE);
 
+        // Other icons
+        mLocationController = new LocationController(mContext); // will post a notification
+        mBatteryController = new BatteryController(mContext);
+        mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
+        mNetworkController = new NetworkController(mContext);
+        final ImageView comboRSSI = 
+                (ImageView)sb.findViewById(R.id.network_signal);
+        if (comboRSSI != null) {
+            mNetworkController.addCombinedSignalIconView(comboRSSI);
+        }
+        final ImageView mobileRSSI = 
+                (ImageView)sb.findViewById(R.id.mobile_signal);
+        if (mobileRSSI != null) {
+            mNetworkController.addPhoneSignalIconView(mobileRSSI);
+        }
+        final ImageView wifiRSSI = 
+                (ImageView)sb.findViewById(R.id.wifi_signal);
+        if (wifiRSSI != null) {
+            mNetworkController.addWifiIconView(wifiRSSI);
+        }
+        mNetworkController.addDataTypeIconView(
+                (ImageView)sb.findViewById(R.id.network_type));
+        mNetworkController.addDataDirectionOverlayIconView(
+                (ImageView)sb.findViewById(R.id.network_direction));
+        mNetworkController.setStackedMode(true);
+
         // Recents Panel
         updateRecentsPanel();
 
@@ -472,7 +505,7 @@
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
         if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
                 + " icon=" + icon);
-        StatusBarIconView view = new StatusBarIconView(mContext, slot);
+        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
         view.set(icon);
         mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
     }
@@ -565,27 +598,33 @@
 
         final RemoteViews contentView = notification.notification.contentView;
 
-        if (false) {
+        if (DEBUG) {
             Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " expanded=" + oldEntry.expanded
-                    + " contentView=" + oldContentView);
+                    + " contentView=" + oldContentView
+                    + " rowParent=" + oldEntry.row.getParent());
             Slog.d(TAG, "new notification: when=" + notification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " contentView=" + contentView);
         }
 
+
         // Can we just reapply the RemoteViews in place?  If when didn't change, the order
         // didn't change.
-        if (notification.notification.when == oldNotification.notification.when
-                && notification.isOngoing() == oldNotification.isOngoing()
-                && oldEntry.expanded != null
+        boolean contentsUnchanged = oldEntry.expanded != null
                 && contentView != null && oldContentView != null
                 && contentView.getPackage() != null
                 && oldContentView.getPackage() != null
                 && oldContentView.getPackage().equals(contentView.getPackage())
-                && oldContentView.getLayoutId() == contentView.getLayoutId()) {
-            if (SPEW) Slog.d(TAG, "reusing notification");
+                && oldContentView.getLayoutId() == contentView.getLayoutId();
+        ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
+        boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
+                && notification.priority == oldNotification.priority;
+                // priority now encompasses isOngoing()
+        boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
+        if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
+            if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
             try {
                 // Reapply the RemoteViews
@@ -601,11 +640,19 @@
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                         notification.notification.icon, notification.notification.iconLevel,
-                        notification.notification.number);
+                        notification.notification.number, notification.notification.tickerText);
                 if (!oldEntry.icon.set(ic)) {
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
                 }
+                // Update the large icon
+                if (notification.notification.largeIcon != null) {
+                    oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
+                } else {
+                    oldEntry.largeIcon.getLayoutParams().width = 0;
+                    oldEntry.largeIcon.setVisibility(View.INVISIBLE);
+                }
+
             }
             catch (RuntimeException e) {
                 // It failed to add cleanly.  Log, and remove the view from the panel.
@@ -759,9 +806,11 @@
         final View expanded = views[2];
         // Construct the icon.
         final StatusBarIconView iconView = new StatusBarIconView(mContext,
-                notification.pkg + "/0x" + Integer.toHexString(notification.id));
+                notification.pkg + "/0x" + Integer.toHexString(notification.id),
+                notification.notification);
         final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon,
-                    notification.notification.iconLevel, notification.notification.number);
+                    notification.notification.iconLevel, notification.notification.number,
+                    notification.notification.tickerText);
         if (!iconView.set(ic)) {
             handleNotificationError(key, notification, "Coulding create icon: " + ic);
             return null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index dedbe5d..322a8c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -18,25 +18,17 @@
 
 import android.app.StatusBarManager;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothPbap;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
@@ -44,26 +36,13 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
-import android.text.format.DateFormat;
-import android.text.style.CharacterStyle;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.StyleSpan;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
 import android.util.Slog;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
 
-import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.telephony.cdma.TtyIntent;
 import com.android.server.am.BatteryStatsService;
-
 import com.android.systemui.R;
 
 /**
@@ -88,221 +67,14 @@
     private final Context mContext;
     private final StatusBarManager mService;
     private final Handler mHandler = new Handler();
-    private final IBatteryStats mBatteryStats;
 
     // storage
     private StorageManager mStorageManager;
 
-    // phone
-    private TelephonyManager mPhone;
-    private int mPhoneSignalIconId;
-
-    //***** Signal strength icons
-    //GSM/UMTS
-    private static final int[][] sSignalImages = {
-        { R.drawable.stat_sys_signal_0,
-          R.drawable.stat_sys_signal_1,
-          R.drawable.stat_sys_signal_2,
-          R.drawable.stat_sys_signal_3,
-          R.drawable.stat_sys_signal_4 },
-        { R.drawable.stat_sys_signal_0_fully,
-          R.drawable.stat_sys_signal_1_fully,
-          R.drawable.stat_sys_signal_2_fully,
-          R.drawable.stat_sys_signal_3_fully,
-          R.drawable.stat_sys_signal_4_fully }
-    };
-    private static final int[][] sSignalImages_r = {
-        { R.drawable.stat_sys_r_signal_0,
-          R.drawable.stat_sys_r_signal_1,
-          R.drawable.stat_sys_r_signal_2,
-          R.drawable.stat_sys_r_signal_3,
-          R.drawable.stat_sys_r_signal_4 },
-        { R.drawable.stat_sys_r_signal_0_fully,
-          R.drawable.stat_sys_r_signal_1_fully,
-          R.drawable.stat_sys_r_signal_2_fully,
-          R.drawable.stat_sys_r_signal_3_fully,
-          R.drawable.stat_sys_r_signal_4_fully }
-    };
-    private static final int[] sRoamingIndicatorImages_cdma = new int[] {
-        R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
-        // 1 is Standard Roaming Indicator OFF
-        // TODO T: image never used, remove and put 0 instead?
-        R.drawable.stat_sys_roaming_cdma_0,
-
-        // 2 is Standard Roaming Indicator FLASHING
-        // TODO T: image never used, remove and put 0 instead?
-        R.drawable.stat_sys_roaming_cdma_0,
-
-        // 3-12 Standard ERI
-        R.drawable.stat_sys_roaming_cdma_0, //3
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-
-        // 13-63 Reserved for Standard ERI
-        R.drawable.stat_sys_roaming_cdma_0, //13
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-
-        // 64-127 Reserved for Non Standard (Operator Specific) ERI
-        R.drawable.stat_sys_roaming_cdma_0, //64
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0,
-        R.drawable.stat_sys_roaming_cdma_0 //83
-
-        // 128-255 Reserved
-    };
-
-    //***** Data connection icons
-    private int[] mDataIconList = sDataNetType_g[0];
-    //GSM/UMTS
-    private static final int[][] sDataNetType_g = {
-            { R.drawable.stat_sys_data_connected_g,
-              R.drawable.stat_sys_data_in_g,
-              R.drawable.stat_sys_data_out_g,
-              R.drawable.stat_sys_data_inandout_g },
-            { R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_in_g,
-              R.drawable.stat_sys_data_fully_out_g,
-              R.drawable.stat_sys_data_fully_inandout_g }
-        };
-    private static final int[][] sDataNetType_3g = {
-            { R.drawable.stat_sys_data_connected_3g,
-              R.drawable.stat_sys_data_in_3g,
-              R.drawable.stat_sys_data_out_3g,
-              R.drawable.stat_sys_data_inandout_3g },
-            { R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_in_3g,
-              R.drawable.stat_sys_data_fully_out_3g,
-              R.drawable.stat_sys_data_fully_inandout_3g }
-        };
-    private static final int[][] sDataNetType_4g = {
-            { R.drawable.stat_sys_data_connected_4g,
-              R.drawable.stat_sys_data_in_4g,
-              R.drawable.stat_sys_data_out_4g,
-              R.drawable.stat_sys_data_inandout_4g },
-            { R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_in_4g,
-              R.drawable.stat_sys_data_fully_out_4g,
-              R.drawable.stat_sys_data_fully_inandout_4g }
-        };
-    private static final int[][] sDataNetType_e = {
-            { R.drawable.stat_sys_data_connected_e,
-              R.drawable.stat_sys_data_in_e,
-              R.drawable.stat_sys_data_out_e,
-              R.drawable.stat_sys_data_inandout_e },
-            { R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_in_e,
-              R.drawable.stat_sys_data_fully_out_e,
-              R.drawable.stat_sys_data_fully_inandout_e }
-        };
-    //3.5G
-    private static final int[][] sDataNetType_h = {
-            { R.drawable.stat_sys_data_connected_h,
-              R.drawable.stat_sys_data_in_h,
-              R.drawable.stat_sys_data_out_h,
-              R.drawable.stat_sys_data_inandout_h },
-            { R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_in_h,
-              R.drawable.stat_sys_data_fully_out_h,
-              R.drawable.stat_sys_data_fully_inandout_h }
-    };
-
-    //CDMA
-    // Use 3G icons for EVDO data and 1x icons for 1XRTT data
-    private static final int[][] sDataNetType_1x = {
-            { R.drawable.stat_sys_data_connected_1x,
-              R.drawable.stat_sys_data_in_1x,
-              R.drawable.stat_sys_data_out_1x,
-              R.drawable.stat_sys_data_inandout_1x },
-            { R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_in_1x,
-              R.drawable.stat_sys_data_fully_out_1x,
-              R.drawable.stat_sys_data_fully_inandout_1x }
-            };
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
     IccCard.State mSimState = IccCard.State.READY;
-    int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
-    int mDataState = TelephonyManager.DATA_DISCONNECTED;
-    int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
-    ServiceState mServiceState;
-    SignalStrength mSignalStrength;
-
-    // data connection
-    private boolean mDataIconVisible;
-    private boolean mHspaDataDistinguishable;
 
     // ringer volume
     private boolean mVolumeVisible;
@@ -338,10 +110,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
-                updateBattery(intent);
-            }
-            else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
+            if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
                 updateAlarm(intent);
             }
             else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
@@ -351,15 +120,6 @@
                     action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                 updateBluetooth(intent);
             }
-            else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
-                    action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
-                    action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
-                updateWifi(intent);
-            }
-            else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) ||
-                    action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) {
-                updateGps(intent);
-            }
             else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
                     action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
                 updateVolume();
@@ -370,61 +130,28 @@
             else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
                 updateTTY(intent);
             }
-            else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
-                     action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
-                // TODO - stop using other means to get wifi/mobile info
-                updateConnectivity(intent);
-            }
         }
     };
 
     public PhoneStatusBarPolicy(Context context) {
         mContext = context;
         mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
-        mSignalStrength = new SignalStrength();
-        mBatteryStats = BatteryStatsService.getService();
 
         // storage
         mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
         mStorageManager.registerListener(
                 new com.android.systemui.usb.StorageNotification(context));
 
-        // battery
-        mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0);
-
-        // phone_signal
-        mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
-        mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
-
-        // register for phone state notifications.
-        ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
-                .listen(mPhoneStateListener,
-                          PhoneStateListener.LISTEN_SERVICE_STATE
-                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                        | PhoneStateListener.LISTEN_CALL_STATE
-                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
-
-        // data_connection
-        mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0);
-        mService.setIconVisibility("data_connection", false);
-
-        // wifi
-        mService.setIcon("wifi", sWifiSignalImages[0][0], 0);
-        mService.setIconVisibility("wifi", false);
-        // wifi will get updated by the sticky intents
-
         // TTY status
-        mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0);
+        mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
         mService.setIconVisibility("tty", false);
 
         // Cdma Roaming Indicator, ERI
-        mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0);
+        mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
         mService.setIconVisibility("cdma_eri", false);
 
         // bluetooth status
-        mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0);
+        mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0, null);
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             mBluetoothEnabled = adapter.isEnabled();
@@ -433,54 +160,35 @@
         }
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
 
-        // Gps status
-        mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0);
-        mService.setIconVisibility("gps", false);
-
         // Alarm clock
-        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0);
+        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null);
         mService.setIconVisibility("alarm_clock", false);
 
         // Sync state
-        mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0, 0);
-        mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error, 0);
+        mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0,
+                0, null);
+        mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error,
+                0, null);
         mService.setIconVisibility("sync_active", false);
         mService.setIconVisibility("sync_failing", false);
 
         // volume
-        mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0);
+        mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
         mService.setIconVisibility("volume", false);
         updateVolume();
 
         IntentFilter filter = new IntentFilter();
 
         // Register for Intent broadcasts for...
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Intent.ACTION_ALARM_CHANGED);
         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
-        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
-        filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
-        filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
-        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-        filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
-
-        // load config to determine if to distinguish Hspa data icon
-        try {
-            mHspaDataDistinguishable = mContext.getResources().getBoolean(
-                    R.bool.config_hspa_data_distinguishable);
-        } catch (Exception e) {
-            mHspaDataDistinguishable = false;
-        }
     }
 
     private final void updateAlarm(Intent intent) {
@@ -496,90 +204,6 @@
         //mService.setIconVisibility("sync_failing", isFailing && !isActive);
     }
 
-    private final void updateBattery(Intent intent) {
-        final int id = intent.getIntExtra("icon-small", 0);
-        int level = intent.getIntExtra("level", 0);
-        mService.setIcon("battery", id, level);
-    }
-
-    private void updateConnectivity(Intent intent) {
-        NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
-                ConnectivityManager.EXTRA_NETWORK_INFO));
-        int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
-
-        int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
-
-        switch (info.getType()) {
-        case ConnectivityManager.TYPE_MOBILE:
-            mInetCondition = inetCondition;
-            updateDataNetType(info.getSubtype());
-            updateDataIcon();
-            updateSignalStrength(); // apply any change in connectionStatus
-            break;
-        case ConnectivityManager.TYPE_WIFI:
-            mInetCondition = inetCondition;
-            if (info.isConnected()) {
-                mIsWifiConnected = true;
-                int iconId;
-                if (mLastWifiSignalLevel == -1) {
-                    iconId = sWifiSignalImages[mInetCondition][0];
-                } else {
-                    iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel];
-                }
-                mService.setIcon("wifi", iconId, 0);
-                // Show the icon since wi-fi is connected
-                mService.setIconVisibility("wifi", true);
-            } else {
-                mLastWifiSignalLevel = -1;
-                mIsWifiConnected = false;
-                int iconId = sWifiSignalImages[0][0];
-
-                mService.setIcon("wifi", iconId, 0);
-                // Hide the icon since we're not connected
-                mService.setIconVisibility("wifi", false);
-            }
-            updateSignalStrength(); // apply any change in mInetCondition
-            break;
-        }
-    }
-
-    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-        @Override
-        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            mSignalStrength = signalStrength;
-            updateSignalStrength();
-        }
-
-        @Override
-        public void onServiceStateChanged(ServiceState state) {
-            mServiceState = state;
-            updateSignalStrength();
-            updateCdmaRoamingIcon(state);
-            updateDataIcon();
-        }
-
-        @Override
-        public void onCallStateChanged(int state, String incomingNumber) {
-            // In cdma, if a voice call is made, RSSI should switch to 1x.
-            if (isCdma()) {
-                updateSignalStrength();
-            }
-        }
-
-        @Override
-        public void onDataConnectionStateChanged(int state, int networkType) {
-            mDataState = state;
-            updateDataNetType(networkType);
-            updateDataIcon();
-        }
-
-        @Override
-        public void onDataActivity(int direction) {
-            mDataActivity = direction;
-            updateDataIcon();
-        }
-    };
-
     private final void updateSimState(Intent intent) {
         String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
         if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
@@ -602,162 +226,6 @@
         } else {
             mSimState = IccCard.State.UNKNOWN;
         }
-        updateDataIcon();
-    }
-
-    private boolean isCdma() {
-        return (mSignalStrength != null) && !mSignalStrength.isGsm();
-    }
-
-    private boolean hasService() {
-        if (mServiceState != null) {
-            switch (mServiceState.getState()) {
-                case ServiceState.STATE_OUT_OF_SERVICE:
-                case ServiceState.STATE_POWER_OFF:
-                    return false;
-                default:
-                    return true;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    private final void updateSignalStrength() {
-        int[] iconList;
-
-        // Display signal strength while in "emergency calls only" mode
-        if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) {
-            //Slog.d(TAG, "updateSignalStrength: no service");
-            if (Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
-                mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode;
-            } else {
-                mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
-            }
-            mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
-            return;
-        }
-
-        if (!isCdma()) {
-            // Though mPhone is a Manager, this call is not an IPC
-            if (mPhone.isNetworkRoaming()) {
-                iconList = sSignalImages_r[mInetCondition];
-            } else {
-                iconList = sSignalImages[mInetCondition];
-            }
-        } else {
-            iconList = sSignalImages[mInetCondition];
-        }
-        mPhoneSignalIconId = iconList[mSignalStrength.getLevel()];
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
-    }
-
-    private final void updateDataNetType(int net) {
-        switch (net) {
-        case TelephonyManager.NETWORK_TYPE_EDGE:
-            mDataIconList = sDataNetType_e[mInetCondition];
-            break;
-        case TelephonyManager.NETWORK_TYPE_UMTS:
-            mDataIconList = sDataNetType_3g[mInetCondition];
-            break;
-        case TelephonyManager.NETWORK_TYPE_HSDPA:
-        case TelephonyManager.NETWORK_TYPE_HSUPA:
-        case TelephonyManager.NETWORK_TYPE_HSPA:
-            if (mHspaDataDistinguishable) {
-                mDataIconList = sDataNetType_h[mInetCondition];
-            } else {
-                mDataIconList = sDataNetType_3g[mInetCondition];
-            }
-            break;
-        case TelephonyManager.NETWORK_TYPE_CDMA:
-            // display 1xRTT for IS95A/B
-            mDataIconList = sDataNetType_1x[mInetCondition];
-            break;
-        case TelephonyManager.NETWORK_TYPE_1xRTT:
-            mDataIconList = sDataNetType_1x[mInetCondition];
-            break;
-        case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
-        case TelephonyManager.NETWORK_TYPE_EVDO_A:
-        case TelephonyManager.NETWORK_TYPE_EVDO_B:
-        case TelephonyManager.NETWORK_TYPE_EHRPD:
-            mDataIconList = sDataNetType_3g[mInetCondition];
-            break;
-        case TelephonyManager.NETWORK_TYPE_LTE:
-            mDataIconList = sDataNetType_4g[mInetCondition];
-            break;
-        default:
-            mDataIconList = sDataNetType_g[mInetCondition];
-        break;
-        }
-    }
-
-    private final void updateDataIcon() {
-        int iconId;
-        boolean visible = true;
-
-        if (!isCdma()) {
-            // GSM case, we have to check also the sim state
-            if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
-                if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
-                    switch (mDataActivity) {
-                        case TelephonyManager.DATA_ACTIVITY_IN:
-                            iconId = mDataIconList[1];
-                            break;
-                        case TelephonyManager.DATA_ACTIVITY_OUT:
-                            iconId = mDataIconList[2];
-                            break;
-                        case TelephonyManager.DATA_ACTIVITY_INOUT:
-                            iconId = mDataIconList[3];
-                            break;
-                        default:
-                            iconId = mDataIconList[0];
-                            break;
-                    }
-                    mService.setIcon("data_connection", iconId, 0);
-                } else {
-                    visible = false;
-                }
-            } else {
-                iconId = R.drawable.stat_sys_no_sim;
-                mService.setIcon("data_connection", iconId, 0);
-            }
-        } else {
-            // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
-            if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
-                switch (mDataActivity) {
-                    case TelephonyManager.DATA_ACTIVITY_IN:
-                        iconId = mDataIconList[1];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_OUT:
-                        iconId = mDataIconList[2];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_INOUT:
-                        iconId = mDataIconList[3];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_DORMANT:
-                    default:
-                        iconId = mDataIconList[0];
-                        break;
-                }
-                mService.setIcon("data_connection", iconId, 0);
-            } else {
-                visible = false;
-            }
-        }
-
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-
-        if (mDataIconVisible != visible) {
-            mService.setIconVisibility("data_connection", visible);
-            mDataIconVisible = visible;
-        }
     }
 
     private final void updateVolume() {
@@ -765,12 +233,19 @@
         final int ringerMode = audioManager.getRingerMode();
         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
                 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
-        final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
-                ? R.drawable.stat_sys_ringer_vibrate
-                : R.drawable.stat_sys_ringer_silent;
+
+        final int iconId;
+        String contentDescription = null;
+        if (audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
+            iconId = R.drawable.stat_sys_ringer_vibrate;
+            contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
+        } else {
+            iconId =  R.drawable.stat_sys_ringer_silent;
+            contentDescription = mContext.getString(R.string.accessibility_ringer_silent);
+        }
 
         if (visible) {
-            mService.setIcon("volume", iconId, 0);
+            mService.setIcon("volume", iconId, 0, contentDescription);
         }
         if (visible != mVolumeVisible) {
             mService.setIconVisibility("volume", visible);
@@ -780,6 +255,7 @@
 
     private final void updateBluetooth(Intent intent) {
         int iconId = R.drawable.stat_sys_data_bluetooth;
+        String contentDescription = null;
         String action = intent.getAction();
         if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
@@ -789,68 +265,19 @@
                 BluetoothAdapter.STATE_DISCONNECTED);
             if (state == BluetoothAdapter.STATE_CONNECTED) {
                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
+                contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
+            } else {
+                contentDescription = mContext.getString(
+                        R.string.accessibility_bluetooth_disconnected);
             }
         } else {
             return;
         }
 
-        mService.setIcon("bluetooth", iconId, 0);
+        mService.setIcon("bluetooth", iconId, 0, contentDescription);
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
     }
 
-    private final void updateWifi(Intent intent) {
-        final String action = intent.getAction();
-        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-
-            final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                    WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
-            if (!enabled) {
-                // If disabled, hide the icon. (We show icon when connected.)
-                mService.setIconVisibility("wifi", false);
-            }
-
-        } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
-            final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
-                                                           false);
-            if (!enabled) {
-                mService.setIconVisibility("wifi", false);
-            }
-        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
-            int iconId;
-            final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
-            int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
-                                                                  sWifiSignalImages[0].length);
-            if (newSignalLevel != mLastWifiSignalLevel) {
-                mLastWifiSignalLevel = newSignalLevel;
-                if (mIsWifiConnected) {
-                    iconId = sWifiSignalImages[mInetCondition][newSignalLevel];
-                } else {
-                    iconId = sWifiTemporarilyNotConnectedImage;
-                }
-                mService.setIcon("wifi", iconId, 0);
-            }
-        }
-    }
-
-    private final void updateGps(Intent intent) {
-        final String action = intent.getAction();
-        final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
-
-        if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
-            // GPS is getting fixes
-            mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0);
-            mService.setIconVisibility("gps", true);
-        } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
-            // GPS is off
-            mService.setIconVisibility("gps", false);
-        } else {
-            // GPS is on, but not receiving fixes
-            mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0);
-            mService.setIconVisibility("gps", true);
-        }
-    }
-
     private final void updateTTY(Intent intent) {
         final String action = intent.getAction();
         final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
@@ -860,7 +287,8 @@
         if (enabled) {
             // TTY is on
             if (false) Slog.v(TAG, "updateTTY: set TTY on");
-            mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0);
+            mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0,
+                    mContext.getString(R.string.accessibility_tty_enabled));
             mService.setIconVisibility("tty", true);
         } else {
             // TTY is off
@@ -868,49 +296,4 @@
             mService.setIconVisibility("tty", false);
         }
     }
-
-    private final void updateCdmaRoamingIcon(ServiceState state) {
-        if (!hasService()) {
-            mService.setIconVisibility("cdma_eri", false);
-            return;
-        }
-
-        if (!isCdma()) {
-            mService.setIconVisibility("cdma_eri", false);
-            return;
-        }
-
-        int[] iconList = sRoamingIndicatorImages_cdma;
-        int iconIndex = state.getCdmaEriIconIndex();
-        int iconMode = state.getCdmaEriIconMode();
-
-        if (iconIndex == -1) {
-            Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
-            return;
-        }
-
-        if (iconMode == -1) {
-            Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
-            return;
-        }
-
-        if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
-            if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
-            mService.setIconVisibility("cdma_eri", false);
-            return;
-        }
-
-        switch (iconMode) {
-            case EriInfo.ROAMING_ICON_MODE_NORMAL:
-                mService.setIcon("cdma_eri", iconList[iconIndex], 0);
-                mService.setIconVisibility("cdma_eri", true);
-                break;
-            case EriInfo.ROAMING_ICON_MODE_FLASH:
-                mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0);
-                mService.setIconVisibility("cdma_eri", true);
-                break;
-
-        }
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 84c524a..c2390e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -26,6 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
@@ -203,5 +204,19 @@
         return mService.interceptTouchEvent(event)
                 ? true : super.onInterceptTouchEvent(event);
     }
-}
 
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // The status bar is very small so augment the view that the user is touching
+            // with the content of the status bar a whole. This way an accessibility service
+            // may announce the current item as well as the entire content if appropriate.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index 8ee12de..e76fe51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -183,7 +183,8 @@
         }
 
         final Drawable icon = StatusBarIconView.getIcon(mContext,
-                new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0));
+                new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0,
+                        n.notification.tickerText));
         final Segment newSegment = new Segment(n, icon, n.notification.tickerText);
 
         // If there's already a notification schedule for this package and id, remove it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
new file mode 100644
index 0000000..13fb03e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -0,0 +1,37 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.R;
+
+/**
+ * Content descriptions for accessibility support.
+ */
+public class AccessibilityContentDescriptions {
+
+    private AccessibilityContentDescriptions() {}
+    
+    static final int[] PHONE_SIGNAL_STRENGTH = {
+        R.string.accessibility_no_phone,
+        R.string.accessibility_phone_one_bar,
+        R.string.accessibility_phone_two_bars,
+        R.string.accessibility_phone_three_bars,
+        R.string.accessibility_phone_signal_full
+    };
+
+    static final int[] DATA_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_data,
+        R.string.accessibility_data_one_bar,
+        R.string.accessibility_data_two_bars,
+        R.string.accessibility_data_three_bars,
+        R.string.accessibility_data_signal_full
+    };
+
+    static final int[] WIFI_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_wifi,
+        R.string.accessibility_wifi_one_bar,
+        R.string.accessibility_wifi_two_bars,
+        R.string.accessibility_wifi_three_bars,
+        R.string.accessibility_wifi_signal_full
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index ae2b6b2..ff418c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -56,18 +56,22 @@
         final String action = intent.getAction();
         if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
             final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+            final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+            final int icon = plugged ? R.drawable.stat_sys_battery_charge 
+                                     : R.drawable.stat_sys_battery;
             int N = mIconViews.size();
             for (int i=0; i<N; i++) {
-                final int icon = intent.getIntExtra(BatteryManager.EXTRA_ICON_SMALL, 0);
                 ImageView v = mIconViews.get(i);
                 v.setImageResource(icon);
                 v.setImageLevel(level);
+                v.setContentDescription(mContext.getString(R.string.accessibility_battery_level,
+                        level));
             }
             N = mLabelViews.size();
             for (int i=0; i<N; i++) {
-                //final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
                 TextView v = mLabelViews.get(i);
-                v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, level));
+                v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format,
+                        level));
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
index 0525054..c6f416f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -19,12 +19,10 @@
 import java.util.ArrayList;
 
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.util.Slog;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -54,26 +52,24 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        String action = intent.getAction();
-        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
-            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
-            mEnabled = state == BluetoothAdapter.STATE_ON;
-        } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
-            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
+        int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
                 BluetoothAdapter.STATE_DISCONNECTED);
-            if (state == BluetoothAdapter.STATE_CONNECTED) {
-                mIconId = R.drawable.stat_sys_data_bluetooth_connected;
-            } else {
-                mIconId = R.drawable.stat_sys_data_bluetooth;
-            }
-        }
+        int contentDescriptionResId = 0;
 
+        if (state == BluetoothAdapter.STATE_CONNECTED) {
+            mIconId = R.drawable.stat_sys_data_bluetooth_connected;
+            contentDescriptionResId = R.string.accessibility_bluetooth_connected;
+        } else {
+            mIconId = R.drawable.stat_sys_data_bluetooth;
+            contentDescriptionResId = R.string.accessibility_bluetooth_disconnected;
+        }
 
         int N = mIconViews.size();
         for (int i=0; i<N; i++) {
             ImageView v = mIconViews.get(i);
             v.setImageResource(mIconId);
             v.setVisibility(mEnabled ? View.VISIBLE : View.GONE);
+            v.setContentDescription(mContext.getString(contentDescriptionResId));
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 3175a99..f32c602 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -28,14 +28,11 @@
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
@@ -87,6 +84,11 @@
     int mDataTypeIconId;
     boolean mDataActive;
 
+    String mContentDescriptionPhoneSignal;
+    String mContentDescriptionWifi;
+    String mContentDescriptionCombinedSignal;
+    String mContentDescriptionDataType;
+
     // wifi
     final WifiManager mWifiManager;
     AsyncChannel mWifiChannel;
@@ -125,6 +127,8 @@
     int mLastDataTypeIconId = -1;
     String mLastLabel = "";
 
+    boolean mDataAndWifiStacked = false;
+
     // yuck -- stop doing this here and put it in the framework
     IBatteryStats mBatteryStats;
 
@@ -209,6 +213,10 @@
         mLabelViews.add(v);
     }
 
+    public void setStackedMode(boolean stacked) {
+        mDataAndWifiStacked = true;
+    }
+
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
@@ -366,6 +374,8 @@
             if (mSignalStrength == null) {
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
                 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null
+                mContentDescriptionPhoneSignal = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
             } else {
                 int iconLevel;
                 int[] iconList;
@@ -385,6 +395,9 @@
                     }
                 }
                 mPhoneSignalIconId = iconList[iconLevel];
+                mContentDescriptionPhoneSignal = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
+
                 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
             }
         }
@@ -395,14 +408,20 @@
             case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = 0;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_gprs);
                 break;
             case TelephonyManager.NETWORK_TYPE_EDGE:
                 mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_edge;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_edge);
                 break;
             case TelephonyManager.NETWORK_TYPE_UMTS:
                 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_3g);
                 break;
             case TelephonyManager.NETWORK_TYPE_HSDPA:
             case TelephonyManager.NETWORK_TYPE_HSUPA:
@@ -410,19 +429,27 @@
                 if (mHspaDataDistinguishable) {
                     mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa;
+                    mContentDescriptionDataType = mContext.getString(
+                            R.string.accessibility_data_connection_3_5g);
                 } else {
                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                    mContentDescriptionDataType = mContext.getString(
+                            R.string.accessibility_data_connection_3g);
                 }
                 break;
             case TelephonyManager.NETWORK_TYPE_CDMA:
                 // display 1xRTT for IS95A/B
                 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_1x;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_cdma);
                 break;
             case TelephonyManager.NETWORK_TYPE_1xRTT:
                 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_1x;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_cdma);
                 break;
             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
             case TelephonyManager.NETWORK_TYPE_EVDO_A:
@@ -430,14 +457,20 @@
             case TelephonyManager.NETWORK_TYPE_EHRPD:
                 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_3g);
                 break;
             case TelephonyManager.NETWORK_TYPE_LTE:
                 mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_4g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_4g);
                 break;
             default:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_gprs);
                 break;
         }
         if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) {
@@ -618,8 +651,15 @@
     private void updateWifiIcons() {
         if (mWifiConnected) {
             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
+            mContentDescriptionWifi = mContext.getString(
+                    AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
         } else {
-            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
+            if (mDataAndWifiStacked) {
+                mWifiIconId = 0;
+            } else {
+                mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
+            }
+            mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
         }
     }
 
@@ -704,6 +744,7 @@
                 }
             }
             combinedSignalIconId = mWifiIconId;
+            mContentDescriptionCombinedSignal = mContentDescriptionWifi;
             dataTypeIconId = 0;
         } else if (mDataConnected) {
             label = mNetworkName;
@@ -723,22 +764,29 @@
                     break;
             }
             combinedSignalIconId = mDataSignalIconId;
+            mContentDescriptionCombinedSignal = mContentDescriptionDataType;
             dataTypeIconId = mDataTypeIconId;
         } else if (mBluetoothTethered) {
             label = mContext.getString(R.string.bluetooth_tethered);
             combinedSignalIconId = mBluetoothTetherIconId;
+            mContentDescriptionCombinedSignal = mContext.getString(
+                    R.string.accessibility_bluetooth_tether);
             dataTypeIconId = 0;
         } else if (mAirplaneMode &&
                 (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
             // Only display the flight-mode icon if not in "emergency calls only" mode.
             label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             combinedSignalIconId = R.drawable.stat_sys_signal_flightmode;
+            mContentDescriptionCombinedSignal = mContext.getString(
+                    R.string.accessibility_airplane_mode);
             dataTypeIconId = 0;
         } else {
             label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             // On devices without mobile radios, we want to show the wifi icon
             combinedSignalIconId =
                 hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId;
+            mContentDescriptionCombinedSignal = hasMobileDataFeature()
+                ? mContentDescriptionDataType : mContentDescriptionWifi;
             dataTypeIconId = 0;
         }
 
@@ -764,6 +812,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mPhoneSignalIconViews.get(i);
                 v.setImageResource(mPhoneSignalIconId);
+                v.setContentDescription(mContentDescriptionPhoneSignal);
             }
         }
 
@@ -774,6 +823,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mDataDirectionIconViews.get(i);
                 v.setImageResource(mDataDirectionIconId);
+                v.setContentDescription(mContentDescriptionDataType);
             }
         }
 
@@ -783,7 +833,13 @@
             N = mWifiIconViews.size();
             for (int i=0; i<N; i++) {
                 final ImageView v = mWifiIconViews.get(i);
-                v.setImageResource(mWifiIconId);
+                if (mWifiIconId == 0) {
+                    v.setVisibility(View.INVISIBLE);
+                } else {
+                    v.setVisibility(View.VISIBLE);
+                    v.setImageResource(mWifiIconId);
+                    v.setContentDescription(mContentDescriptionWifi);
+                }
             }
         }
 
@@ -794,6 +850,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mCombinedSignalIconViews.get(i);
                 v.setImageResource(combinedSignalIconId);
+                v.setContentDescription(mContentDescriptionCombinedSignal);
             }
         }
 
@@ -808,6 +865,7 @@
                 } else {
                     v.setVisibility(View.VISIBLE);
                     v.setImageResource(dataTypeIconId);
+                    v.setContentDescription(mContentDescriptionDataType);
                 }
             }
         }
@@ -826,6 +884,7 @@
                 } else {
                     v.setVisibility(View.VISIBLE);
                     v.setImageResource(dataDirectionOverlayIconId);
+                    v.setContentDescription(mContentDescriptionDataType);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 981fb24..90234c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -21,47 +21,33 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
-import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Slog;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
 
 import java.util.HashSet;
 
-import com.android.systemui.R;
-
-public class NotificationRowLayout extends ViewGroup {
+public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Callback {
     private static final String TAG = "NotificationRowLayout";
     private static final boolean DEBUG = false;
     private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
 
     private static final boolean ANIMATE_LAYOUT = true;
 
-    private static final boolean CLEAR_IF_SWIPED_FAR_ENOUGH = true;
-    
-    private static final boolean CONSTRAIN_SWIPE_ON_PERMANENT = true;
-
     private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250;
     private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN;
-    private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250;
-
-    private static final float SWIPE_ESCAPE_VELOCITY = 1500f;
-    private static final float SWIPE_ANIM_VELOCITY_MIN = 1000f;
 
     Rect mTmpRect = new Rect();
     int mNumRows = 0;
@@ -71,10 +57,7 @@
     HashSet<View> mAppearingViews = new HashSet<View>();
     HashSet<View> mDisappearingViews = new HashSet<View>();
 
-    VelocityTracker mVT;
-    float mInitialTouchX, mInitialTouchY;
-    View mSlidingChild = null;
-    float mLiftoffVelocity;
+    private SwipeHelper mSwipeHelper;
 
     public NotificationRowLayout(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -83,8 +66,6 @@
     public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        mVT = VelocityTracker.obtain();
-
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationRowLayout,
                 defStyle, 0);
         mRowHeight = a.getDimensionPixelSize(R.styleable.NotificationRowLayout_rowHeight, 0);
@@ -107,112 +88,71 @@
             setBackgroundColor(0x80FF8000);
         }
 
+        float densityScale = getResources().getDisplayMetrics().density;
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
     }
 
-    // Swipey code
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-//        if (DEBUG) Slog.d(TAG, "intercepting touch event: " + ev);
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVT.clear();
-                mVT.addMovement(ev);
-                mInitialTouchX = ev.getX();
-                mInitialTouchY = ev.getY();
-                mSlidingChild = null;
-                break;
-            case MotionEvent.ACTION_MOVE:
-                mVT.addMovement(ev);
-                if (mSlidingChild == null) {
-                    if (Math.abs(ev.getX() - mInitialTouchX) > 4) { // slide slop
-
-                        // find the view under the pointer, accounting for GONE views
-                        final int count = getChildCount();
-                        int y = 0;
-                        int childIdx = 0;
-                        for (; childIdx < count; childIdx++) {
-                            mSlidingChild = getChildAt(childIdx);
-                            if (mSlidingChild.getVisibility() == GONE) {
-                                continue;
-                            }
-                            y += mRowHeight;
-                            if (mInitialTouchY < y) break;
-                        }
-
-                        mInitialTouchX -= mSlidingChild.getTranslationX();
-                        mSlidingChild.animate().cancel();
-
-                        if (DEBUG) {
-                            Slog.d(TAG, String.format(
-                                "now sliding child %d: %s (touchY=%.1f, rowHeight=%d, count=%d)",
-                                childIdx, mSlidingChild, mInitialTouchY, mRowHeight, count));
-                        }
-                    }
-                }
-                break;
-        }
-        return mSlidingChild != null;
-    }
-
-    protected boolean canBeCleared(View v) {
-        final View veto = v.findViewById(R.id.veto);
-        return (veto != null && veto.getVisibility() != View.GONE);
-    }
-
-    protected boolean clear(View v) {
-        final View veto = v.findViewById(R.id.veto);
-        if (veto != null && veto.getVisibility() != View.GONE) {
-            veto.performClick();
-            return true;
-        }
-        return false;
+        if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
+        return mSwipeHelper.onInterceptTouchEvent(ev) ||
+            super.onInterceptTouchEvent(ev);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-//        if (DEBUG) Slog.d(TAG, "touch event: " + ev + " sliding: " + mSlidingChild);
-        if (mSlidingChild != null) {
-            switch (action) {
-                case MotionEvent.ACTION_OUTSIDE:
-                case MotionEvent.ACTION_MOVE:
-                    mVT.addMovement(ev);
+        return mSwipeHelper.onTouchEvent(ev) ||
+            super.onTouchEvent(ev);
+    }
 
-                    float delta = (ev.getX() - mInitialTouchX);
-                    if (CONSTRAIN_SWIPE_ON_PERMANENT && !canBeCleared(mSlidingChild)) {
-                        delta = Math.copySign(
-                                    Math.min(Math.abs(delta),
-                                    mSlidingChild.getMeasuredWidth() * 0.2f), delta);
-                    }
-                    mSlidingChild.setTranslationX(delta);
-                    break;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mVT.addMovement(ev);
-                    mVT.computeCurrentVelocity(1000 /* px/sec */);
-                    if (DEBUG) Slog.d(TAG, "exit velocity: " + mVT.getXVelocity());
-                    boolean restore = true;
-                    mLiftoffVelocity = mVT.getXVelocity();
-                    if (Math.abs(mLiftoffVelocity) > SWIPE_ESCAPE_VELOCITY
-                        || (CLEAR_IF_SWIPED_FAR_ENOUGH && 
-                            (mSlidingChild.getTranslationX() * 2) > mSlidingChild.getMeasuredWidth()))
-                    {
+    public boolean canChildBeDismissed(View v) {
+        final View veto = v.findViewById(R.id.veto);
+        return (veto != null && veto.getVisibility() != View.GONE);
+    }
 
-                        // flingadingy
-                        restore = ! clear(mSlidingChild);
-                    }
-                    if (restore) {
-                        // snappity
-                        mSlidingChild.animate().translationX(0)
-                            .setDuration(SNAP_ANIM_LEN)
-                            .start();
-                    }
-                    break;
-            }
-            return true;
+    public void onChildDismissed(View v) {
+        final View veto = v.findViewById(R.id.veto);
+        if (veto != null && veto.getVisibility() != View.GONE) {
+            veto.performClick();
         }
-        return false;
+    }
+
+    public void onBeginDrag(View v) {
+        // We need to prevent the surrounding ScrollView from intercepting us now;
+        // the scroll position will be locked while we swipe
+        requestDisallowInterceptTouchEvent(true);
+    }
+
+    public View getChildAtPosition(MotionEvent ev) {
+        // find the view under the pointer, accounting for GONE views
+        final int count = getChildCount();
+        int y = 0;
+        int touchY = (int) ev.getY();
+        int childIdx = 0;
+        View slidingChild;
+        for (; childIdx < count; childIdx++) {
+            slidingChild = getChildAt(childIdx);
+            if (slidingChild.getVisibility() == GONE) {
+                continue;
+            }
+            y += mRowHeight;
+            if (touchY < y) return slidingChild;
+        }
+        return null;
+    }
+
+    public View getChildContentView(View v) {
+        return v;
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        float densityScale = getResources().getDisplayMetrics().density;
+        mSwipeHelper.setDensityScale(densityScale);
+        float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
     }
 
     //**
@@ -236,6 +176,7 @@
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     mAppearingViews.remove(childF);
+                    requestLayout(); // pick up any final changes in position
                 }
             });
             a.start();
@@ -254,9 +195,10 @@
 
             child.setPivotY(0);
 
-            final float velocity = (mSlidingChild == child) 
-                    ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN)
-                    : SWIPE_ESCAPE_VELOCITY;
+            //final float velocity = (mSlidingChild == child)
+             //       ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN)
+            //        : SWIPE_ESCAPE_VELOCITY;
+            final float velocity = 0f;
             final TimeAnimator zoom = new TimeAnimator();
             zoom.setTimeListener(new TimeAnimator.TimeListener() {
                 @Override
@@ -274,6 +216,7 @@
                     NotificationRowLayout.super.removeView(childF);
                     childF.setAlpha(1f);
                     mDisappearingViews.remove(childF);
+                    requestLayout(); // pick up any final changes in position
                 }
             });
 
@@ -372,7 +315,7 @@
         final int width = right - left;
         final int height = bottom - top;
 
-        //if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
+        if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
 
         final int count = getChildCount();
         int y = 0;
@@ -381,20 +324,22 @@
             if (child.getVisibility() == GONE) {
                 continue;
             }
-//            final int thisRowHeight = (int)(
-//                ((mAppearingViews.contains(child) || mDisappearingViews.contains(child))
-//                        ? child.getScaleY()
-//                        : 1.0f)
-//                * mRowHeight);
             final int thisRowHeight = (int)(child.getAlpha() * mRowHeight);
-//            child.layout(0, y, width, y + thisRowHeight);
-            child.layout(0, y, width, y + mRowHeight);
+            if (DEBUG) {
+                Slog.d(TAG, String.format(
+                            "laying out child #%d: (0, %d, %d, %d) h=%d",
+                            i, y, width, y + thisRowHeight, thisRowHeight));
+            }
+            child.layout(0, y, width, y + thisRowHeight);
             y += thisRowHeight;
         }
+        if (DEBUG) {
+            Slog.d(TAG, "onLayout: final y=" + y);
+        }
     }
 
     public void setForcedHeight(int h) {
-        //if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
+        if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
         if (h != mHeight) {
             mHeight = h;
             requestLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 9093b3e..449ea99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -50,19 +50,6 @@
 
     static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH;
 
-    static final int[][] DATA_SIGNAL_STRENGTH_ACTIVE = {
-        { R.drawable.stat_sys_signal_0,
-          R.drawable.stat_sys_signal_1_flowing,
-          R.drawable.stat_sys_signal_2_flowing,
-          R.drawable.stat_sys_signal_3_flowing,
-          R.drawable.stat_sys_signal_4_flowing },
-        { R.drawable.stat_sys_signal_0_fully,
-          R.drawable.stat_sys_signal_1_fully_flowing,
-          R.drawable.stat_sys_signal_2_fully_flowing,
-          R.drawable.stat_sys_signal_3_fully_flowing,
-          R.drawable.stat_sys_signal_4_fully_flowing }
-    };
-
     //***** Data connection icons
 
     //GSM/UMTS
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
index c62c4ad..8c4ae19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
@@ -22,6 +22,7 @@
 import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Slog;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -90,6 +91,19 @@
         return false;
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     public void setTrigger(View v) {
         mTrigger = v;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
index 7f4c918..3e9a9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
@@ -25,7 +25,7 @@
 import android.content.res.Resources;
 import android.util.DisplayMetrics;
 import android.util.Slog;
-import android.view.View;
+import android.view.Display;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
@@ -41,6 +41,7 @@
     ArrayList<OnBarHeightChangedListener> mListeners = new ArrayList<OnBarHeightChangedListener>();
     WindowManager mWindowManager;
     int mHeight;
+    boolean mPlugged;
 
     public HeightReceiver(Context context) {
         mContext = context;
@@ -71,15 +72,24 @@
     }
 
     private void setPlugged(boolean plugged) {
+        mPlugged = plugged;
+        updateHeight();
+    }
+
+    public void updateHeight() {
         final Resources res = mContext.getResources();
 
         int height = -1;
-        if (plugged) {
+        if (mPlugged) {
             final DisplayMetrics metrics = new DisplayMetrics();
-            mWindowManager.getDefaultDisplay().getRealMetrics(metrics);
-            //Slog.i(TAG, "setPlugged: display metrics=" + metrics);
+            Display display = mWindowManager.getDefaultDisplay();
+            display.getRealMetrics(metrics);
+
+            //Slog.i(TAG, "updateHeight: display metrics=" + metrics);
             final int shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
-            height = shortSide - 720;
+            final int externalShortSide = Math.min(display.getRawExternalWidth(),
+                    display.getRawExternalHeight());
+            height = shortSide - externalShortSide;
         }
 
         final int minHeight
@@ -87,7 +97,7 @@
         if (height < minHeight) {
             height = minHeight;
         }
-        Slog.i(TAG, "Resizing status bar plugged=" + plugged + " height="
+        Slog.i(TAG, "Resizing status bar plugged=" + mPlugged + " height="
                 + height + " old=" + mHeight);
         mHeight = height;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index 339e3f3..1e417ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -30,6 +30,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -160,6 +161,19 @@
         }
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     private void updateHardKeyboardEnabled() {
         if (mHardKeyboardAvailable) {
             final boolean checked = mHardKeyboardSwitch.isChecked();
@@ -222,6 +236,7 @@
             itemSubtitle.setText(imiName);
         }
         subtypeIcon.setImageDrawable(icon);
+        subtypeIcon.setContentDescription(itemTitle.getText());
         final String settingsActivity = imi.getSettingsActivity();
         if (!TextUtils.isEmpty(settingsActivity)) {
             settingsIcon.setOnClickListener(new View.OnClickListener() {
@@ -463,4 +478,5 @@
     public interface OnHardKeyboardEnabledChangeListener {
         public void onHardKeyboardEnabledChange(boolean enabled);
     }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java
new file mode 100644
index 0000000..42bdf3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.LinearLayout;
+
+public class NotificationArea extends LinearLayout {
+
+    public NotificationArea(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // The event is coming from a descendant like battery but append
+            // the content of the entire notification area so accessibility
+            // services can choose how to present the content to the user.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 64a4f16..a316e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -20,27 +20,15 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Slog;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
-import android.widget.TextView;
 
 import com.android.systemui.R;
 
@@ -53,8 +41,7 @@
 
     boolean mShowing;
     int mNotificationCount = 0;
-    View mTitleArea;
-    ModeToggle mModeToggle;
+    NotificationPanelTitle mTitleArea;
     View mSettingsButton;
     View mNotificationButton;
     View mNotificationScroller;
@@ -68,48 +55,6 @@
 
     Choreographer mChoreo = new Choreographer();
 
-    static class ModeToggle extends View {
-        NotificationPanel mPanel;
-        View mTitle;
-        public ModeToggle(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-        public void setPanel(NotificationPanel p) {
-            mPanel = p;
-        }
-        public void setTitleArea(View v) {
-            mTitle = v;
-        }
-        @Override
-        public boolean onTouchEvent(MotionEvent e) {
-            final int x = (int)e.getX();
-            final int y = (int)e.getY();
-            switch (e.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mTitle.setPressed(true);
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    mTitle.setPressed(x >= 0
-                            && x < getWidth()
-                            && y >= 0
-                            && y < getHeight());
-                    break;
-                case MotionEvent.ACTION_CANCEL:
-                    mTitle.setPressed(false);
-                    break;
-                case MotionEvent.ACTION_UP:
-                    if (mTitle.isPressed()) {
-                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                        playSoundEffect(SoundEffectConstants.CLICK);
-                        mPanel.swapPanels();
-                        mTitle.setPressed(false);
-                    }
-                    break;
-            }
-            return true;
-        }
-    }
-
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -126,14 +71,11 @@
 
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
         mContentParent.bringToFront();
-        mTitleArea = findViewById(R.id.title_area);
-        mModeToggle = (ModeToggle) findViewById(R.id.mode_toggle);
-        mModeToggle.setOnClickListener(this);
-        mModeToggle.setPanel(this);
-        mModeToggle.setTitleArea(mTitleArea);
+        mTitleArea = (NotificationPanelTitle) findViewById(R.id.title_area);
+        mTitleArea.setPanel(this);
 
-        mSettingsButton = (ImageView)findViewById(R.id.settings_button);
-        mNotificationButton = (ImageView)findViewById(R.id.notification_button);
+        mSettingsButton = findViewById(R.id.settings_button);
+        mNotificationButton = findViewById(R.id.notification_button);
 
         mNotificationScroller = findViewById(R.id.notification_scroller);
         mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
@@ -185,6 +127,19 @@
         }
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     /*
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
@@ -205,7 +160,7 @@
     */
 
     public void onClick(View v) {
-        if (v == mModeToggle) {
+        if (v == mTitleArea) {
             swapPanels();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
new file mode 100644
index 0000000..689bc36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.RelativeLayout;
+
+public class NotificationPanelTitle extends RelativeLayout implements View.OnClickListener {
+    private NotificationPanel mPanel;
+
+    public NotificationPanelTitle(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setOnClickListener(this);
+    }
+
+    public void setPanel(NotificationPanel p) {
+        mPanel = p;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent e) {
+        switch (e.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                setPressed(true);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                final int x = (int) e.getX();
+                final int y = (int) e.getY();
+                setPressed(x > 0 && x < getWidth() && y > 0 && y < getHeight());
+                break;
+            case MotionEvent.ACTION_UP:
+                if (isPressed()) {
+                    playSoundEffect(SoundEffectConstants.CLICK);
+                    mPanel.swapPanels();
+                    setPressed(false);
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                setPressed(false);
+                break;
+        }
+        return true;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == this) {
+            mPanel.swapPanels();
+        }
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
index 8b68240..ba28306 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
@@ -18,12 +18,9 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Slog;
 import android.view.MotionEvent;
 import android.widget.RelativeLayout;
 
-import com.android.systemui.R;
-
 public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel {
     TabletStatusBar mBar;
 
@@ -54,5 +51,17 @@
         mBar.resetNotificationPeekFadeTimer();
         return false;
     }
-}
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index df09f84..96f6e2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -34,6 +34,7 @@
 import android.content.res.Resources;
 import android.inputmethodservice.InputMethodService;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.LayerDrawable;
 import android.provider.Settings;
@@ -188,14 +189,33 @@
         mNotificationPanel.setOnTouchListener(
                 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
 
-        // the battery and network icons
+        // the battery icon
         mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
         mBatteryController.addLabelView(
                 (TextView)mNotificationPanel.findViewById(R.id.battery_text));
+
+        // Bt
         mBluetoothController.addIconView(
                 (ImageView)mNotificationPanel.findViewById(R.id.bluetooth));
-        mNetworkController.addCombinedSignalIconView(
-                (ImageView)mNotificationPanel.findViewById(R.id.network_signal));
+
+        // network icons: either a combo icon that switches between mobile and data, or distinct
+        // mobile and data icons
+        final ImageView comboRSSI = 
+                (ImageView)mNotificationPanel.findViewById(R.id.network_signal);
+        if (comboRSSI != null) {
+            mNetworkController.addCombinedSignalIconView(comboRSSI);
+        }
+        final ImageView mobileRSSI = 
+                (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal);
+        if (mobileRSSI != null) {
+            mNetworkController.addPhoneSignalIconView(mobileRSSI);
+        }
+        final ImageView wifiRSSI = 
+                (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal);
+        if (wifiRSSI != null) {
+            mNetworkController.addWifiIconView(wifiRSSI);
+        }
+
         mNetworkController.addDataTypeIconView(
                 (ImageView)mNotificationPanel.findViewById(R.id.network_type));
         mNetworkController.addDataDirectionOverlayIconView(
@@ -341,8 +361,9 @@
     private int getNotificationPanelHeight() {
         final Resources res = mContext.getResources();
         final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
-        return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height),
-                d.getRealHeight());
+        final Point size = new Point();
+        d.getRealSize(size);
+        return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
     }
 
     @Override
@@ -352,6 +373,7 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
+        mHeightReceiver.updateHeight(); // display size may have changed
         loadDimens();
         mNotificationPanelParams.height = getNotificationPanelHeight();
         WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
@@ -444,9 +466,23 @@
         mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
         mBluetoothController = new BluetoothController(mContext);
         mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth));
+
         mNetworkController = new NetworkController(mContext);
-        mNetworkController.addCombinedSignalIconView(
-                (ImageView)sb.findViewById(R.id.network_signal));
+        final ImageView comboRSSI = 
+                (ImageView)sb.findViewById(R.id.network_signal);
+        if (comboRSSI != null) {
+            mNetworkController.addCombinedSignalIconView(comboRSSI);
+        }
+        final ImageView mobileRSSI = 
+                (ImageView)sb.findViewById(R.id.mobile_signal);
+        if (mobileRSSI != null) {
+            mNetworkController.addPhoneSignalIconView(mobileRSSI);
+        }
+        final ImageView wifiRSSI = 
+                (ImageView)sb.findViewById(R.id.wifi_signal);
+        if (wifiRSSI != null) {
+            mNetworkController.addWifiIconView(wifiRSSI);
+        }
         mNetworkController.addDataTypeIconView(
                 (ImageView)sb.findViewById(R.id.network_type));
         mNetworkController.addDataDirectionOverlayIconView(
@@ -808,7 +844,8 @@
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                         notification.notification.icon, notification.notification.iconLevel,
-                        notification.notification.number);
+                        notification.notification.number,
+                        notification.notification.tickerText);
                 if (!oldEntry.icon.set(ic)) {
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
@@ -1012,10 +1049,7 @@
 
         mCompatModeButton.refresh();
         if (mCompatModeButton.getVisibility() == View.VISIBLE) {
-            if (DEBUG_COMPAT_HELP
-                    || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) {
                 showCompatibilityHelp();
-            }
         } else {
             hideCompatibilityHelp();
             mCompatModePanel.closePanel();
@@ -1451,13 +1485,15 @@
         }
         // Construct the icon.
         final StatusBarIconView iconView = new StatusBarIconView(mContext,
-                notification.pkg + "/0x" + Integer.toHexString(notification.id));
+                notification.pkg + "/0x" + Integer.toHexString(notification.id),
+                notification.notification);
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
         final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                     notification.notification.icon,
                     notification.notification.iconLevel,
-                    notification.notification.number);
+                    notification.notification.number,
+                    notification.notification.tickerText);
         if (!iconView.set(ic)) {
             handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
             return null;
@@ -1501,11 +1537,6 @@
         // alternate behavior in DND mode
         if (mNotificationDNDMode) {
             if (mIconLayout.getChildCount() == 0) {
-                final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd");
-                iconView.setImageResource(R.drawable.ic_notification_dnd);
-                iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-                iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
-
                 final Notification dndNotification = new Notification.Builder(mContext)
                     .setContentTitle(mContext.getText(R.string.notifications_off_title))
                     .setContentText(mContext.getText(R.string.notifications_off_text))
@@ -1513,6 +1544,12 @@
                     .setOngoing(true)
                     .getNotification();
 
+                final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd",
+                        dndNotification);
+                iconView.setImageResource(R.drawable.ic_notification_dnd);
+                iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+                iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
+
                 mNotificationDNDDummyEntry = new NotificationData.Entry(
                         null,
                         new StatusBarNotification("", 0, "", 0, 0, dndNotification),
@@ -1634,19 +1671,24 @@
         } else {
             if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
                 vetoButton.setVisibility(View.INVISIBLE);
+                vetoButton.setContentDescription("VETO");
             } else {
                 vetoButton.setVisibility(View.GONE);
             }
         }
+        vetoButton.setContentDescription(mContext.getString(
+                R.string.accessibility_remove_notification));
 
         // the large icon
         ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
         if (sbn.notification.largeIcon != null) {
             largeIcon.setImageBitmap(sbn.notification.largeIcon);
+            largeIcon.setContentDescription(sbn.notification.tickerText);
         } else {
             largeIcon.getLayoutParams().width = 0;
             largeIcon.setVisibility(View.INVISIBLE);
         }
+        largeIcon.setContentDescription(sbn.notification.tickerText);
 
         // bind the click event to the content area
         ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index a8f4262..6045e31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -284,7 +284,7 @@
         } else if (n.tickerText != null) {
             group = (ViewGroup)inflater.inflate(R.layout.status_bar_ticker_compat, mWindow, false);
             final Drawable icon = StatusBarIconView.getIcon(mContext,
-                    new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0));
+                    new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0, n.tickerText));
             ImageView iv = (ImageView)group.findViewById(iconId);
             iv.setImageDrawable(icon);
             iv.setVisibility(View.VISIBLE);
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index c0b0a08..8554b77 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -4,6 +4,7 @@
 
     <application android:label="VpnDialogs">
         <activity android:name=".ConfirmDialog"
+                android:permission="android.permission.VPN"
                 android:theme="@style/transparent">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml
index 5ab6ee2..11a247a 100644
--- a/packages/VpnDialogs/res/layout/confirm.xml
+++ b/packages/VpnDialogs/res/layout/confirm.xml
@@ -18,7 +18,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:padding="5mm">
+        android:padding="3mm">
 
     <ImageView android:id="@+id/icon"
             android:layout_width="@android:dimen/app_icon_size"
diff --git a/packages/VpnDialogs/res/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml
index 330b8e3..3dcbb46 100644
--- a/packages/VpnDialogs/res/layout/manage.xml
+++ b/packages/VpnDialogs/res/layout/manage.xml
@@ -18,6 +18,7 @@
 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:padding="3mm"
         android:stretchColumns="0,1">
 
     <TableRow>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index 21e916b..40c0a02 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -58,6 +58,13 @@
     @Override
     protected void onResume() {
         super.onResume();
+
+        if (getCallingPackage() != null) {
+            Log.e(TAG, getCallingPackage() + " cannot start this activity");
+            finish();
+            return;
+        }
+
         try {
             mConfig = getIntent().getParcelableExtra("config");
 
@@ -83,7 +90,6 @@
             } else {
                 PackageManager pm = getPackageManager();
                 ApplicationInfo app = pm.getApplicationInfo(mConfig.packagz, 0);
-
                 mDialog = new AlertDialog.Builder(this)
                         .setIcon(app.loadIcon(pm))
                         .setTitle(app.loadLabel(pm))
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 8ba235b..47d34b3 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -35,7 +35,6 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.LocalPowerManager;
 import android.os.Message;
 import android.os.PowerManager;
@@ -43,7 +42,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.telephony.TelephonyManager;
 import android.util.EventLog;
 import android.util.Log;
@@ -689,13 +687,11 @@
 
         switch (simState) {
             case ABSENT:
-            case PERM_DISABLED:
                 // only force lock screen in case of missing sim if user hasn't
                 // gone through setup wizard
                 if (!mUpdateMonitor.isDeviceProvisioned()) {
                     if (!isShowing()) {
-                        if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_ABSENT "
-                                + "or PERM_DISABLED and keygaurd isn't showing,"
+                        if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
                                 + " we need to show the keyguard since the "
                                 + "device isn't provisioned yet.");
                         doKeyguard();
@@ -713,7 +709,17 @@
                 } else {
                     resetStateLocked();
                 }
-
+                break;
+            case PERM_DISABLED:
+                if (!isShowing()) {
+                    if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+                          + "keygaurd isn't showing.");
+                    doKeyguard();
+                } else {
+                    if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+                          + "show permanently disabled message in lockscreen.");
+                    resetStateLocked();
+                }
                 break;
             case READY:
                 if (isShowing()) {
@@ -1109,8 +1115,11 @@
                 // Give feedback to user when secure keyguard is active and engaged
                 if (mShowing && isSecure()) {
                     if (!mShowingLockIcon) {
+                        String contentDescription = mContext.getString(
+                                com.android.internal.R.string.status_bar_device_locked);
                         mStatusBarManager.setIcon("secure",
-                                com.android.internal.R.drawable.stat_sys_secure, 0);
+                                com.android.internal.R.drawable.stat_sys_secure, 0,
+                                contentDescription);
                         mShowingLockIcon = true;
                     }
                 } else {
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 75e799c..e177565a 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -75,6 +75,7 @@
 
     private StatusView mStatusView;
     private final boolean mUseSystemIME = true; // TODO: Make configurable
+    private boolean mResuming; // used to prevent poking the wakelock during onResume()
 
     // To avoid accidental lockout due to events while the device in in the pocket, ignore
     // any passwords with length less than or equal to this length.
@@ -185,7 +186,9 @@
             }
 
             public void afterTextChanged(Editable s) {
-                mCallback.pokeWakelock();
+                if (!mResuming) {
+                    mCallback.pokeWakelock();
+                }
             }
         });
     }
@@ -208,6 +211,7 @@
 
     /** {@inheritDoc} */
     public void onResume() {
+        mResuming = true;
         // reset status
         mStatusView.resetStatusInfo(mUpdateMonitor, mLockPatternUtils);
 
@@ -222,6 +226,7 @@
         if (deadline != 0) {
             handleAttemptLockout(deadline);
         }
+        mResuming = false;
     }
 
     /** {@inheritDoc} */
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index dff0556..a4e94ef 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -374,13 +374,13 @@
                 st.menu.startDispatchingItemsChanged();
                 return false;
             }
-            st.menu.startDispatchingItemsChanged();
 
             // Set the proper keymap
             KeyCharacterMap kmap = KeyCharacterMap.load(
                     event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD);
             st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC;
             st.menu.setQwertyMode(st.qwertyMode);
+            st.menu.startDispatchingItemsChanged();
         }
 
         // Set other state
@@ -388,6 +388,11 @@
         st.isHandled = false;
         mPreparedPanel = st;
 
+        if (st.frozenActionViewState != null) {
+            st.menu.restoreActionViewStates(st.frozenActionViewState);
+            st.frozenActionViewState = null;
+        }
+
         return true;
     }
 
@@ -449,8 +454,6 @@
         if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
                 mActionBar.isOverflowReserved()) {
             if (mActionBar.getVisibility() == View.VISIBLE) {
-                // Invalidate the options menu, we want a prepare event that the app can respond to.
-                invalidatePanelMenu(FEATURE_OPTIONS_PANEL);
                 mActionBar.showOverflowMenu();
             }
         } else {
@@ -652,7 +655,15 @@
     @Override
     public void invalidatePanelMenu(int featureId) {
         PanelFeatureState st = getPanelState(featureId, true);
+        Bundle savedActionViewStates = null;
         if (st.menu != null) {
+            savedActionViewStates = new Bundle();
+            st.menu.saveActionViewStates(savedActionViewStates);
+            if (savedActionViewStates.size() > 0) {
+                st.frozenActionViewState = savedActionViewStates;
+            }
+            // This will be started again when the panel is prepared.
+            st.menu.stopDispatchingItemsChanged();
             st.menu.clear();
         }
         st.refreshMenuContent = true;
@@ -1668,14 +1679,6 @@
                 }
             }
 
-            // Back cancels action modes first.
-            if (mActionMode != null && keyCode == KeyEvent.KEYCODE_BACK) {
-                if (action == KeyEvent.ACTION_UP) {
-                    mActionMode.finish();
-                }
-                return true;
-            }
-
             if (!isDestroyed()) {
                 final Callback cb = getCallback();
                 final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
@@ -1684,6 +1687,7 @@
                     return true;
                 }
             }
+
             return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
                     : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
         }
@@ -1730,7 +1734,32 @@
         }
 
         public boolean superDispatchKeyEvent(KeyEvent event) {
-            return super.dispatchKeyEvent(event);
+            if (super.dispatchKeyEvent(event)) {
+                return true;
+            }
+
+            // Not handled by the view hierarchy, does the action bar want it
+            // to cancel out of something special?
+            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+                final int action = event.getAction();
+                // Back cancels action modes first.
+                if (mActionMode != null) {
+                    if (action == KeyEvent.ACTION_UP) {
+                        mActionMode.finish();
+                    }
+                    return true;
+                }
+
+                // Next collapse any expanded action views.
+                if (mActionBar != null && mActionBar.hasExpandedActionView()) {
+                    if (action == KeyEvent.ACTION_UP) {
+                        mActionBar.collapseActionView();
+                    }
+                    return true;
+                }
+            }
+
+            return false;
         }
 
         public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
@@ -2011,13 +2040,14 @@
                         mActionModePopup = new PopupWindow(mContext, null,
                                 com.android.internal.R.attr.actionModePopupWindowStyle);
                         mActionModePopup.setLayoutInScreenEnabled(true);
+                        mActionModePopup.setLayoutInsetDecor(true);
                         mActionModePopup.setClippingEnabled(false);
                         mActionModePopup.setContentView(mActionModeView);
                         mActionModePopup.setWidth(MATCH_PARENT);
 
                         TypedValue heightValue = new TypedValue();
                         mContext.getTheme().resolveAttribute(
-                                com.android.internal.R.attr.actionBarSize, heightValue, false);
+                                com.android.internal.R.attr.actionBarSize, heightValue, true);
                         final int height = TypedValue.complexToDimensionPixelSize(heightValue.data,
                                 mContext.getResources().getDisplayMetrics());
                         mActionModePopup.setHeight(height);
@@ -2240,7 +2270,7 @@
             }
 
             PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
-            if (st != null && st.menu != null) {
+            if (st != null && st.menu != null && mFeatureId < 0) {
                 st.menu.close();
             }
         }
@@ -2627,7 +2657,9 @@
                     // being called in the middle of onCreate or similar.
                     mDecor.post(new Runnable() {
                         public void run() {
-                            if (!isDestroyed()) {
+                            // Invalidate if the panel menu hasn't been created before this.
+                            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+                            if (!isDestroyed() && (st == null || st.menu == null)) {
                                 invalidatePanelMenu(FEATURE_ACTION_BAR);
                             }
                         }
@@ -3006,6 +3038,12 @@
          */
         Bundle frozenMenuState;
 
+        /**
+         * Contains the state of associated action views when told to freeze.
+         * These are saved across invalidations.
+         */
+        Bundle frozenActionViewState;
+
         PanelFeatureState(int featureId) {
             this.featureId = featureId;
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ad6cebb..b7f6adf 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -166,22 +166,22 @@
     static final int SYSTEM_DIALOG_LAYER = 6;
     // toasts and the plugged-in battery thing
     static final int TOAST_LAYER = 7;
-    static final int STATUS_BAR_LAYER = 8;
-    static final int STATUS_BAR_PANEL_LAYER = 9;
     // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    static final int PRIORITY_PHONE_LAYER = 10;
+    static final int PRIORITY_PHONE_LAYER = 8;
     // like the ANR / app crashed dialogs
-    static final int SYSTEM_ALERT_LAYER = 11;
+    static final int SYSTEM_ALERT_LAYER = 9;
     // system-level error dialogs
-    static final int SYSTEM_ERROR_LAYER = 12;
+    static final int SYSTEM_ERROR_LAYER = 10;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_LAYER = 13;
+    static final int INPUT_METHOD_LAYER = 11;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_DIALOG_LAYER = 14;
+    static final int INPUT_METHOD_DIALOG_LAYER = 12;
     // the keyguard; nothing on top of these can take focus, since they are
     // responsible for power management when displayed.
-    static final int KEYGUARD_LAYER = 15;
-    static final int KEYGUARD_DIALOG_LAYER = 16;
+    static final int KEYGUARD_LAYER = 13;
+    static final int KEYGUARD_DIALOG_LAYER = 14;
+    static final int STATUS_BAR_LAYER = 15;
+    static final int STATUS_BAR_PANEL_LAYER = 16;
     // the navigation bar, if available, shows atop most things
     static final int NAVIGATION_BAR_LAYER = 17;
     // the drag layer: input for drag-and-drop is associated with this window,
@@ -1703,7 +1703,11 @@
                     }
                 }
             }
-            if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + navr);
+            if (DEBUG_LAYOUT) {
+                Log.i(TAG, "mNavigationBar frame: " + navr);
+                Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
+                            mDockLeft, mDockTop, mDockRight, mDockBottom));
+            }
 
             // apply navigation bar insets
             pf.left = df.left = vf.left = mDockLeft;
@@ -1713,6 +1717,25 @@
 
             mStatusBar.computeFrameLw(pf, df, vf, vf);
 
+            // now, let's consider the navigation bar; if it exists, it must be removed from the
+            // available screen real estate (like an un-hideable status bar)
+            if (navr != null) {
+                if (navr.top == 0) {
+                    // Navigation bar is vertical
+                    if (mRestrictedScreenLeft == navr.left) {
+                        mRestrictedScreenLeft = navr.right;
+                        mRestrictedScreenWidth -= (navr.right - navr.left);
+                    } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
+                        mRestrictedScreenWidth -= (navr.right - navr.left);
+                    }
+                } else {
+                    // Navigation bar horizontal, at bottom
+                    if ((mRestrictedScreenHeight+mRestrictedScreenTop) == navr.bottom) {
+                        mRestrictedScreenHeight -= (navr.bottom-navr.top);
+                    }
+                }
+            }
+
             if (mStatusBar.isVisibleLw()) {
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
@@ -1745,23 +1768,6 @@
                         mRestrictedScreenHeight -= (r.bottom-r.top);
                     }
 
-                    if (navr != null) {
-                        if (navr.top == 0) {
-                            // Navigation bar is vertical
-                            if (mRestrictedScreenLeft == navr.left) {
-                                mRestrictedScreenLeft = navr.right;
-                                mRestrictedScreenWidth -= (navr.right - navr.left);
-                            } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
-                                mRestrictedScreenWidth -= (navr.right - navr.left);
-                            }
-                        } else {
-                            // Navigation bar horizontal, at bottom
-                            if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
-                                mRestrictedScreenHeight -= (navr.bottom-navr.top);
-                            }
-                        }
-                    }
-
                     mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
                     mContentBottom = mCurBottom = mDockBottom
                             = mRestrictedScreenTop + mRestrictedScreenHeight;
@@ -1873,19 +1879,22 @@
                         // permission, so they have the same privileges as the status
                         // bar itself.
                         //
-                        // However, they should still dodge the navigation bar if it exists. A
-                        // straightforward way to do this is to only allow the status bar panels to
-                        // extend to the extrema of the allowable region for the IME dock.
+                        // However, they should still dodge the navigation bar if it exists.
 
                         pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
                         pf.top = df.top = mUnrestrictedScreenTop;
                         pf.right = df.right = hasNavBar
-                                            ? mDockRight
+                                            ? mRestrictedScreenLeft+mRestrictedScreenWidth
                                             : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                         pf.bottom = df.bottom = hasNavBar
-                                              ? mDockBottom
+                                              ? mRestrictedScreenTop+mRestrictedScreenHeight
                                               : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
 
+                        if (DEBUG_LAYOUT) {
+                            Log.v(TAG, String.format(
+                                        "Laying out status bar window: (%d,%d - %d,%d)",
+                                        pf.left, pf.top, pf.right, pf.bottom));
+                        }
                     } else {
                         pf.left = df.left = mRestrictedScreenLeft;
                         pf.top = df.top = mRestrictedScreenTop;
@@ -1922,12 +1931,23 @@
                     pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
                     pf.top = df.top = cf.top = mUnrestrictedScreenTop;
                     pf.right = df.right = cf.right = hasNavBar
-                                        ? mDockRight
+                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
                                         : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                     pf.bottom = df.bottom = cf.bottom = hasNavBar
-                                          ? mDockBottom
+                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
                                           : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
 
+                } else if (attrs.type == TYPE_NAVIGATION_BAR) {
+                    // The navigation bar has Real Ultimate Power.
+                    pf.left = df.left = mUnrestrictedScreenLeft;
+                    pf.top = df.top = mUnrestrictedScreenTop;
+                    pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+                    pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+                    if (DEBUG_LAYOUT) {
+                        Log.v(TAG, String.format(
+                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
+                                    pf.left, pf.top, pf.right, pf.bottom));
+                    }
                 } else {
                     pf.left = df.left = cf.left = mRestrictedScreenLeft;
                     pf.top = df.top = cf.top = mRestrictedScreenTop;
@@ -2424,20 +2444,22 @@
         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;
+                    if (isScreenOn) {
+                        // 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();
+                            // Take the screenshot
+                            takeScreenshot();
 
-                        // Prevent the event from being passed through to the current activity
-                        result &= ~ACTION_PASS_TO_USER;
-                        break;
+                            // Prevent the event from being passed through to the current activity
+                            result &= ~ACTION_PASS_TO_USER;
+                            break;
+                        }
+                        mVolumeDownTriggered = true;
                     }
-                    mVolumeDownTriggered = true;
                 } else {
                     mVolumeDownTriggered = false;
                 }
@@ -2521,17 +2543,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;
+                    if (isScreenOn) {
+                        // 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;
+                            // Prevent the event from being passed through to the current activity
+                            break;
+                        }
+                        mPowerDownTriggered = true;
                     }
-                    mPowerDownTriggered = true;
-
 
                     ITelephony telephonyService = getTelephonyService();
                     boolean hungUp = false;
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 6bb1f56..fa49592 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -21,9 +21,11 @@
     libhardware \
     libhardware_legacy \
     libeffects \
-    libdl
+    libdl \
+    libpowermanager
 
 LOCAL_STATIC_LIBRARIES := \
+    libcpustats \
     libmedia_helper
 
 LOCAL_MODULE:= libaudioflinger
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index daf94f2..4e068b2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -52,6 +52,10 @@
 #include <media/EffectsFactoryApi.h>
 #include <audio_effects/effect_visualizer.h>
 
+#include <cpustats/ThreadCpuUsage.h>
+#include <powermanager/PowerManager.h>
+// #define DEBUG_CPU_USAGE 10  // log statistics every n wall clock seconds
+
 // ----------------------------------------------------------------------------
 
 
@@ -78,6 +82,8 @@
 
 static const nsecs_t kWarningThrottle = seconds(5);
 
+// RecordThread loop sleep time upon application overrun or audio HAL read error
+static const int kRecordThreadSleepUs = 5000;
 
 // ----------------------------------------------------------------------------
 
@@ -414,7 +420,7 @@
             lSessionId = *sessionId;
         } else {
             // if no audio session id is provided, create one here
-            lSessionId = nextUniqueId_l();
+            lSessionId = nextUniqueId();
             if (sessionId != NULL) {
                 *sessionId = lSessionId;
             }
@@ -722,6 +728,15 @@
         thread = checkPlaybackThread_l(ioHandle);
         if (thread == NULL) {
             thread = checkRecordThread_l(ioHandle);
+        } else if (thread.get() == primaryPlaybackThread_l()) {
+            // indicate output device change to all input threads for pre processing
+            AudioParameter param = AudioParameter(keyValuePairs);
+            int value;
+            if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+                for (size_t i = 0; i < mRecordThreads.size(); i++) {
+                    mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
+                }
+            }
         }
     }
     if (thread != NULL) {
@@ -870,17 +885,21 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
     :   Thread(false),
         mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
-        mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
+        mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
+        mDevice(device)
 {
+    mDeathRecipient = new PMDeathRecipient(this);
 }
 
 AudioFlinger::ThreadBase::~ThreadBase()
 {
     mParamCond.broadcast();
     mNewParameters.clear();
+    // do not lock the mutex in destructor
+    releaseWakeLock_l();
 }
 
 void AudioFlinger::ThreadBase::exit()
@@ -1029,15 +1048,100 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+    write(fd, buffer, strlen(buffer));
+
+    for (size_t i = 0; i < mEffectChains.size(); ++i) {
+        sp<EffectChain> chain = mEffectChains[i];
+        if (chain != 0) {
+            chain->dump(fd, args);
+        }
+    }
+    return NO_ERROR;
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock()
+{
+    Mutex::Autolock _l(mLock);
+    acquireWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
+{
+    if (mPowerManager == 0) {
+        // use checkService() to avoid blocking if power service is not up yet
+        sp<IBinder> binder =
+            defaultServiceManager()->checkService(String16("power"));
+        if (binder == 0) {
+            LOGW("Thread %s cannot connect to the power manager service", mName);
+        } else {
+            mPowerManager = interface_cast<IPowerManager>(binder);
+            binder->linkToDeath(mDeathRecipient);
+        }
+    }
+    if (mPowerManager != 0) {
+        sp<IBinder> binder = new BBinder();
+        status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+                                                         binder,
+                                                         String16(mName));
+        if (status == NO_ERROR) {
+            mWakeLockToken = binder;
+        }
+        LOGV("acquireWakeLock_l() %s status %d", mName, status);
+    }
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock()
+{
+    Mutex::Autolock _l(mLock);
+    releaseWakeLock();
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock_l()
+{
+    if (mWakeLockToken != 0) {
+        LOGV("releaseWakeLock_l() %s", mName);
+        if (mPowerManager != 0) {
+            mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+        }
+        mWakeLockToken.clear();
+    }
+}
+
+void AudioFlinger::ThreadBase::clearPowerManager()
+{
+    Mutex::Autolock _l(mLock);
+    releaseWakeLock_l();
+    mPowerManager.clear();
+}
+
+void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        thread->clearPowerManager();
+    }
+    LOGW("power manager service died !!!");
+}
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
-    :   ThreadBase(audioFlinger, id),
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
+                                             AudioStreamOut* output,
+                                             int id,
+                                             uint32_t device)
+    :   ThreadBase(audioFlinger, id, device),
         mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
-        mDevice(device)
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
+    snprintf(mName, kNameLength, "AudioOut_%d", id);
+
     readOutputParameters();
 
     mMasterVolume = mAudioFlinger->masterVolume();
@@ -1096,24 +1200,6 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
-    write(fd, buffer, strlen(buffer));
-
-    for (size_t i = 0; i < mEffectChains.size(); ++i) {
-        sp<EffectChain> chain = mEffectChains[i];
-        if (chain != 0) {
-            chain->dump(fd, args);
-        }
-    }
-    return NO_ERROR;
-}
-
 status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -1154,12 +1240,7 @@
 
 void AudioFlinger::PlaybackThread::onFirstRef()
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-
-    snprintf(buffer, SIZE, "Playback Thread %p", this);
-
-    run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+    run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
 // PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1196,9 +1277,9 @@
         }
     }
 
-    if (mOutput == 0) {
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
         LOGE("Audio driver not initialized.");
-        lStatus = NO_INIT;
         goto Exit;
     }
 
@@ -1420,7 +1501,7 @@
     if (halFrames == 0 || dspFrames == 0) {
         return BAD_VALUE;
     }
-    if (mOutput == 0) {
+    if (initCheck() != NO_ERROR) {
         return INVALID_OPERATION;
     }
     *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
@@ -1465,34 +1546,6 @@
     return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
-{
-    Mutex::Autolock _l(mLock);
-    return getEffectChain_l(sessionId);
-}
-
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
-{
-    sp<EffectChain> chain;
-
-    size_t size = mEffectChains.size();
-    for (size_t i = 0; i < size; i++) {
-        if (mEffectChains[i]->sessionId() == sessionId) {
-            chain = mEffectChains[i];
-            break;
-        }
-    }
-    return chain;
-}
-
-void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
-{
-    Mutex::Autolock _l(mLock);
-    size_t size = mEffectChains.size();
-    for (size_t i = 0; i < size; i++) {
-        mEffectChains[i]->setMode_l(mode);
-    }
-}
 
 // ----------------------------------------------------------------------------
 
@@ -1500,7 +1553,7 @@
     :   PlaybackThread(audioFlinger, output, id, device),
         mAudioMixer(0)
 {
-    mType = PlaybackThread::MIXER;
+    mType = ThreadBase::MIXER;
     mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
 
     // FIXME - Current mixer implementation only supports stereo output
@@ -1529,9 +1582,42 @@
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
     Vector< sp<EffectChain> > effectChains;
+#ifdef DEBUG_CPU_USAGE
+    ThreadCpuUsage cpu;
+    const CentralTendencyStatistics& stats = cpu.statistics();
+#endif
+
+    acquireWakeLock();
 
     while (!exitPending())
     {
+#ifdef DEBUG_CPU_USAGE
+        cpu.sampleAndEnable();
+        unsigned n = stats.n();
+        // cpu.elapsed() is expensive, so don't call it every loop
+        if ((n & 127) == 1) {
+            long long elapsed = cpu.elapsed();
+            if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
+                double perLoop = elapsed / (double) n;
+                double perLoop100 = perLoop * 0.01;
+                double mean = stats.mean();
+                double stddev = stats.stddev();
+                double minimum = stats.minimum();
+                double maximum = stats.maximum();
+                cpu.resetStatistics();
+                LOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n  us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n  %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f",
+                        elapsed * .000000001, n, perLoop * .000001,
+                        mean * .001,
+                        stddev * .001,
+                        minimum * .001,
+                        maximum * .001,
+                        mean / perLoop100,
+                        stddev / perLoop100,
+                        minimum / perLoop100,
+                        maximum / perLoop100);
+            }
+        }
+#endif
         processConfigEvents();
 
         mixerStatus = MIXER_IDLE;
@@ -1566,10 +1652,12 @@
 
                     if (exitPending()) break;
 
+                    releaseWakeLock_l();
                     // wait until we have something to do...
                     LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
                     mWaitWorkCV.wait(mLock);
                     LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+                    acquireWakeLock_l();
 
                     if (mMasterMute == false) {
                         char value[PROPERTY_VALUE_MAX];
@@ -1670,6 +1758,8 @@
         mOutput->stream->common.standby(&mOutput->stream->common);
     }
 
+    releaseWakeLock();
+
     LOGV("MixerThread %p exiting", this);
     return false;
 }
@@ -2038,7 +2128,7 @@
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
     :   PlaybackThread(audioFlinger, output, id, device)
 {
-    mType = PlaybackThread::DIRECT;
+    mType = ThreadBase::DIRECT;
 }
 
 AudioFlinger::DirectOutputThread::~DirectOutputThread()
@@ -2157,6 +2247,8 @@
     // hardware resources as soon as possible
     nsecs_t standbyDelay = microseconds(activeSleepTime*2);
 
+    acquireWakeLock();
+
     while (!exitPending())
     {
         bool rampVolume;
@@ -2196,9 +2288,11 @@
 
                     if (exitPending()) break;
 
+                    releaseWakeLock_l();
                     LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
                     mWaitWorkCV.wait(mLock);
                     LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+                    acquireWakeLock_l();
 
                     if (mMasterMute == false) {
                         char value[PROPERTY_VALUE_MAX];
@@ -2417,6 +2511,8 @@
         mOutput->stream->common.standby(&mOutput->stream->common);
     }
 
+    releaseWakeLock();
+
     LOGV("DirectOutputThread %p exiting", this);
     return false;
 }
@@ -2517,7 +2613,7 @@
 AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
     :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
 {
-    mType = PlaybackThread::DUPLICATING;
+    mType = ThreadBase::DUPLICATING;
     addOutputTrack(mainThread);
 }
 
@@ -2542,6 +2638,8 @@
     uint32_t sleepTime = idleSleepTime;
     Vector< sp<EffectChain> > effectChains;
 
+    acquireWakeLock();
+
     while (!exitPending())
     {
         processConfigEvents();
@@ -2582,9 +2680,12 @@
 
                     if (exitPending()) break;
 
+                    releaseWakeLock_l();
                     LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
                     mWaitWorkCV.wait(mLock);
                     LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+                    acquireWakeLock_l();
+
                     if (mMasterMute == false) {
                         char value[PROPERTY_VALUE_MAX];
                         property_get("ro.audio.silent", value, "0");
@@ -2671,6 +2772,8 @@
         effectChains.clear();
     }
 
+    releaseWakeLock();
+
     return false;
 }
 
@@ -2936,7 +3039,7 @@
         mStreamType = streamType;
         // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
         // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
-        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
+        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
     }
 }
 
@@ -3717,21 +3820,26 @@
         if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
             lSessionId = *sessionId;
         } else {
-            lSessionId = nextUniqueId_l();
+            lSessionId = nextUniqueId();
             if (sessionId != NULL) {
                 *sessionId = lSessionId;
             }
         }
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
-        recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
-                                                   format, channelMask, frameCount, flags, lSessionId);
+        recordTrack = thread->createRecordTrack_l(client,
+                                                sampleRate,
+                                                format,
+                                                channelMask,
+                                                frameCount,
+                                                flags,
+                                                lSessionId,
+                                                &lStatus);
     }
-    if (recordTrack->getCblk() == NULL) {
+    if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the RecordTrack so that the Client
         // destructor is called by the TrackBase destructor with mLock held
         client.clear();
         recordTrack.clear();
-        lStatus = NO_MEMORY;
         goto Exit;
     }
 
@@ -3780,10 +3888,19 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
-    ThreadBase(audioFlinger, id),
-    mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
+                                         AudioStreamIn *input,
+                                         uint32_t sampleRate,
+                                         uint32_t channels,
+                                         int id,
+                                         uint32_t device) :
+    ThreadBase(audioFlinger, id, device),
+    mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
+    mType = ThreadBase::RECORD;
+
+    snprintf(mName, kNameLength, "AudioIn_%d", id);
+
     mReqChannelCount = popcount(channels);
     mReqSampleRate = sampleRate;
     readInputParameters();
@@ -3801,21 +3918,19 @@
 
 void AudioFlinger::RecordThread::onFirstRef()
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-
-    snprintf(buffer, SIZE, "Record Thread %p", this);
-
-    run(buffer, PRIORITY_URGENT_AUDIO);
+    run(mName, PRIORITY_URGENT_AUDIO);
 }
 
 bool AudioFlinger::RecordThread::threadLoop()
 {
     AudioBufferProvider::Buffer buffer;
     sp<RecordTrack> activeTrack;
+    Vector< sp<EffectChain> > effectChains;
 
     nsecs_t lastWarning = 0;
 
+    acquireWakeLock();
+
     // start recording
     while (!exitPending()) {
 
@@ -3832,10 +3947,12 @@
 
                 if (exitPending()) break;
 
+                releaseWakeLock_l();
                 LOGV("RecordThread: loop stopping");
                 // go to sleep
                 mWaitWorkCV.wait(mLock);
                 LOGV("RecordThread: loop starting");
+                acquireWakeLock_l();
                 continue;
             }
             if (mActiveTrack != 0) {
@@ -3863,14 +3980,20 @@
                     mStandby = false;
                 }
             }
+            lockEffectChains_l(effectChains);
         }
 
         if (mActiveTrack != 0) {
             if (mActiveTrack->mState != TrackBase::ACTIVE &&
                 mActiveTrack->mState != TrackBase::RESUMING) {
-                usleep(5000);
+                unlockEffectChains(effectChains);
+                usleep(kRecordThreadSleepUs);
                 continue;
             }
+            for (size_t i = 0; i < effectChains.size(); i ++) {
+                effectChains[i]->process_l();
+            }
+
             buffer.frameCount = mFrameCount;
             if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
                 size_t framesOut = buffer.frameCount;
@@ -3919,7 +4042,7 @@
                                     // Force input into standby so that it tries to
                                     // recover at next read attempt
                                     mInput->stream->common.standby(&mInput->stream->common);
-                                    usleep(5000);
+                                    usleep(kRecordThreadSleepUs);
                                 }
                                 mRsmpInIndex = mFrameCount;
                                 framesOut = 0;
@@ -3967,9 +4090,12 @@
                 // Release the processor for a while before asking for a new buffer.
                 // This will give the application more chance to read from the buffer and
                 // clear the overflow.
-                usleep(5000);
+                usleep(kRecordThreadSleepUs);
             }
         }
+        // enable changes in effect chain
+        unlockEffectChains(effectChains);
+        effectChains.clear();
     }
 
     if (!mStandby) {
@@ -3979,10 +4105,55 @@
 
     mStartStopCond.broadcast();
 
+    releaseWakeLock();
+
     LOGV("RecordThread %p exiting", this);
     return false;
 }
 
+
+sp<AudioFlinger::RecordThread::RecordTrack>  AudioFlinger::RecordThread::createRecordTrack_l(
+        const sp<AudioFlinger::Client>& client,
+        uint32_t sampleRate,
+        int format,
+        int channelMask,
+        int frameCount,
+        uint32_t flags,
+        int sessionId,
+        status_t *status)
+{
+    sp<RecordTrack> track;
+    status_t lStatus;
+
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
+        LOGE("Audio driver not initialized.");
+        goto Exit;
+    }
+
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+
+        track = new RecordTrack(this, client, sampleRate,
+                      format, channelMask, frameCount, flags, sessionId);
+
+        if (track->getCblk() == NULL) {
+            lStatus = NO_MEMORY;
+            goto Exit;
+        }
+
+        mTrack = track.get();
+
+    }
+    lStatus = NO_ERROR;
+
+Exit:
+    if (status) {
+        *status = lStatus;
+    }
+    return track;
+}
+
 status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
     LOGV("RecordThread::start");
@@ -4094,6 +4265,7 @@
     write(fd, result.string(), result.size());
 
     dumpBase(fd, args);
+    dumpEffectChains(fd, args);
 
     return NO_ERROR;
 }
@@ -4112,7 +4284,7 @@
                 // Force input into standby so that it tries to
                 // recover at next read attempt
                 mInput->stream->common.standby(&mInput->stream->common);
-                usleep(5000);
+                usleep(kRecordThreadSleepUs);
             }
             buffer->raw = 0;
             buffer->frameCount = 0;
@@ -4177,6 +4349,23 @@
                 reconfig = true;
             }
         }
+        if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            // forward device change to effects that have requested to be
+            // aware of attached audio device.
+            for (size_t i = 0; i < mEffectChains.size(); i++) {
+                mEffectChains[i]->setDevice_l(value);
+            }
+            // store input device and output device but do not forward output device to audio HAL.
+            // Note that status is ignored by the caller for output device
+            // (see AudioFlinger::setParameters()
+            if (value & AUDIO_DEVICE_OUT_ALL) {
+                mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
+                status = BAD_VALUE;
+            } else {
+                mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
+            }
+            mDevice |= (uint32_t)value;
+        }
         if (status == NO_ERROR) {
             status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
             if (status == INVALID_OPERATION) {
@@ -4286,6 +4475,21 @@
     return mInput->stream->get_input_frames_lost(mInput->stream);
 }
 
+uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    uint32_t result = 0;
+    if (getEffectChain_l(sessionId) != 0) {
+        result = EFFECT_SESSION;
+    }
+
+    if (mTrack != NULL && sessionId == mTrack->sessionId()) {
+        result |= TRACK_SESSION;
+    }
+
+    return result;
+}
+
 // ----------------------------------------------------------------------------
 
 int AudioFlinger::openOutput(uint32_t *pDevices,
@@ -4334,7 +4538,7 @@
     mHardwareStatus = AUDIO_HW_IDLE;
     if (outStream != NULL) {
         AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
-        int id = nextUniqueId_l();
+        int id = nextUniqueId();
 
         if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
             (format != AUDIO_FORMAT_PCM_16_BIT) ||
@@ -4371,7 +4575,7 @@
         return 0;
     }
 
-    int id = nextUniqueId_l();
+    int id = nextUniqueId();
     DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
     thread->addOutputTrack(thread2);
     mPlaybackThreads.add(id, thread);
@@ -4394,9 +4598,9 @@
 
         LOGV("closeOutput() %d", output);
 
-        if (thread->type() == PlaybackThread::MIXER) {
+        if (thread->type() == ThreadBase::MIXER) {
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-                if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
+                if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
                     DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
                     dupThread->removeOutputTrack((MixerThread *)thread.get());
                 }
@@ -4408,7 +4612,7 @@
     }
     thread->exit();
 
-    if (thread->type() != PlaybackThread::DUPLICATING) {
+    if (thread->type() != ThreadBase::DUPLICATING) {
         AudioStreamOut *out = thread->getOutput();
         out->hwDev->close_output_stream(out->hwDev, out->stream);
         delete out;
@@ -4503,9 +4707,17 @@
     if (inStream != NULL) {
         AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
 
-        int id = nextUniqueId_l();
-         // Start record thread
-        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
+        int id = nextUniqueId();
+        // Start record thread
+        // RecorThread require both input and output device indication to forward to audio
+        // pre processing modules
+        uint32_t device = (*pDevices) | primaryOutputDevice_l();
+        thread = new RecordThread(this,
+                                  input,
+                                  reqSamplingRate,
+                                  reqChannels,
+                                  id,
+                                  device);
         mRecordThreads.add(id, thread);
         LOGV("openInput() created record thread: ID %d thread %p", id, thread);
         if (pSamplingRate) *pSamplingRate = reqSamplingRate;
@@ -4563,7 +4775,7 @@
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
         if (thread != dstThread &&
-            thread->type() != PlaybackThread::DIRECT) {
+            thread->type() != ThreadBase::DIRECT) {
             MixerThread *srcThread = (MixerThread *)thread;
             srcThread->invalidateTracks(stream);
         }
@@ -4575,8 +4787,7 @@
 
 int AudioFlinger::newAudioSessionId()
 {
-    AutoMutex _l(mLock);
-    return nextUniqueId_l();
+    return nextUniqueId();
 }
 
 // checkPlaybackThread_l() must be called with AudioFlinger::mLock held
@@ -4594,7 +4805,7 @@
 {
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread != NULL) {
-        if (thread->type() == PlaybackThread::DIRECT) {
+        if (thread->type() == ThreadBase::DIRECT) {
             thread = NULL;
         }
     }
@@ -4611,12 +4822,34 @@
     return thread;
 }
 
-// nextUniqueId_l() must be called with AudioFlinger::mLock held
-int AudioFlinger::nextUniqueId_l()
+uint32_t AudioFlinger::nextUniqueId()
 {
-    return mNextUniqueId++;
+    return android_atomic_inc(&mNextUniqueId);
 }
 
+AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l()
+{
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        if (thread->getOutput()->hwDev == mPrimaryHardwareDev) {
+            return thread;
+        }
+    }
+    return NULL;
+}
+
+uint32_t AudioFlinger::primaryOutputDevice_l()
+{
+    PlaybackThread *thread = primaryPlaybackThread_l();
+
+    if (thread == NULL) {
+        return 0;
+    }
+
+    return thread->device();
+}
+
+
 // ----------------------------------------------------------------------------
 //  Effect management
 // ----------------------------------------------------------------------------
@@ -4649,7 +4882,7 @@
         effect_descriptor_t *pDesc,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
-        int output,
+        int io,
         int sessionId,
         status_t *status,
         int *id,
@@ -4661,8 +4894,8 @@
     sp<Client> client;
     wp<Client> wclient;
 
-    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
-            pid, effectClient.get(), priority, sessionId, output);
+    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, io %d",
+            pid, effectClient.get(), priority, sessionId, io);
 
     if (pDesc == NULL) {
         lStatus = BAD_VALUE;
@@ -4690,7 +4923,7 @@
         goto Exit;
     }
 
-    if (output == 0) {
+    if (io == 0) {
         if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
             // output must be specified by AudioPolicyManager when using session
             // AUDIO_SESSION_OUTPUT_STAGE
@@ -4698,9 +4931,9 @@
             goto Exit;
         } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
             // if the output returned by getOutputForEffect() is removed before we lock the
-            // mutex below, the call to checkPlaybackThread_l(output) below will detect it
+            // mutex below, the call to checkPlaybackThread_l(io) below will detect it
             // and we will exit safely
-            output = AudioSystem::getOutputForEffect(&desc);
+            io = AudioSystem::getOutputForEffect(&desc);
         }
     }
 
@@ -4777,30 +5010,40 @@
         // output threads.
         // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
         // because of code checking output when entering the function.
-        if (output == 0) {
+        // Note: io is never 0 when creating an effect on an input
+        if (io == 0) {
              // look for the thread where the specified audio session is present
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
-                    output = mPlaybackThreads.keyAt(i);
+                    io = mPlaybackThreads.keyAt(i);
                     break;
                 }
             }
+            if (io == 0) {
+               for (size_t i = 0; i < mRecordThreads.size(); i++) {
+                   if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
+                       io = mRecordThreads.keyAt(i);
+                       break;
+                   }
+               }
+            }
             // If no output thread contains the requested session ID, default to
             // first output. The effect chain will be moved to the correct output
             // thread when a track with the same session ID is created
-            if (output == 0 && mPlaybackThreads.size()) {
-                output = mPlaybackThreads.keyAt(0);
+            if (io == 0 && mPlaybackThreads.size()) {
+                io = mPlaybackThreads.keyAt(0);
+            }
+            LOGV("createEffect() got io %d for effect %s", io, desc.name);
+        }
+        ThreadBase *thread = checkRecordThread_l(io);
+        if (thread == NULL) {
+            thread = checkPlaybackThread_l(io);
+            if (thread == NULL) {
+                LOGE("createEffect() unknown output thread");
+                lStatus = BAD_VALUE;
+                goto Exit;
             }
         }
-        LOGV("createEffect() got output %d for effect %s", output, desc.name);
-        PlaybackThread *thread = checkPlaybackThread_l(output);
-        if (thread == NULL) {
-            LOGE("createEffect() unknown output thread");
-            lStatus = BAD_VALUE;
-            goto Exit;
-        }
-
-        // TODO: allow attachment of effect to inputs
 
         wclient = mClients.valueFor(pid);
 
@@ -4909,8 +5152,9 @@
     return NO_ERROR;
 }
 
+
 // PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
+sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
         const sp<AudioFlinger::Client>& client,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
@@ -4923,24 +5167,14 @@
     sp<EffectModule> effect;
     sp<EffectHandle> handle;
     status_t lStatus;
-    sp<Track> track;
     sp<EffectChain> chain;
     bool chainCreated = false;
     bool effectCreated = false;
     bool effectRegistered = false;
 
-    if (mOutput == 0) {
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
         LOGW("createEffect_l() Audio driver not initialized.");
-        lStatus = NO_INIT;
-        goto Exit;
-    }
-
-    // Do not allow auxiliary effect on session other than 0
-    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
-        sessionId != AUDIO_SESSION_OUTPUT_MIX) {
-        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
-                desc->name, sessionId);
-        lStatus = BAD_VALUE;
         goto Exit;
     }
 
@@ -4952,6 +5186,16 @@
         lStatus = BAD_VALUE;
         goto Exit;
     }
+    // Only Pre processor effects are allowed on input threads and only on input threads
+    if ((mType == RECORD &&
+            (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) ||
+            (mType != RECORD &&
+                    (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
+        LOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
+                desc->name, desc->flags, mType);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
 
     LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
 
@@ -4974,7 +5218,7 @@
         LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
 
         if (effect == 0) {
-            int id = mAudioFlinger->nextUniqueId_l();
+            int id = mAudioFlinger->nextUniqueId();
             // Check CPU and memory usage
             lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
             if (lStatus != NO_ERROR) {
@@ -5025,9 +5269,20 @@
     return handle;
 }
 
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
+{
+    sp<EffectModule> effect;
+
+    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    if (chain != 0) {
+        effect = chain->getEffectFromId_l(effectId);
+    }
+    return effect;
+}
+
 // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
 // PlaybackThread::mLock held
-status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
+status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
 {
     // check for existing effect chain with the requested audio session
     int sessionId = effect->sessionId();
@@ -5063,7 +5318,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
+void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
 
     LOGV("removeEffect_l() %p effect %p", this, effect.get());
     effect_descriptor_t desc = effect->desc();
@@ -5082,7 +5337,53 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
+void AudioFlinger::ThreadBase::lockEffectChains_l(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    effectChains = mEffectChains;
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        mEffectChains[i]->lock();
+    }
+}
+
+void AudioFlinger::ThreadBase::unlockEffectChains(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    for (size_t i = 0; i < effectChains.size(); i++) {
+        effectChains[i]->unlock();
+    }
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    return getEffectChain_l(sessionId);
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
+{
+    sp<EffectChain> chain;
+
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        if (mEffectChains[i]->sessionId() == sessionId) {
+            chain = mEffectChains[i];
+            break;
+        }
+    }
+    return chain;
+}
+
+void AudioFlinger::ThreadBase::setMode(uint32_t mode)
+{
+    Mutex::Autolock _l(mLock);
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffectChains[i]->setMode_l(mode);
+    }
+}
+
+void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
                                                     const wp<EffectHandle>& handle) {
     Mutex::Autolock _l(mLock);
     LOGV("disconnectEffect() %p effect %p", this, effect.get());
@@ -5188,35 +5489,6 @@
     return mEffectChains.size();
 }
 
-void AudioFlinger::PlaybackThread::lockEffectChains_l(
-        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
-{
-    effectChains = mEffectChains;
-    for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->lock();
-    }
-}
-
-void AudioFlinger::PlaybackThread::unlockEffectChains(
-        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
-{
-    for (size_t i = 0; i < effectChains.size(); i++) {
-        effectChains[i]->unlock();
-    }
-}
-
-
-sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
-{
-    sp<EffectModule> effect;
-
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
-    if (chain != 0) {
-        effect = chain->getEffectFromId_l(effectId);
-    }
-    return effect;
-}
-
 status_t AudioFlinger::PlaybackThread::attachAuxEffect(
         const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
 {
@@ -5257,6 +5529,34 @@
     }
 }
 
+status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+{
+    // only one chain per input thread
+    if (mEffectChains.size() != 0) {
+        return INVALID_OPERATION;
+    }
+    LOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
+
+    chain->setInBuffer(NULL);
+    chain->setOutBuffer(NULL);
+
+    mEffectChains.add(chain);
+
+    return NO_ERROR;
+}
+
+size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+{
+    LOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
+    LOGW_IF(mEffectChains.size() != 1,
+            "removeEffectChain_l() %p invalid chain size %d on thread %p",
+            chain.get(), mEffectChains.size(), this);
+    if (mEffectChains.size() == 1) {
+        mEffectChains.removeAt(0);
+    }
+    return 0;
+}
+
 // ----------------------------------------------------------------------------
 //  EffectModule implementation
 // ----------------------------------------------------------------------------
@@ -5278,12 +5578,11 @@
     if (thread == 0) {
         return;
     }
-    PlaybackThread *p = (PlaybackThread *)thread.get();
 
     memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
 
     // create effect engine from effect factory
-    mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
+    mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
 
     if (mStatus != NO_ERROR) {
         return;
@@ -5306,6 +5605,13 @@
 {
     LOGV("Destructor %p", this);
     if (mEffectInterface != NULL) {
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+                (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+            sp<ThreadBase> thread = mThread.promote();
+            if (thread != 0) {
+                thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+            }
+        }
         // release effect engine
         EffectRelease(mEffectInterface);
     }
@@ -5361,13 +5667,11 @@
         }
     }
 
-    // Release effect engine here so that it is done immediately. Otherwise it will be released
-    // by the destructor when the last strong reference on the this object is released which can
-    // happen after next process is called on this effect.
-    if (size == 0 && mEffectInterface != NULL) {
-        // release effect engine
-        EffectRelease(mEffectInterface);
-        mEffectInterface = NULL;
+    // Prevent calls to process() and other functions on effect interface from now on.
+    // The effect engine will be released by the destructor when the last strong reference on
+    // this object is released which can happen after next process is called.
+    if (size == 0) {
+        mState = DESTROYED;
     }
 
     return size;
@@ -5381,8 +5685,7 @@
     {
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-            playbackThread->disconnectEffect(keep, handle);
+            thread->disconnectEffect(keep, handle);
         }
     }
 }
@@ -5418,7 +5721,7 @@
             mState = IDLE;
         }
         break;
-    default: //IDLE , ACTIVE
+    default: //IDLE , ACTIVE, DESTROYED
         break;
     }
 }
@@ -5427,7 +5730,7 @@
 {
     Mutex::Autolock _l(mLock);
 
-    if (mEffectInterface == NULL ||
+    if (mState == DESTROYED || mEffectInterface == NULL ||
             mConfig.inputCfg.buffer.raw == NULL ||
             mConfig.outputCfg.buffer.raw == NULL) {
         return;
@@ -5592,9 +5895,23 @@
     if (status == 0) {
         status = cmdStatus;
     }
+    if (status == 0 &&
+            ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            thread->stream()->add_audio_effect(thread->stream(), mEffectInterface);
+        }
+    }
     return status;
 }
 
+status_t AudioFlinger::EffectModule::stop()
+{
+    Mutex::Autolock _l(mLock);
+    return stop_l();
+}
+
 status_t AudioFlinger::EffectModule::stop_l()
 {
     if (mEffectInterface == NULL) {
@@ -5611,6 +5928,14 @@
     if (status == 0) {
         status = cmdStatus;
     }
+    if (status == 0 &&
+            ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+        }
+    }
     return status;
 }
 
@@ -5623,7 +5948,7 @@
     Mutex::Autolock _l(mLock);
 //    LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
 
-    if (mEffectInterface == NULL) {
+    if (mState == DESTROYED || mEffectInterface == NULL) {
         return NO_INIT;
     }
     status_t status = (*mEffectInterface)->command(mEffectInterface,
@@ -5672,6 +5997,8 @@
         case ACTIVE:
             mState = STOPPING;
             break;
+        case DESTROYED:
+            return NO_ERROR; // simply ignore as we are being destroyed
         }
         for (size_t i = 1; i < mHandles.size(); i++) {
             sp<EffectHandle> h = mHandles[i].promote();
@@ -5693,6 +6020,7 @@
     case IDLE:
     case STOPPING:
     case STOPPED:
+    case DESTROYED:
     default:
         return false;
     }
@@ -5708,6 +6036,7 @@
         return true;
     case IDLE:
     case STARTING:
+    case DESTROYED:
     default:
         return false;
     }
@@ -5750,17 +6079,41 @@
 {
     Mutex::Autolock _l(mLock);
     status_t status = NO_ERROR;
-    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
-        status_t cmdStatus;
-        uint32_t size = sizeof(status_t);
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_SET_DEVICE,
-                                              sizeof(uint32_t),
-                                              &device,
-                                              &size,
-                                              &cmdStatus);
-        if (status == NO_ERROR) {
-            status = cmdStatus;
+    if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+        // audio pre processing modules on RecordThread can receive both output and
+        // input device indication in the same call
+        uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
+        if (dev) {
+            status_t cmdStatus;
+            uint32_t size = sizeof(status_t);
+
+            status = (*mEffectInterface)->command(mEffectInterface,
+                                                  EFFECT_CMD_SET_DEVICE,
+                                                  sizeof(uint32_t),
+                                                  &dev,
+                                                  &size,
+                                                  &cmdStatus);
+            if (status == NO_ERROR) {
+                status = cmdStatus;
+            }
+        }
+        dev = device & AUDIO_DEVICE_IN_ALL;
+        if (dev) {
+            status_t cmdStatus;
+            uint32_t size = sizeof(status_t);
+
+            status_t status2 = (*mEffectInterface)->command(mEffectInterface,
+                                                  EFFECT_CMD_SET_INPUT_DEVICE,
+                                                  sizeof(uint32_t),
+                                                  &dev,
+                                                  &size,
+                                                  &cmdStatus);
+            if (status2 == NO_ERROR) {
+                status2 = cmdStatus;
+            }
+            if (status == NO_ERROR) {
+                status = status2;
+            }
         }
     }
     return status;
@@ -6134,7 +6487,6 @@
         LOGW("process_l(): cannot promote mixer thread");
         return;
     }
-    PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
     bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
             (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
     bool tracksOnSession = false;
@@ -6146,7 +6498,7 @@
     // will not do it
     if (tracksOnSession &&
             activeTrackCnt() == 0) {
-        size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
+        size_t numSamples = thread->frameCount() * thread->channelCount();
         memset(mInBuffer, 0, numSamples * sizeof(int16_t));
     }
 
@@ -6286,6 +6638,10 @@
 
     for (i = 0; i < size; i++) {
         if (effect == mEffects[i]) {
+            // calling stop here will remove pre-processing effect from the audio HAL.
+            // This is safe as we hold the EffectChain mutex which guarantees that we are not in
+            // the middle of a read from audio HAL
+            mEffects[i]->stop();
             if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
                 delete[] effect->inBuffer();
             } else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1fad987..7b6215f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,6 +43,8 @@
 
 #include "AudioBufferProvider.h"
 
+#include <powermanager/IPowerManager.h>
+
 namespace android {
 
 class audio_track_cblk_t;
@@ -157,7 +159,7 @@
                         effect_descriptor_t *pDesc,
                         const sp<IEffectClient>& effectClient,
                         int32_t priority,
-                        int output,
+                        int io,
                         int sessionId,
                         status_t *status,
                         int *id,
@@ -273,10 +275,21 @@
 
     class ThreadBase : public Thread {
     public:
-        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id, uint32_t device);
         virtual             ~ThreadBase();
 
+
+        enum type {
+            MIXER,              // Thread class is MixerThread
+            DIRECT,             // Thread class is DirectOutputThread
+            DUPLICATING,        // Thread class is DuplicatingThread
+            RECORD              // Thread class is RecordThread
+        };
+
         status_t dumpBase(int fd, const Vector<String16>& args);
+        status_t dumpEffectChains(int fd, const Vector<String16>& args);
+
+        void clearPowerManager();
 
         // base for record and playback
         class TrackBase : public AudioBufferProvider, public RefBase {
@@ -377,6 +390,23 @@
             int mParam;
         };
 
+        class PMDeathRecipient : public IBinder::DeathRecipient {
+        public:
+                        PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
+            virtual     ~PMDeathRecipient() {}
+
+            // IBinder::DeathRecipient
+            virtual     void        binderDied(const wp<IBinder>& who);
+
+        private:
+                        PMDeathRecipient(const PMDeathRecipient&);
+                        PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+            wp<ThreadBase> mThread;
+        };
+
+        virtual     status_t    initCheck() const = 0;
+                    int         type() const { return mType; }
                     uint32_t    sampleRate() const;
                     int         channelCount() const;
                     uint32_t    format() const;
@@ -392,11 +422,70 @@
                     void        processConfigEvents();
                     int         id() const { return mId;}
                     bool        standby() { return mStandby; }
+                    uint32_t    device() { return mDevice; }
+        virtual     audio_stream_t* stream() = 0;
+
+                    sp<EffectHandle> createEffect_l(
+                                        const sp<AudioFlinger::Client>& client,
+                                        const sp<IEffectClient>& effectClient,
+                                        int32_t priority,
+                                        int sessionId,
+                                        effect_descriptor_t *desc,
+                                        int *enabled,
+                                        status_t *status);
+                    void disconnectEffect(const sp< EffectModule>& effect,
+                                          const wp<EffectHandle>& handle);
+
+                    // return values for hasAudioSession (bit field)
+                    enum effect_state {
+                        EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one
+                                                // effect
+                        TRACK_SESSION = 0x2     // the audio session corresponds to at least one
+                                                // track
+                    };
+
+                    // get effect chain corresponding to session Id.
+                    sp<EffectChain> getEffectChain(int sessionId);
+                    // same as getEffectChain() but must be called with ThreadBase mutex locked
+                    sp<EffectChain> getEffectChain_l(int sessionId);
+                    // add an effect chain to the chain list (mEffectChains)
+        virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
+                    // remove an effect chain from the chain list (mEffectChains)
+        virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
+                    // lock mall effect chains Mutexes. Must be called before releasing the
+                    // ThreadBase mutex before processing the mixer and effects. This guarantees the
+                    // integrity of the chains during the process.
+                    void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
+                    // unlock effect chains after process
+                    void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
+                    // set audio mode to all effect chains
+                    void setMode(uint32_t mode);
+                    // get effect module with corresponding ID on specified audio session
+                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
+                    // add and effect module. Also creates the effect chain is none exists for
+                    // the effects audio session
+                    status_t addEffect_l(const sp< EffectModule>& effect);
+                    // remove and effect module. Also removes the effect chain is this was the last
+                    // effect
+                    void removeEffect_l(const sp< EffectModule>& effect);
+                    // detach all tracks connected to an auxiliary effect
+        virtual     void detachAuxEffect_l(int effectId) {}
+                    // returns either EFFECT_SESSION if effects on this audio session exist in one
+                    // chain, or TRACK_SESSION if tracks on this audio session exist, or both
+                    virtual uint32_t hasAudioSession(int sessionId) = 0;
+                    // the value returned by default implementation is not important as the
+                    // strategy is only meaningful for PlaybackThread which implements this method
+                    virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; }
 
         mutable     Mutex                   mLock;
 
     protected:
 
+                    void        acquireWakeLock();
+                    void        acquireWakeLock_l();
+                    void        releaseWakeLock();
+                    void        releaseWakeLock_l();
+
         friend class Track;
         friend class TrackBase;
         friend class PlaybackThread;
@@ -406,6 +495,7 @@
         friend class RecordThread;
         friend class RecordTrack;
 
+                    int                     mType;
                     Condition               mWaitWorkCV;
                     sp<AudioFlinger>        mAudioFlinger;
                     uint32_t                mSampleRate;
@@ -421,18 +511,20 @@
                     bool                    mStandby;
                     int                     mId;
                     bool                    mExiting;
+                    Vector< sp<EffectChain> > mEffectChains;
+                    uint32_t                mDevice;    // output device for PlaybackThread
+                                                        // input + output devices for RecordThread
+                    static const int        kNameLength = 32;
+                    char                    mName[kNameLength];
+                    sp<IPowerManager>       mPowerManager;
+                    sp<IBinder>             mWakeLockToken;
+                    sp<PMDeathRecipient>    mDeathRecipient;
     };
 
     // --- PlaybackThread ---
     class PlaybackThread : public ThreadBase {
     public:
 
-        enum type {
-            MIXER,
-            DIRECT,
-            DUPLICATING
-        };
-
         enum mixer_state {
             MIXER_IDLE,
             MIXER_TRACKS_ENABLED,
@@ -569,6 +661,8 @@
         virtual     status_t    readyToRun();
         virtual     void        onFirstRef();
 
+        virtual     status_t    initCheck() const { return (mOutput == 0) ? NO_INIT : NO_ERROR; }
+
         virtual     uint32_t    latency() const;
 
         virtual     status_t    setMasterVolume(float value);
@@ -595,8 +689,8 @@
                                     status_t *status);
 
                     AudioStreamOut* getOutput() { return mOutput; }
+                    virtual audio_stream_t* stream() { return &mOutput->stream->common; }
 
-        virtual     int         type() const { return mType; }
                     void        suspend() { mSuspended++; }
                     void        restore() { if (mSuspended) mSuspended--; }
                     bool        isSuspended() { return (mSuspended != 0); }
@@ -605,45 +699,16 @@
         virtual     status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
                     int16_t     *mixBuffer() { return mMixBuffer; };
 
-                    sp<EffectHandle> createEffect_l(
-                                        const sp<AudioFlinger::Client>& client,
-                                        const sp<IEffectClient>& effectClient,
-                                        int32_t priority,
-                                        int sessionId,
-                                        effect_descriptor_t *desc,
-                                        int *enabled,
-                                        status_t *status);
-                    void disconnectEffect(const sp< EffectModule>& effect,
-                                          const wp<EffectHandle>& handle);
-
-                    // return values for hasAudioSession (bit field)
-                    enum effect_state {
-                        EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one
-                                                // effect
-                        TRACK_SESSION = 0x2     // the audio session corresponds to at least one
-                                                // track
-                    };
-
-                    uint32_t hasAudioSession(int sessionId);
-                    sp<EffectChain> getEffectChain(int sessionId);
-                    sp<EffectChain> getEffectChain_l(int sessionId);
-                    status_t addEffectChain_l(const sp<EffectChain>& chain);
-                    size_t removeEffectChain_l(const sp<EffectChain>& chain);
-                    void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
-                    void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
-
-                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
-                    void detachAuxEffect_l(int effectId);
+        virtual     void detachAuxEffect_l(int effectId);
                     status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track,
                             int EffectId);
                     status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track,
                             int EffectId);
-                    void setMode(uint32_t mode);
 
-                    status_t addEffect_l(const sp< EffectModule>& effect);
-                    void removeEffect_l(const sp< EffectModule>& effect);
-
-                    uint32_t getStrategyForSession_l(int sessionId);
+                    virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+                    virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+                    virtual uint32_t hasAudioSession(int sessionId);
+                    virtual uint32_t getStrategyForSession_l(int sessionId);
 
         struct  stream_type_t {
             stream_type_t()
@@ -656,7 +721,6 @@
         };
 
     protected:
-        int                             mType;
         int16_t*                        mMixBuffer;
         int                             mSuspended;
         int                             mBytesWritten;
@@ -688,11 +752,8 @@
 
         void        readOutputParameters();
 
-        uint32_t    device() { return mDevice; }
-
         virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
         status_t    dumpTracks(int fd, const Vector<String16>& args);
-        status_t    dumpEffectChains(int fd, const Vector<String16>& args);
 
         SortedVector< sp<Track> >       mTracks;
         // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
@@ -703,8 +764,6 @@
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
-        Vector< sp<EffectChain> >       mEffectChains;
-        uint32_t                        mDevice;
     };
 
     class MixerThread : public PlaybackThread {
@@ -788,11 +847,13 @@
               float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
               void audioConfigChanged_l(int event, int ioHandle, void *param2);
 
-              int  nextUniqueId_l();
+              uint32_t nextUniqueId();
               status_t moveEffectChain_l(int session,
                                      AudioFlinger::PlaybackThread *srcThread,
                                      AudioFlinger::PlaybackThread *dstThread,
                                      bool reRegister);
+              PlaybackThread *primaryPlaybackThread_l();
+              uint32_t primaryOutputDevice_l();
 
     friend class AudioBuffer;
 
@@ -864,18 +925,33 @@
                         AudioStreamIn *input,
                         uint32_t sampleRate,
                         uint32_t channels,
-                        int id);
+                        int id,
+                        uint32_t device);
                 ~RecordThread();
 
         virtual bool        threadLoop();
         virtual status_t    readyToRun() { return NO_ERROR; }
         virtual void        onFirstRef();
 
+        virtual status_t    initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; }
+                sp<AudioFlinger::RecordThread::RecordTrack>  createRecordTrack_l(
+                        const sp<AudioFlinger::Client>& client,
+                        uint32_t sampleRate,
+                        int format,
+                        int channelMask,
+                        int frameCount,
+                        uint32_t flags,
+                        int sessionId,
+                        status_t *status);
+
                 status_t    start(RecordTrack* recordTrack);
                 void        stop(RecordTrack* recordTrack);
                 status_t    dump(int fd, const Vector<String16>& args);
                 AudioStreamIn* getInput() { return mInput; }
+                virtual audio_stream_t* stream() { return &mInput->stream->common; }
 
+
+                void        setTrack(RecordTrack *recordTrack) { mTrack = recordTrack; }
         virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
         virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
         virtual bool        checkForNewParameters_l();
@@ -884,9 +960,14 @@
                 void        readInputParameters();
         virtual unsigned int  getInputFramesLost();
 
+        virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+        virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+        virtual uint32_t hasAudioSession(int sessionId);
+
     private:
                 RecordThread();
                 AudioStreamIn                       *mInput;
+                RecordTrack*                        mTrack;
                 sp<RecordTrack>                     mActiveTrack;
                 Condition                           mStartStopCond;
                 AudioResampler                      *mResampler;
@@ -943,7 +1024,8 @@
             STARTING,
             ACTIVE,
             STOPPING,
-            STOPPED
+            STOPPED,
+            DESTROYED
         };
 
         int         id() { return mId; }
@@ -988,6 +1070,7 @@
         status_t         setDevice(uint32_t device);
         status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
         status_t         setMode(uint32_t mode);
+        status_t         stop();
 
         status_t         dump(int fd, const Vector<String16>& args);
 
@@ -1103,9 +1186,8 @@
         status_t addEffect_l(const sp<EffectModule>& handle);
         size_t removeEffect_l(const sp<EffectModule>& handle);
 
-        int sessionId() {
-            return mSessionId;
-        }
+        int sessionId() { return mSessionId; }
+        void setSessionId(int sessionId) { mSessionId = sessionId; }
 
         sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
         sp<EffectModule> getEffectFromId_l(int id);
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 47ca3a0..6d06d83 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -33,11 +33,14 @@
 #include <cutils/properties.h>
 #include <dlfcn.h>
 #include <hardware_legacy/power.h>
+#include <media/AudioEffect.h>
+#include <media/EffectsFactoryApi.h>
 
 #include <hardware/hardware.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
+#include <audio_effects/audio_effects_conf.h>
 
 namespace android {
 
@@ -48,9 +51,6 @@
 static const int kDumpLockSleep = 20000;
 
 static bool checkPermission() {
-#ifndef HAVE_ANDROID_OS
-    return true;
-#endif
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
     if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
@@ -104,6 +104,13 @@
     mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
 
     LOGI("Loaded audio policy from %s (%s)", module->name, module->id);
+
+    // load audio pre processing modules
+    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+    }
 }
 
 AudioPolicyService::~AudioPolicyService()
@@ -113,6 +120,31 @@
     mAudioCommandThread->exit();
     mAudioCommandThread.clear();
 
+
+    // release audio pre processing resources
+    for (size_t i = 0; i < mInputSources.size(); i++) {
+        InputSourceDesc *source = mInputSources.valueAt(i);
+        Vector <EffectDesc *> effects = source->mEffects;
+        for (size_t j = 0; j < effects.size(); j++) {
+            delete effects[j]->mName;
+            Vector <effect_param_t *> params = effects[j]->mParams;
+            for (size_t k = 0; k < params.size(); k++) {
+                delete params[k];
+            }
+            params.clear();
+            delete effects[j];
+        }
+        effects.clear();
+        delete source;
+    }
+    mInputSources.clear();
+
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        mInputs.valueAt(i)->mEffects.clear();
+        delete mInputs.valueAt(i);
+    }
+    mInputs.clear();
+
     if (mpAudioPolicy && mpAudioPolicyDev)
         mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
     if (mpAudioPolicyDev)
@@ -279,13 +311,51 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int audioSession)
 {
     if (mpAudioPolicy == NULL) {
         return 0;
     }
     Mutex::Autolock _l(mLock);
-    return mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, format, channels, acoustics);
+    audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+                                                       format, channels, acoustics);
+
+    if (input == 0) {
+        return input;
+    }
+    // create audio pre processors according to input source
+    ssize_t index = mInputSources.indexOfKey((audio_source_t)inputSource);
+    if (index < 0) {
+        return input;
+    }
+    ssize_t idx = mInputs.indexOfKey(input);
+    InputDesc *inputDesc;
+    if (idx < 0) {
+        inputDesc = new InputDesc();
+        inputDesc->mSessionId = audioSession;
+        mInputs.add(input, inputDesc);
+    } else {
+        inputDesc = mInputs.valueAt(idx);
+    }
+
+    Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
+    for (size_t i = 0; i < effects.size(); i++) {
+        EffectDesc *effect = effects[i];
+        sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
+        status_t status = fx->initCheck();
+        if (status != NO_ERROR && status != ALREADY_EXISTS) {
+            LOGW("Failed to create Fx %s on input %d", effect->mName, input);
+            // fx goes out of scope and strong ref on AudioEffect is released
+            continue;
+        }
+        for (size_t j = 0; j < effect->mParams.size(); j++) {
+            fx->setParameter(effect->mParams[j]);
+        }
+        inputDesc->mEffects.add(fx);
+    }
+    setPreProcessorEnabled(inputDesc, true);
+    return input;
 }
 
 status_t AudioPolicyService::startInput(audio_io_handle_t input)
@@ -294,6 +364,7 @@
         return NO_INIT;
     }
     Mutex::Autolock _l(mLock);
+
     return mpAudioPolicy->start_input(mpAudioPolicy, input);
 }
 
@@ -303,6 +374,7 @@
         return NO_INIT;
     }
     Mutex::Autolock _l(mLock);
+
     return mpAudioPolicy->stop_input(mpAudioPolicy, input);
 }
 
@@ -313,6 +385,16 @@
     }
     Mutex::Autolock _l(mLock);
     mpAudioPolicy->release_input(mpAudioPolicy, input);
+
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        return;
+    }
+    InputDesc *inputDesc = mInputs.valueAt(index);
+    setPreProcessorEnabled(inputDesc, false);
+    inputDesc->mEffects.clear();
+    delete inputDesc;
+    mInputs.removeItemsAt(index);
 }
 
 status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
@@ -387,7 +469,7 @@
 }
 
 status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
-                                audio_io_handle_t output,
+                                audio_io_handle_t io,
                                 uint32_t strategy,
                                 int session,
                                 int id)
@@ -395,7 +477,7 @@
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
     }
-    return mpAudioPolicy->register_effect(mpAudioPolicy, desc, output, strategy, session, id);
+    return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id);
 }
 
 status_t AudioPolicyService::unregisterEffect(int id)
@@ -415,6 +497,43 @@
     return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
 }
 
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+                                                       effect_descriptor_t *descriptors,
+                                                       uint32_t *count)
+{
+
+    if (mpAudioPolicy == NULL) {
+        *count = 0;
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    status_t status = NO_ERROR;
+
+    size_t index;
+    for (index = 0; index < mInputs.size(); index++) {
+        if (mInputs.valueAt(index)->mSessionId == audioSession) {
+            break;
+        }
+    }
+    if (index == mInputs.size()) {
+        *count = 0;
+        return BAD_VALUE;
+    }
+    Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+    for (size_t i = 0; i < effects.size(); i++) {
+        effect_descriptor_t desc = effects[i]->descriptor();
+        if (i < *count) {
+            memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+        }
+    }
+    if (effects.size() > *count) {
+        status = NO_MEMORY;
+    }
+    *count = effects.size();
+    return status;
+}
+
 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
     LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
             IPCThreadState::self()->getCallingPid());
@@ -492,6 +611,15 @@
     return NO_ERROR;
 }
 
+void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled)
+{
+    Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects;
+    for (size_t i = 0; i < fxVector.size(); i++) {
+        sp<AudioEffect> fx = fxVector.itemAt(i);
+        fx->setEnabled(enabled);
+    }
+}
+
 status_t AudioPolicyService::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
@@ -921,6 +1049,300 @@
     return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
 }
 
+// ----------------------------------------------------------------------------
+// Audio pre-processing configuration
+// ----------------------------------------------------------------------------
+
+const char *AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
+    MIC_SRC_TAG,
+    VOICE_UL_SRC_TAG,
+    VOICE_DL_SRC_TAG,
+    VOICE_CALL_SRC_TAG,
+    CAMCORDER_SRC_TAG,
+    VOICE_REC_SRC_TAG,
+    VOICE_COMM_SRC_TAG
+};
+
+// returns the audio_source_t enum corresponding to the input source name or
+// AUDIO_SOURCE_CNT is no match found
+audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
+{
+    int i;
+    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
+        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
+            LOGV("inputSourceNameToEnum found source %s %d", name, i);
+            break;
+        }
+    }
+    return (audio_source_t)i;
+}
+
+size_t AudioPolicyService::growParamSize(char *param,
+                                         size_t size,
+                                         size_t *curSize,
+                                         size_t *totSize)
+{
+    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
+    size_t pos = ((*curSize - 1 ) / size + 1) * size;
+
+    if (pos + size > *totSize) {
+        while (pos + size > *totSize) {
+            *totSize += ((*totSize + 7) / 8) * 4;
+        }
+        param = (char *)realloc(param, *totSize);
+    }
+    *curSize = pos + size;
+    return pos;
+}
+
+size_t AudioPolicyService::readParamValue(cnode *node,
+                                          char *param,
+                                          size_t *curSize,
+                                          size_t *totSize)
+{
+    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
+        *(short *)((char *)param + pos) = (short)atoi(node->value);
+        LOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
+        return sizeof(short);
+    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
+        *(int *)((char *)param + pos) = atoi(node->value);
+        LOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
+        return sizeof(int);
+    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
+        *(float *)((char *)param + pos) = (float)atof(node->value);
+        LOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
+        return sizeof(float);
+    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
+        if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
+            *(bool *)((char *)param + pos) = false;
+        } else {
+            *(bool *)((char *)param + pos) = true;
+        }
+        LOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
+        return sizeof(bool);
+    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
+        size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
+        if (*curSize + len + 1 > *totSize) {
+            *totSize = *curSize + len + 1;
+            param = (char *)realloc(param, *totSize);
+        }
+        strncpy(param + *curSize, node->value, len);
+        *curSize += len;
+        param[*curSize] = '\0';
+        LOGV("readParamValue() reading string %s", param + *curSize - len);
+        return len;
+    }
+    LOGW("readParamValue() unknown param type %s", node->name);
+    return 0;
+}
+
+effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
+{
+    cnode *param;
+    cnode *value;
+    size_t curSize = sizeof(effect_param_t);
+    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
+    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
+
+    param = config_find(root, PARAM_TAG);
+    value = config_find(root, VALUE_TAG);
+    if (param == NULL && value == NULL) {
+        // try to parse simple parameter form {int int}
+        param = root->first_child;
+        if (param) {
+            // Note: that a pair of random strings is read as 0 0
+            int *ptr = (int *)fx_param->data;
+            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
+            LOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
+            *ptr++ = atoi(param->name);
+            *ptr = atoi(param->value);
+            fx_param->psize = sizeof(int);
+            fx_param->vsize = sizeof(int);
+            return fx_param;
+        }
+    }
+    if (param == NULL || value == NULL) {
+        LOGW("loadEffectParameter() invalid parameter description %s", root->name);
+        goto error;
+    }
+
+    fx_param->psize = 0;
+    param = param->first_child;
+    while (param) {
+        LOGV("loadEffectParameter() reading param of type %s", param->name);
+        size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
+        if (size == 0) {
+            goto error;
+        }
+        fx_param->psize += size;
+        param = param->next;
+    }
+
+    // align start of value field on 32 bit boundary
+    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
+
+    fx_param->vsize = 0;
+    value = value->first_child;
+    while (value) {
+        LOGV("loadEffectParameter() reading value of type %s", value->name);
+        size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
+        if (size == 0) {
+            goto error;
+        }
+        fx_param->vsize += size;
+        value = value->next;
+    }
+
+    return fx_param;
+
+error:
+    delete fx_param;
+    return NULL;
+}
+
+void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
+{
+    cnode *node = root->first_child;
+    while (node) {
+        LOGV("loadEffectParameters() loading param %s", node->name);
+        effect_param_t *param = loadEffectParameter(node);
+        if (param == NULL) {
+            node = node->next;
+            continue;
+        }
+        params.add(param);
+        node = node->next;
+    }
+}
+
+AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
+                                                            cnode *root,
+                                                            const Vector <EffectDesc *>& effects)
+{
+    cnode *node = root->first_child;
+    if (node == NULL) {
+        LOGW("loadInputSource() empty element %s", root->name);
+        return NULL;
+    }
+    InputSourceDesc *source = new InputSourceDesc();
+    while (node) {
+        size_t i;
+        for (i = 0; i < effects.size(); i++) {
+            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
+                LOGV("loadInputSource() found effect %s in list", node->name);
+                break;
+            }
+        }
+        if (i == effects.size()) {
+            LOGV("loadInputSource() effect %s not in list", node->name);
+            node = node->next;
+            continue;
+        }
+        EffectDesc *effect = new EffectDesc(*effects[i]);
+        loadEffectParameters(node, effect->mParams);
+        LOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
+        source->mEffects.add(effect);
+        node = node->next;
+    }
+    if (source->mEffects.size() == 0) {
+        LOGW("loadInputSource() no valid effects found in source %s", root->name);
+        delete source;
+        return NULL;
+    }
+    return source;
+}
+
+status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
+{
+    cnode *node = config_find(root, PREPROCESSING_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        audio_source_t source = inputSourceNameToEnum(node->name);
+        if (source == AUDIO_SOURCE_CNT) {
+            LOGW("loadInputSources() invalid input source %s", node->name);
+            node = node->next;
+            continue;
+        }
+        LOGV("loadInputSources() loading input source %s", node->name);
+        InputSourceDesc *desc = loadInputSource(node, effects);
+        if (desc == NULL) {
+            node = node->next;
+            continue;
+        }
+        mInputSources.add(source, desc);
+        node = node->next;
+    }
+    return NO_ERROR;
+}
+
+AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
+{
+    cnode *node = config_find(root, UUID_TAG);
+    if (node == NULL) {
+        return NULL;
+    }
+    effect_uuid_t uuid;
+    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
+        LOGW("loadEffect() invalid uuid %s", node->value);
+        return NULL;
+    }
+    EffectDesc *effect = new EffectDesc();
+    effect->mName = strdup(root->name);
+    memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t));
+
+    return effect;
+}
+
+status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
+{
+    cnode *node = config_find(root, EFFECTS_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        LOGV("loadEffects() loading effect %s", node->name);
+        EffectDesc *effect = loadEffect(node);
+        if (effect == NULL) {
+            node = node->next;
+            continue;
+        }
+        effects.add(effect);
+        node = node->next;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
+{
+    cnode *root;
+    char *data;
+
+    data = (char *)load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+
+    Vector <EffectDesc *> effects;
+    loadEffects(root, effects);
+    loadInputSources(root, effects);
+
+    config_free(root);
+    free(root);
+    free(data);
+
+    return NO_ERROR;
+}
+
 /* implementation of the interface to the policy manager */
 extern "C" {
 
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index b830120..834b794 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -17,14 +17,17 @@
 #ifndef ANDROID_AUDIOPOLICYSERVICE_H
 #define ANDROID_AUDIOPOLICYSERVICE_H
 
-#include <media/IAudioPolicyService.h>
-#include <media/ToneGenerator.h>
+#include <cutils/misc.h>
+#include <cutils/config_utils.h>
 #include <utils/Vector.h>
+#include <utils/SortedVector.h>
 #include <binder/BinderService.h>
-
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
+#include <media/IAudioPolicyService.h>
+#include <media/ToneGenerator.h>
+#include <media/AudioEffect.h>
 
 namespace android {
 
@@ -78,7 +81,8 @@
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = 0,
                                     audio_in_acoustics_t acoustics =
-                                            (audio_in_acoustics_t)0);
+                                            (audio_in_acoustics_t)0,
+                                    int audioSession = 0);
     virtual status_t startInput(audio_io_handle_t input);
     virtual status_t stopInput(audio_io_handle_t input);
     virtual void releaseInput(audio_io_handle_t input);
@@ -93,13 +97,16 @@
 
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id);
     virtual status_t unregisterEffect(int id);
     virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
 
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count);
     virtual     status_t    onTransact(
                                 uint32_t code,
                                 const Parcel& data,
@@ -218,6 +225,51 @@
         String8 mName;                      // string used by wake lock fo delayed commands
     };
 
+    class EffectDesc {
+    public:
+        EffectDesc() {}
+        virtual ~EffectDesc() {}
+        char *mName;
+        effect_uuid_t mUuid;
+        Vector <effect_param_t *> mParams;
+    };
+
+    class InputSourceDesc {
+    public:
+        InputSourceDesc() {}
+        virtual ~InputSourceDesc() {}
+        Vector <EffectDesc *> mEffects;
+    };
+
+
+    class InputDesc {
+    public:
+        InputDesc() {}
+        virtual ~InputDesc() {}
+        int mSessionId;
+        Vector< sp<AudioEffect> >mEffects;
+    };
+
+    static const char *kInputSourceNames[AUDIO_SOURCE_CNT -1];
+
+    void setPreProcessorEnabled(InputDesc *inputDesc, bool enabled);
+    status_t loadPreProcessorConfig(const char *path);
+    status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
+    EffectDesc *loadEffect(cnode *root);
+    status_t loadInputSources(cnode *root, const Vector <EffectDesc *>& effects);
+    audio_source_t inputSourceNameToEnum(const char *name);
+    InputSourceDesc *loadInputSource(cnode *root, const Vector <EffectDesc *>& effects);
+    void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params);
+    effect_param_t *loadEffectParameter(cnode *root);
+    size_t readParamValue(cnode *node,
+                          char *param,
+                          size_t *curSize,
+                          size_t *totSize);
+    size_t growParamSize(char *param,
+                         size_t size,
+                         size_t *curSize,
+                         size_t *totSize);
+
     // Internal dump utilities.
     status_t dumpPermissionDenial(int fd);
 
@@ -226,9 +278,10 @@
                             // device connection state  or routing
     sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
     sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
-
     struct audio_policy_device *mpAudioPolicyDev;
     struct audio_policy *mpAudioPolicy;
+    KeyedVector< audio_source_t, InputSourceDesc* > mInputSources;
+    KeyedVector< audio_io_handle_t, InputDesc* > mInputs;
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a583aad..09e88c43 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -386,7 +386,10 @@
         if (mDevice->ops->get_parameters) {
             char *temp = mDevice->ops->get_parameters(mDevice);
             String8 str_parms(temp);
-            free(temp);
+            if (mDevice->ops->put_parameters)
+                mDevice->ops->put_parameters(mDevice, temp);
+            else
+                free(temp);
             parms.unflatten(str_parms);
         }
         return parms;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9b09983..96b26e7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -458,6 +458,17 @@
     return NO_ERROR;
 }
 
+static void disconnectWindow(const sp<ANativeWindow>& window) {
+    if (window != 0) {
+        status_t result = native_window_disconnect(window.get(),
+                NATIVE_WINDOW_API_CAMERA);
+        if (result != NO_ERROR) {
+            LOGW("native_window_disconnect failed: %s (%d)", strerror(-result),
+                    result);
+        }
+    }
+}
+
 void CameraService::Client::disconnect() {
     int callingPid = getCallingPid();
     LOG1("disconnect E (pid %d)", callingPid);
@@ -489,6 +500,7 @@
 
     // Release the held ANativeWindow resources.
     if (mPreviewWindow != 0) {
+        disconnectWindow(mPreviewWindow);
         mPreviewWindow = 0;
         mHardware->setPreviewWindow(mPreviewWindow);
     }
@@ -502,77 +514,73 @@
 
 // ----------------------------------------------------------------------------
 
-// set the Surface that the preview will use
-status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
-    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
+        const sp<ANativeWindow>& window) {
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
 
-    result = NO_ERROR;
-
     // return if no change in surface.
-    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
     if (binder == mSurface) {
-        return result;
+        return NO_ERROR;
     }
 
-    if (mSurface != 0) {
-        LOG1("clearing old preview surface %p", mSurface.get());
-    }
-    mSurface = binder;
-    mPreviewWindow = surface;
-
-    // If preview has been already started, register preview
-    // buffers now.
-    if (mHardware->previewEnabled()) {
-        if (mPreviewWindow != 0) {
-            native_window_set_buffers_transform(mPreviewWindow.get(),
-                                                mOrientation);
-            result = mHardware->setPreviewWindow(mPreviewWindow);
+    if (window != 0) {
+        result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
+        if (result != NO_ERROR) {
+            LOGE("native_window_connect failed: %s (%d)", strerror(-result),
+                    result);
+            return result;
         }
     }
 
+    // If preview has been already started, register preview buffers now.
+    if (mHardware->previewEnabled()) {
+        if (window != 0) {
+            native_window_set_scaling_mode(window.get(),
+                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+            native_window_set_buffers_transform(window.get(), mOrientation);
+            result = mHardware->setPreviewWindow(window);
+        }
+    }
+
+    if (result == NO_ERROR) {
+        // Everything has succeeded.  Disconnect the old window and remember the
+        // new window.
+        disconnectWindow(mPreviewWindow);
+        mSurface = binder;
+        mPreviewWindow = window;
+    } else {
+        // Something went wrong after we connected to the new window, so
+        // disconnect here.
+        disconnectWindow(window);
+    }
+
     return result;
 }
 
+// set the Surface that the preview will use
+status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
+    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+
+    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
+    sp<ANativeWindow> window(surface);
+    return setPreviewWindow(binder, window);
+}
+
 // set the SurfaceTexture that the preview will use
 status_t CameraService::Client::setPreviewTexture(
         const sp<ISurfaceTexture>& surfaceTexture) {
     LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
             getCallingPid());
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
 
-    // return if no change in surface.
-    // asBinder() is safe on NULL (returns NULL)
-    if (surfaceTexture->asBinder() == mSurface) {
-        return result;
-    }
-
-    if (mSurface != 0) {
-        LOG1("clearing old preview surface %p", mSurface.get());
-    }
-    mSurface = surfaceTexture->asBinder();
+    sp<IBinder> binder;
+    sp<ANativeWindow> window;
     if (surfaceTexture != 0) {
-        mPreviewWindow = new SurfaceTextureClient(surfaceTexture);
-    } else {
-        mPreviewWindow = 0;
+        binder = surfaceTexture->asBinder();
+        window = new SurfaceTextureClient(surfaceTexture);
     }
-
-    // If preview has been already started, set overlay or register preview
-    // buffers now.
-    if (mHardware->previewEnabled()) {
-        // XXX: What if the new preview window is 0?
-        if (mPreviewWindow != 0) {
-            native_window_set_buffers_transform(mPreviewWindow.get(),
-                                                mOrientation);
-            result = mHardware->setPreviewWindow(mPreviewWindow);
-        }
-    }
-
-    return result;
+    return setPreviewWindow(binder, window);
 }
 
 // set the preview callback flag to affect how the received frames from
@@ -637,6 +645,8 @@
     }
 
     if (mPreviewWindow != 0) {
+        native_window_set_scaling_mode(mPreviewWindow.get(),
+                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
         native_window_set_buffers_transform(mPreviewWindow.get(),
                 mOrientation);
     }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 5e2d571..c5fefb8 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -161,6 +161,10 @@
 
         int                     getOrientation(int orientation, bool mirror);
 
+        status_t                setPreviewWindow(
+                                    const sp<IBinder>& binder,
+                                    const sp<ANativeWindow>& window);
+
         // these are initialized in the constructor.
         sp<CameraService>               mCameraService;  // immutable after constructor
         sp<ICameraClient>               mCameraClient;
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index f86ca47..e390ae20 100644
--- a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -29,7 +29,6 @@
 #include <camera/ICamera.h>
 #include <camera/ICameraClient.h>
 #include <camera/ICameraService.h>
-#include <ui/Overlay.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
@@ -311,8 +310,6 @@
     virtual status_t registerBuffers(const BufferHeap& buffers);
     virtual void postBuffer(ssize_t offset);
     virtual void unregisterBuffers();
-    virtual sp<OverlayRef> createOverlay(
-            uint32_t w, uint32_t h, int32_t format, int32_t orientation);
     virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
     virtual status_t setBufferCount(int bufferCount);
 
@@ -381,13 +378,6 @@
     }
 }
 
-sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
-        int32_t orientation) {
-    // Not implemented.
-    ASSERT(0);
-    return NULL;
-}
-
 //
 //  Utilities to use the Holder service
 //
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index ca2540b..7ea3de2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -460,6 +460,17 @@
     mExcludedDevices = devices;
 }
 
+bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
+        if (test_bit(scanCode, device->keyBitmask)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 695dfdf..293a1a0 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -195,6 +195,7 @@
     virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
             uint8_t* outFlags) const = 0;
 
+    virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
     virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
     virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
 
@@ -246,6 +247,7 @@
 
     virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
 
+    virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
     virtual bool hasLed(int32_t deviceId, int32_t led) const;
     virtual void setLedState(int32_t deviceId, int32_t led, bool on);
 
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
index cc80062..8902f7a 100644
--- a/services/input/InputApplication.h
+++ b/services/input/InputApplication.h
@@ -26,26 +26,32 @@
 namespace android {
 
 /*
- * A handle to an application that can receive input.
- * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * Describes the properties of an application that can receive input.
+ *
+ * Used by the native input dispatcher as a handle for the window manager objects
  * that describe an application.
  */
 class InputApplicationHandle : public RefBase {
+public:
+    String8 name;
+    nsecs_t dispatchingTimeout;
+
+    /**
+     * Requests that the state of this object be updated to reflect
+     * the most current available information about the application.
+     *
+     * This method should only be called from within the input dispatcher's
+     * critical section.
+     *
+     * Returns true on success, or false if the handle is no longer valid.
+     */
+    virtual bool update() = 0;
+
 protected:
     InputApplicationHandle() { }
     virtual ~InputApplicationHandle() { }
 };
 
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
-    sp<InputApplicationHandle> inputApplicationHandle;
-    String8 name;
-    nsecs_t dispatchingTimeout;
-};
-
 } // namespace android
 
 #endif // _UI_INPUT_APPLICATION_H
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 10b9083..af13945 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -211,21 +211,10 @@
     mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
     mNextUnblockedEvent(NULL),
     mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false),
-    mFocusedWindow(NULL),
-    mFocusedApplication(NULL),
     mCurrentInputTargetsValid(false),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE),
-    mLastHoverWindow(NULL) {
+    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
 
-    mInboundQueue.headSentinel.refCount = -1;
-    mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
-
-    mInboundQueue.tailSentinel.refCount = -1;
-    mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
-
     mKeyRepeatState.lastKeyEntry = NULL;
 
     policy->getDispatcherConfiguration(&mConfig);
@@ -322,7 +311,7 @@
             }
         } else {
             // Inbound queue has at least one entry.
-            EventEntry* entry = mInboundQueue.headSentinel.next;
+            EventEntry* entry = mInboundQueue.head;
 
             // Throttle the entry if it is a move event and there are no
             // other events behind it in the queue.  Due to movement batching, additional
@@ -338,7 +327,7 @@
                 int32_t deviceId = motionEntry->deviceId;
                 uint32_t source = motionEntry->source;
                 if (! isAppSwitchDue
-                        && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
+                        && !motionEntry->next // exactly one event, no successors
                         && (motionEntry->action == AMOTION_EVENT_ACTION_MOVE
                                 || motionEntry->action == AMOTION_EVENT_ACTION_HOVER_MOVE)
                         && deviceId == mThrottleState.lastDeviceId
@@ -501,16 +490,15 @@
         if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
                 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
-                && mInputTargetWaitApplication != NULL) {
+                && mInputTargetWaitApplicationHandle != NULL) {
             int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_X));
             int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_Y));
-            const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
-            if (touchedWindow
-                    && touchedWindow->inputWindowHandle != NULL
-                    && touchedWindow->inputWindowHandle->getInputApplicationHandle()
-                            != mInputTargetWaitApplication) {
+            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            if (touchedWindowHandle != NULL
+                    && touchedWindowHandle->inputApplicationHandle
+                            != mInputTargetWaitApplicationHandle) {
                 // User touched a different application than the one we are waiting on.
                 // Flag the event, and start pruning the input queue.
                 mNextUnblockedEvent = motionEntry;
@@ -524,25 +512,25 @@
     return needWake;
 }
 
-const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
     // Traverse windows from front to back to find touched window.
-    size_t numWindows = mWindows.size();
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* window = & mWindows.editItemAt(i);
-        int32_t flags = window->layoutParamsFlags;
+        sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+        int32_t flags = windowHandle->layoutParamsFlags;
 
-        if (window->visible) {
-            if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                        | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
+        if (windowHandle->visible) {
+            if (!(flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
+                bool isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
+                        | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
+                if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
                     // Found window.
-                    return window;
+                    return windowHandle;
                 }
             }
         }
 
-        if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+        if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
             // Error window is on top but not visible, so touch is dropped.
             return NULL;
         }
@@ -645,13 +633,13 @@
         (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
 
         commandEntry->connection.clear();
-        mAllocator.releaseCommandEntry(commandEntry);
+        delete commandEntry;
     } while (! mCommandQueue.isEmpty());
     return true;
 }
 
 InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
-    CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
+    CommandEntry* commandEntry = new CommandEntry(command);
     mCommandQueue.enqueueAtTail(commandEntry);
     return commandEntry;
 }
@@ -678,12 +666,12 @@
 #endif
         setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
     }
-    mAllocator.releaseEventEntry(entry);
+    entry->release();
 }
 
 void InputDispatcher::resetKeyRepeatLocked() {
     if (mKeyRepeatState.lastKeyEntry) {
-        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
+        mKeyRepeatState.lastKeyEntry->release();
         mKeyRepeatState.lastKeyEntry = NULL;
     }
 }
@@ -695,18 +683,18 @@
     uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
             | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
     if (entry->refCount == 1) {
-        mAllocator.recycleKeyEntry(entry);
+        entry->recycle();
         entry->eventTime = currentTime;
         entry->policyFlags = policyFlags;
         entry->repeatCount += 1;
     } else {
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
+        KeyEntry* newEntry = new KeyEntry(currentTime,
                 entry->deviceId, entry->source, policyFlags,
                 entry->action, entry->flags, entry->keyCode, entry->scanCode,
                 entry->metaState, entry->repeatCount + 1, entry->downTime);
 
         mKeyRepeatState.lastKeyEntry = newEntry;
-        mAllocator.releaseKeyEntry(entry);
+        entry->release();
 
         entry = newEntry;
     }
@@ -781,8 +769,8 @@
         if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             CommandEntry* commandEntry = postCommandLocked(
                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (mFocusedWindow) {
-                commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
+            if (mFocusedWindowHandle != NULL) {
+                commandEntry->inputWindowHandle = mFocusedWindowHandle;
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -891,7 +879,7 @@
             uint32_t originalSampleCount = entry->countSamples();
 #endif
             MotionSample* nextSample = splitBatchAfterSample->next;
-            MotionEntry* nextEntry = mAllocator.obtainMotionEntry(nextSample->eventTime,
+            MotionEntry* nextEntry = new MotionEntry(nextSample->eventTime,
                     entry->deviceId, entry->source, entry->policyFlags,
                     entry->action, entry->flags,
                     entry->metaState, entry->buttonState, entry->edgeFlags,
@@ -901,7 +889,7 @@
                 nextEntry->firstSample.next = nextSample->next;
                 nextEntry->lastSample = entry->lastSample;
             }
-            mAllocator.freeMotionSample(nextSample);
+            delete nextSample;
 
             entry->lastSample = const_cast<MotionSample*>(splitBatchAfterSample);
             entry->lastSample->next = NULL;
@@ -1010,8 +998,7 @@
 void InputDispatcher::resetTargetsLocked() {
     mCurrentInputTargetsValid = false;
     mCurrentInputTargets.clear();
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-    mInputTargetWaitApplication.clear();
+    resetANRTimeoutsLocked();
 }
 
 void InputDispatcher::commitTargetsLocked() {
@@ -1019,9 +1006,11 @@
 }
 
 int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
-        const EventEntry* entry, const InputApplication* application, const InputWindow* window,
+        const EventEntry* entry,
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
         nsecs_t* nextWakeupTime) {
-    if (application == NULL && window == NULL) {
+    if (applicationHandle == NULL && windowHandle == NULL) {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
 #if DEBUG_FOCUS
             LOGD("Waiting for system to become ready for input.");
@@ -1030,29 +1019,29 @@
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
             mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplication.clear();
+            mInputTargetWaitApplicationHandle.clear();
         }
     } else {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
 #if DEBUG_FOCUS
             LOGD("Waiting for application to become ready for input: %s",
-                    getApplicationWindowLabelLocked(application, window).string());
+                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
 #endif
-            nsecs_t timeout = window ? window->dispatchingTimeout :
-                application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+            nsecs_t timeout = windowHandle != NULL ? windowHandle->dispatchingTimeout :
+                applicationHandle != NULL ?
+                        applicationHandle->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
 
             mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = currentTime + timeout;
             mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplication.clear();
+            mInputTargetWaitApplicationHandle.clear();
 
-            if (window && window->inputWindowHandle != NULL) {
-                mInputTargetWaitApplication =
-                        window->inputWindowHandle->getInputApplicationHandle();
+            if (windowHandle != NULL) {
+                mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
             }
-            if (mInputTargetWaitApplication == NULL && application) {
-                mInputTargetWaitApplication = application->inputApplicationHandle;
+            if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
+                mInputTargetWaitApplicationHandle = applicationHandle;
             }
         }
     }
@@ -1062,7 +1051,8 @@
     }
 
     if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
+        onANRLocked(currentTime, applicationHandle, windowHandle,
+                entry->eventTime, mInputTargetWaitStartTime);
 
         // Force poll loop to wake up immediately on next iteration once we get the
         // ANR response back from the policy.
@@ -1119,6 +1109,7 @@
 
     // Reset input target wait timeout.
     mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+    mInputTargetWaitApplicationHandle.clear();
 }
 
 int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
@@ -1129,15 +1120,15 @@
 
     // If there is no currently focused window and no focused application
     // then drop the event.
-    if (! mFocusedWindow) {
-        if (mFocusedApplication) {
+    if (mFocusedWindowHandle == NULL) {
+        if (mFocusedApplicationHandle != NULL) {
 #if DEBUG_FOCUS
             LOGD("Waiting because there is no focused window but there is a "
                     "focused application that may eventually add a window: %s.",
-                    getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+                    getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
 #endif
             injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplication, NULL, nextWakeupTime);
+                    mFocusedApplicationHandle, NULL, nextWakeupTime);
             goto Unresponsive;
         }
 
@@ -1147,34 +1138,34 @@
     }
 
     // Check permissions.
-    if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
+    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
         injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
         goto Failed;
     }
 
     // If the currently focused window is paused then keep waiting.
-    if (mFocusedWindow->paused) {
+    if (mFocusedWindowHandle->paused) {
 #if DEBUG_FOCUS
         LOGD("Waiting because focused window is paused.");
 #endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
         goto Unresponsive;
     }
 
     // If the currently focused window is still working on previous events then keep waiting.
-    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
+    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindowHandle)) {
 #if DEBUG_FOCUS
         LOGD("Waiting because focused window still processing previous input.");
 #endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
         goto Unresponsive;
     }
 
     // Success!  Output targets.
     injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(mFocusedWindow,
+    addWindowTargetLocked(mFocusedWindowHandle,
             InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0));
 
     // Done.
@@ -1236,7 +1227,7 @@
     // Update the touch state as needed based on the properties of the touch event.
     int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
     InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-    const InputWindow* newHoverWindow = NULL;
+    sp<InputWindowHandle> newHoverWindowHandle;
 
     bool isSplit = mTouchState.split;
     bool switchedDevice = mTouchState.deviceId >= 0
@@ -1279,42 +1270,44 @@
                 getAxisValue(AMOTION_EVENT_AXIS_X));
         int32_t y = int32_t(sample->pointerCoords[pointerIndex].
                 getAxisValue(AMOTION_EVENT_AXIS_Y));
-        const InputWindow* newTouchedWindow = NULL;
-        const InputWindow* topErrorWindow = NULL;
+        sp<InputWindowHandle> newTouchedWindowHandle;
+        sp<InputWindowHandle> topErrorWindowHandle;
         bool isTouchModal = false;
 
         // Traverse windows from front to back to find touched window and outside targets.
-        size_t numWindows = mWindows.size();
+        size_t numWindows = mWindowHandles.size();
         for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.editItemAt(i);
-            int32_t flags = window->layoutParamsFlags;
+            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+            int32_t flags = windowHandle->layoutParamsFlags;
 
-            if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
-                if (! topErrorWindow) {
-                    topErrorWindow = window;
+            if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
+                if (topErrorWindowHandle == NULL) {
+                    topErrorWindowHandle = windowHandle;
                 }
             }
 
-            if (window->visible) {
-                if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                    isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                            | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                    if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
-                        if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
-                            newTouchedWindow = window;
+            if (windowHandle->visible) {
+                if (! (flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
+                    isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
+                            | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
+                    if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
+                        if (! screenWasOff
+                                || (flags & InputWindowHandle::FLAG_TOUCHABLE_WHEN_WAKING)) {
+                            newTouchedWindowHandle = windowHandle;
                         }
                         break; // found touched window, exit window loop
                     }
                 }
 
                 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-                        && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
+                        && (flags & InputWindowHandle::FLAG_WATCH_OUTSIDE_TOUCH)) {
                     int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
-                    if (isWindowObscuredAtPointLocked(window, x, y)) {
+                    if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
                         outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
                     }
 
-                    mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
+                    mTempTouchState.addOrUpdateWindow(
+                            windowHandle, outsideTargetFlags, BitSet32(0));
                 }
             }
         }
@@ -1322,7 +1315,7 @@
         // If there is an error window but it is not taking focus (typically because
         // it is invisible) then wait for it.  Any other focused window may in
         // fact be in ANR state.
-        if (topErrorWindow && newTouchedWindow != topErrorWindow) {
+        if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
 #if DEBUG_FOCUS
             LOGD("Waiting because system error window is pending.");
 #endif
@@ -1333,26 +1326,26 @@
         }
 
         // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
+        if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->supportsSplitTouch()) {
             // New window supports splitting.
             isSplit = true;
         } else if (isSplit) {
             // New window does not support splitting but we have already split events.
             // Assign the pointer to the first foreground window we find.
             // (May be NULL which is why we put this code block before the next check.)
-            newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+            newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
         }
 
         // If we did not find a touched window then fail.
-        if (! newTouchedWindow) {
-            if (mFocusedApplication) {
+        if (newTouchedWindowHandle == NULL) {
+            if (mFocusedApplicationHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because there is no touched window but there is a "
                         "focused application that may eventually add a new window: %s.",
-                        getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+                        getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        mFocusedApplication, NULL, nextWakeupTime);
+                        mFocusedApplicationHandle, NULL, nextWakeupTime);
                 goto Unresponsive;
             }
 
@@ -1366,20 +1359,20 @@
         if (isSplit) {
             targetFlags |= InputTarget::FLAG_SPLIT;
         }
-        if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+        if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
             targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
         }
 
         // Update hover state.
         if (isHoverAction) {
-            newHoverWindow = newTouchedWindow;
+            newHoverWindowHandle = newTouchedWindowHandle;
 
             // Ensure all subsequent motion samples are also within the touched window.
             // Set *outSplitBatchAfterSample to the sample before the first one that is not
             // within the touched window.
             if (!isTouchModal) {
                 while (sample->next) {
-                    if (!newHoverWindow->touchableRegionContainsPoint(
+                    if (!newHoverWindowHandle->touchableRegionContainsPoint(
                             sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
                             sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y))) {
                         *outSplitBatchAfterSample = sample;
@@ -1389,7 +1382,7 @@
                 }
             }
         } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
-            newHoverWindow = mLastHoverWindow;
+            newHoverWindowHandle = mLastHoverWindowHandle;
         }
 
         // Update the temporary touch state.
@@ -1398,7 +1391,7 @@
             uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
             pointerIds.markBit(pointerId);
         }
-        mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+        mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
     } else {
         /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
 
@@ -1420,19 +1413,22 @@
             int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
             int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
 
-            const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow();
-            const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y);
-            if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) {
+            sp<InputWindowHandle> oldTouchedWindowHandle =
+                    mTempTouchState.getFirstForegroundWindowHandle();
+            sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            if (oldTouchedWindowHandle != newTouchedWindowHandle
+                    && newTouchedWindowHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Touch is slipping out of window %s into window %s.",
-                        oldTouchedWindow->name.string(), newTouchedWindow->name.string());
+                        oldTouchedWindowHandle->name.string(),
+                        newTouchedWindowHandle->name.string());
 #endif
                 // Make a slippery exit from the old window.
-                mTempTouchState.addOrUpdateWindow(oldTouchedWindow,
+                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
                         InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
 
                 // Make a slippery entrance into the new window.
-                if (newTouchedWindow->supportsSplitTouch()) {
+                if (newTouchedWindowHandle->supportsSplitTouch()) {
                     isSplit = true;
                 }
 
@@ -1441,7 +1437,7 @@
                 if (isSplit) {
                     targetFlags |= InputTarget::FLAG_SPLIT;
                 }
-                if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+                if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
                     targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
                 }
 
@@ -1449,7 +1445,7 @@
                 if (isSplit) {
                     pointerIds.markBit(entry->pointerProperties[0].id);
                 }
-                mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+                mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
 
                 // Split the batch here so we send exactly one sample.
                 *outSplitBatchAfterSample = &entry->firstSample;
@@ -1457,25 +1453,25 @@
         }
     }
 
-    if (newHoverWindow != mLastHoverWindow) {
+    if (newHoverWindowHandle != mLastHoverWindowHandle) {
         // Split the batch here so we send exactly one sample as part of ENTER or EXIT.
         *outSplitBatchAfterSample = &entry->firstSample;
 
         // Let the previous window know that the hover sequence is over.
-        if (mLastHoverWindow) {
+        if (mLastHoverWindowHandle != NULL) {
 #if DEBUG_HOVER
-            LOGD("Sending hover exit event to window %s.", mLastHoverWindow->name.string());
+            LOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->name.string());
 #endif
-            mTempTouchState.addOrUpdateWindow(mLastHoverWindow,
+            mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
                     InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
         }
 
         // Let the new window know that the hover sequence is starting.
-        if (newHoverWindow) {
+        if (newHoverWindowHandle != NULL) {
 #if DEBUG_HOVER
-            LOGD("Sending hover enter event to window %s.", newHoverWindow->name.string());
+            LOGD("Sending hover enter event to window %s.", newHoverWindowHandle->name.string());
 #endif
-            mTempTouchState.addOrUpdateWindow(newHoverWindow,
+            mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
                     InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
         }
     }
@@ -1488,7 +1484,8 @@
             const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
             if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
                 haveForegroundWindow = true;
-                if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
+                if (! checkInjectionPermission(touchedWindow.windowHandle,
+                        entry->injectionState)) {
                     injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
                     injectionPermission = INJECTION_PERMISSION_DENIED;
                     goto Failed;
@@ -1510,14 +1507,15 @@
     // Check whether windows listening for outside touches are owned by the same UID. If it is
     // set the policy flag that we will not reveal coordinate information to this window.
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        const int32_t foregroundWindowUid = foregroundWindow->ownerUid;
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        const int32_t foregroundWindowUid = foregroundWindowHandle->ownerUid;
         for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
             const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
             if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-                const InputWindow* inputWindow = touchedWindow.window;
-                if (inputWindow->ownerUid != foregroundWindowUid) {
-                    mTempTouchState.addOrUpdateWindow(inputWindow,
+                sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
+                if (inputWindowHandle->ownerUid != foregroundWindowUid) {
+                    mTempTouchState.addOrUpdateWindow(inputWindowHandle,
                             InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
                 }
             }
@@ -1529,22 +1527,22 @@
         const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
         if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
             // If the touched window is paused then keep waiting.
-            if (touchedWindow.window->paused) {
+            if (touchedWindow.windowHandle->paused) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because touched window is paused.");
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime);
                 goto Unresponsive;
             }
 
             // If the touched window is still working on previous events then keep waiting.
-            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
+            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because touched window still processing previous input.");
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime);
                 goto Unresponsive;
             }
         }
@@ -1557,12 +1555,13 @@
     // engine only supports touch events.  We would need to add a mechanism similar
     // to View.onGenericMotionEvent to enable wallpapers to handle these events.
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        if (foregroundWindow->hasWallpaper) {
-            for (size_t i = 0; i < mWindows.size(); i++) {
-                const InputWindow* window = & mWindows[i];
-                if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
-                    mTempTouchState.addOrUpdateWindow(window,
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        if (foregroundWindowHandle->hasWallpaper) {
+            for (size_t i = 0; i < mWindowHandles.size(); i++) {
+                sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+                if (windowHandle->layoutParamsType == InputWindowHandle::TYPE_WALLPAPER) {
+                    mTempTouchState.addOrUpdateWindow(windowHandle,
                             InputTarget::FLAG_WINDOW_IS_OBSCURED
                                     | InputTarget::FLAG_DISPATCH_AS_IS,
                             BitSet32(0));
@@ -1576,7 +1575,7 @@
 
     for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
         const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
-        addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
+        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                 touchedWindow.pointerIds);
     }
 
@@ -1658,7 +1657,7 @@
             }
 
             // Update hover state.
-            mLastHoverWindow = newHoverWindow;
+            mLastHoverWindowHandle = newHoverWindowHandle;
         }
     } else {
 #if DEBUG_FOCUS
@@ -1681,16 +1680,16 @@
     return injectionResult;
 }
 
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-        BitSet32 pointerIds) {
+void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+        int32_t targetFlags, BitSet32 pointerIds) {
     mCurrentInputTargets.push();
 
     InputTarget& target = mCurrentInputTargets.editTop();
-    target.inputChannel = window->inputChannel;
+    target.inputChannel = windowHandle->inputChannel;
     target.flags = targetFlags;
-    target.xOffset = - window->frameLeft;
-    target.yOffset = - window->frameTop;
-    target.scaleFactor = window->scaleFactor;
+    target.xOffset = - windowHandle->frameLeft;
+    target.yOffset = - windowHandle->frameTop;
+    target.scaleFactor = windowHandle->scaleFactor;
     target.pointerIds = pointerIds;
 }
 
@@ -1708,17 +1707,17 @@
     }
 }
 
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
+bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
         const InjectionState* injectionState) {
     if (injectionState
-            && (window == NULL || window->ownerUid != injectionState->injectorUid)
+            && (windowHandle == NULL || windowHandle->ownerUid != injectionState->injectorUid)
             && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
-        if (window) {
-            LOGW("Permission denied: injecting event from pid %d uid %d to window "
-                    "with input channel %s owned by uid %d",
+        if (windowHandle != NULL) {
+            LOGW("Permission denied: injecting event from pid %d uid %d to window %s "
+                    "owned by uid %d",
                     injectionState->injectorPid, injectionState->injectorUid,
-                    window->inputChannel->getName().string(),
-                    window->ownerUid);
+                    windowHandle->name.string(),
+                    windowHandle->ownerUid);
         } else {
             LOGW("Permission denied: injecting event from pid %d uid %d",
                     injectionState->injectorPid, injectionState->injectorUid);
@@ -1729,22 +1728,24 @@
 }
 
 bool InputDispatcher::isWindowObscuredAtPointLocked(
-        const InputWindow* window, int32_t x, int32_t y) const {
-    size_t numWindows = mWindows.size();
+        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* other = & mWindows.itemAt(i);
-        if (other == window) {
+        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+        if (otherHandle == windowHandle) {
             break;
         }
-        if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
+        if (otherHandle->visible && ! otherHandle->isTrustedOverlay()
+                && otherHandle->frameContainsPoint(x, y)) {
             return true;
         }
     }
     return false;
 }
 
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
-    ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
+bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(
+        const sp<InputWindowHandle>& windowHandle) {
+    ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->inputChannel);
     if (connectionIndex >= 0) {
         sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
         return connection->outboundQueue.isEmpty();
@@ -1753,19 +1754,20 @@
     }
 }
 
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
-        const InputWindow* window) {
-    if (application) {
-        if (window) {
-            String8 label(application->name);
+String8 InputDispatcher::getApplicationWindowLabelLocked(
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle) {
+    if (applicationHandle != NULL) {
+        if (windowHandle != NULL) {
+            String8 label(applicationHandle->name);
             label.append(" - ");
-            label.append(window->name);
+            label.append(windowHandle->name);
             return label;
         } else {
-            return application->name;
+            return applicationHandle->name;
         }
-    } else if (window) {
-        return window->name;
+    } else if (windowHandle != NULL) {
+        return windowHandle->name;
     } else {
         return String8("<unknown application or window>");
     }
@@ -1982,7 +1984,7 @@
 
     // This is a new event.
     // Enqueue a new dispatch entry onto the outbound queue for this connection.
-    DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
+    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
             inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
             inputTarget->scaleFactor);
     if (dispatchEntry->hasForegroundTarget()) {
@@ -2077,7 +2079,7 @@
     LOG_ASSERT(connection->status == Connection::STATUS_NORMAL);
     LOG_ASSERT(! connection->outboundQueue.isEmpty());
 
-    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+    DispatchEntry* dispatchEntry = connection->outboundQueue.head;
     LOG_ASSERT(! dispatchEntry->inProgress);
 
     // Mark the dispatch entry as in progress.
@@ -2266,7 +2268,7 @@
         const sp<Connection>& connection) {
     // Start the next dispatch cycle for this connection.
     while (! connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
         if (dispatchEntry->inProgress) {
              // Finish or resume current event in progress.
             if (dispatchEntry->tailMotionSample) {
@@ -2283,7 +2285,7 @@
             if (dispatchEntry->hasForegroundTarget()) {
                 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
             }
-            mAllocator.releaseDispatchEntry(dispatchEntry);
+            delete dispatchEntry;
         } else {
             // If the head is not in progress, then we must have already dequeued the in
             // progress event, which means we actually aborted it.
@@ -2323,7 +2325,7 @@
         if (dispatchEntry->hasForegroundTarget()) {
             decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
         }
-        mAllocator.releaseDispatchEntry(dispatchEntry);
+        delete dispatchEntry;
     }
 
     deactivateConnectionLocked(connection);
@@ -2397,7 +2399,7 @@
     nsecs_t currentTime = now();
 
     mTempCancelationEvents.clear();
-    connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
+    connection->inputState.synthesizeCancelationEvents(currentTime,
             mTempCancelationEvents, options);
 
     if (! mTempCancelationEvents.isEmpty()
@@ -2422,11 +2424,11 @@
             }
 
             InputTarget target;
-            const InputWindow* window = getWindowLocked(connection->inputChannel);
-            if (window) {
-                target.xOffset = -window->frameLeft;
-                target.yOffset = -window->frameTop;
-                target.scaleFactor = window->scaleFactor;
+            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
+            if (windowHandle != NULL) {
+                target.xOffset = -windowHandle->frameLeft;
+                target.yOffset = -windowHandle->frameTop;
+                target.scaleFactor = windowHandle->scaleFactor;
             } else {
                 target.xOffset = 0;
                 target.yOffset = 0;
@@ -2438,10 +2440,10 @@
             enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
                     &target, false, InputTarget::FLAG_DISPATCH_AS_IS);
 
-            mAllocator.releaseEventEntry(cancelationEventEntry);
+            cancelationEventEntry->release();
         }
 
-        if (!connection->outboundQueue.headSentinel.next->inProgress) {
+        if (!connection->outboundQueue.head->inProgress) {
             startDispatchCycleLocked(currentTime, connection);
         }
     }
@@ -2513,7 +2515,7 @@
         }
     }
 
-    MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
+    MotionEntry* splitMotionEntry = new MotionEntry(
             originalMotionEntry->eventTime,
             originalMotionEntry->deviceId,
             originalMotionEntry->source,
@@ -2537,8 +2539,7 @@
                     originalMotionSample->pointerCoords[originalPointerIndex]);
         }
 
-        mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
-                splitPointerCoords);
+        splitMotionEntry->appendSample(originalMotionSample->eventTime, splitPointerCoords);
     }
 
     if (originalMotionEntry->injectionState) {
@@ -2558,7 +2559,7 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
+        ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(eventTime);
         needWake = enqueueInboundEventLocked(newEntry);
     } // release lock
 
@@ -2628,7 +2629,7 @@
         }
 
         int32_t repeatCount = 0;
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
+        KeyEntry* newEntry = new KeyEntry(eventTime,
                 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
                 metaState, repeatCount, downTime);
 
@@ -2708,8 +2709,7 @@
             // Try to append a move sample to the tail of the inbound queue for this device.
             // Give up if we encounter a non-move motion event for this device since that
             // means we cannot append any new samples until a new motion event has started.
-            for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
-                    entry != & mInboundQueue.headSentinel; entry = entry->prev) {
+            for (EventEntry* entry = mInboundQueue.tail; entry; entry = entry->prev) {
                 if (entry->type != EventEntry::TYPE_MOTION) {
                     // Keep looking for motion events.
                     continue;
@@ -2788,7 +2788,7 @@
                         continue;
                     }
 
-                    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+                    DispatchEntry* dispatchEntry = connection->outboundQueue.head;
                     if (! dispatchEntry->inProgress
                             || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
                             || dispatchEntry->isSplit()) {
@@ -2809,7 +2809,7 @@
                     }
 
                     if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-                        if (!mLastHoverWindow) {
+                        if (mLastHoverWindowHandle == NULL) {
 #if DEBUG_BATCHING
                             LOGD("Not streaming hover move because there is no "
                                     "last hovered window.");
@@ -2817,15 +2817,16 @@
                             goto NoBatchingOrStreaming;
                         }
 
-                        const InputWindow* hoverWindow = findTouchedWindowAtLocked(
+                        sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(
                                 pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
                                 pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
-                        if (mLastHoverWindow != hoverWindow) {
+                        if (mLastHoverWindowHandle != hoverWindowHandle) {
 #if DEBUG_BATCHING
                             LOGD("Not streaming hover move because the last hovered window "
                                     "is '%s' but the currently hovered window is '%s'.",
-                                    mLastHoverWindow->name.string(),
-                                    hoverWindow ? hoverWindow->name.string() : "<null>");
+                                    mLastHoverWindowHandle->name.string(),
+                                    hoverWindowHandle != NULL
+                                            ? hoverWindowHandle->name.string() : "<null>");
 #endif
                             goto NoBatchingOrStreaming;
                         }
@@ -2833,7 +2834,7 @@
 
                     // Hurray!  This foreground target is currently dispatching a move event
                     // that we can stream onto.  Append the motion sample and resume dispatch.
-                    mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
+                    motionEntry->appendSample(eventTime, pointerCoords);
 #if DEBUG_BATCHING
                     LOGD("Appended motion sample onto batch for most recently dispatched "
                             "motion event for this device and source in the outbound queues.  "
@@ -2853,7 +2854,7 @@
         }
 
         // Just enqueue a new motion event.
-        MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
+        MotionEntry* newEntry = new MotionEntry(eventTime,
                 deviceId, source, policyFlags, action, flags, metaState, buttonState, edgeFlags,
                 xPrecision, yPrecision, downTime,
                 pointerCount, pointerProperties, pointerCoords);
@@ -2890,7 +2891,7 @@
     }
 
     // Append the sample.
-    mAllocator.appendMotionSample(entry, eventTime, pointerCoords);
+    entry->appendSample(eventTime, pointerCoords);
 #if DEBUG_BATCHING
     LOGD("Appended motion sample onto batch for %s, events were %0.3f ms apart",
             eventDescription, interval * 0.000001f);
@@ -2947,7 +2948,7 @@
         }
 
         mLock.lock();
-        injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
+        injectedEntry = new KeyEntry(keyEvent->getEventTime(),
                 keyEvent->getDeviceId(), keyEvent->getSource(),
                 policyFlags, action, flags,
                 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
@@ -2972,7 +2973,7 @@
         mLock.lock();
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
         const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
+        MotionEntry* motionEntry = new MotionEntry(*sampleEventTimes,
                 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
                 action, motionEvent->getFlags(),
                 motionEvent->getMetaState(), motionEvent->getButtonState(),
@@ -2983,7 +2984,7 @@
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
             samplePointerCoords += pointerCount;
-            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
+            motionEntry->appendSample(*sampleEventTimes, samplePointerCoords);
         }
         injectedEntry = motionEntry;
         break;
@@ -2994,7 +2995,7 @@
         return INPUT_EVENT_INJECTION_FAILED;
     }
 
-    InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
+    InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
     if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
         injectionState->injectionIsAsync = true;
     }
@@ -3057,7 +3058,7 @@
             }
         }
 
-        mAllocator.releaseInjectionState(injectionState);
+        injectionState->release();
     } // release lock
 
 #if DEBUG_INJECTION
@@ -3125,113 +3126,115 @@
     }
 }
 
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
-    for (size_t i = 0; i < mWindows.size(); i++) {
-        const InputWindow* window = & mWindows[i];
-        if (window->inputChannel == inputChannel) {
-            return window;
+sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
+        const sp<InputChannel>& inputChannel) const {
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+        if (windowHandle->inputChannel == inputChannel) {
+            return windowHandle;
         }
     }
     return NULL;
 }
 
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
+bool InputDispatcher::hasWindowHandleLocked(
+        const sp<InputWindowHandle>& windowHandle) const {
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        if (mWindowHandles.itemAt(i) == windowHandle) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
 #if DEBUG_FOCUS
     LOGD("setInputWindows");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
-        // Clear old window pointers.
-        sp<InputChannel> oldFocusedWindowChannel;
-        if (mFocusedWindow) {
-            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
-            mFocusedWindow = NULL;
-        }
-        sp<InputChannel> oldLastHoverWindowChannel;
-        if (mLastHoverWindow) {
-            oldLastHoverWindowChannel = mLastHoverWindow->inputChannel;
-            mLastHoverWindow = NULL;
-        }
+        mWindowHandles = inputWindowHandles;
 
-        mWindows.clear();
-
-        // Loop over new windows and rebuild the necessary window pointers for
-        // tracking focus and touch.
-        mWindows.appendVector(inputWindows);
-
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.itemAt(i);
-            if (window->hasFocus) {
-                mFocusedWindow = window;
-                break;
+        sp<InputWindowHandle> newFocusedWindowHandle;
+        bool foundHoveredWindow = false;
+        for (size_t i = 0; i < mWindowHandles.size(); i++) {
+            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+            if (!windowHandle->update() || windowHandle->inputChannel == NULL) {
+                mWindowHandles.removeAt(i--);
+                continue;
+            }
+            if (windowHandle->hasFocus) {
+                newFocusedWindowHandle = windowHandle;
+            }
+            if (windowHandle == mLastHoverWindowHandle) {
+                foundHoveredWindow = true;
             }
         }
 
-        if (oldFocusedWindowChannel != NULL) {
-            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
+        if (!foundHoveredWindow) {
+            mLastHoverWindowHandle = NULL;
+        }
+
+        if (mFocusedWindowHandle != newFocusedWindowHandle) {
+            if (mFocusedWindowHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Focus left window: %s",
-                        oldFocusedWindowChannel->getName().string());
+                        mFocusedWindowHandle->name.string());
 #endif
                 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                         "focus left window");
-                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel, options);
-                oldFocusedWindowChannel.clear();
+                synthesizeCancelationEventsForInputChannelLocked(
+                        mFocusedWindowHandle->inputChannel, options);
             }
-        }
-        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
+            if (newFocusedWindowHandle != NULL) {
 #if DEBUG_FOCUS
-            LOGD("Focus entered window: %s",
-                    mFocusedWindow->inputChannel->getName().string());
+                LOGD("Focus entered window: %s",
+                        newFocusedWindowHandle->name.string());
 #endif
+            }
+            mFocusedWindowHandle = newFocusedWindowHandle;
         }
 
-        for (size_t i = 0; i < mTouchState.windows.size(); ) {
+        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
-            const InputWindow* window = getWindowLocked(touchedWindow.channel);
-            if (window) {
-                touchedWindow.window = window;
-                i += 1;
-            } else {
+            if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
-                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
+                LOGD("Touched window was removed: %s", touchedWindow.windowHandle->name.string());
 #endif
                 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                         "touched window was removed");
-                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel, options);
-                mTouchState.windows.removeAt(i);
+                synthesizeCancelationEventsForInputChannelLocked(
+                        touchedWindow.windowHandle->inputChannel, options);
+                mTouchState.windows.removeAt(i--);
             }
         }
-
-        // Recover the last hovered window.
-        if (oldLastHoverWindowChannel != NULL) {
-            mLastHoverWindow = getWindowLocked(oldLastHoverWindowChannel);
-            oldLastHoverWindowChannel.clear();
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
     } // release lock
 
     // Wake up poll loop since it may need to make new input dispatching choices.
     mLooper->wake();
 }
 
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
+void InputDispatcher::setFocusedApplication(
+        const sp<InputApplicationHandle>& inputApplicationHandle) {
 #if DEBUG_FOCUS
     LOGD("setFocusedApplication");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
-        releaseFocusedApplicationLocked();
-
-        if (inputApplication) {
-            mFocusedApplicationStorage = *inputApplication;
-            mFocusedApplication = & mFocusedApplicationStorage;
+        if (inputApplicationHandle != NULL && inputApplicationHandle->update()) {
+            if (mFocusedApplicationHandle != inputApplicationHandle) {
+                if (mFocusedApplicationHandle != NULL) {
+                    resetTargetsLocked();
+                }
+                mFocusedApplicationHandle = inputApplicationHandle;
+            }
+        } else if (mFocusedApplicationHandle != NULL) {
+            resetTargetsLocked();
+            mFocusedApplicationHandle.clear();
         }
 
 #if DEBUG_FOCUS
@@ -3243,13 +3246,6 @@
     mLooper->wake();
 }
 
-void InputDispatcher::releaseFocusedApplicationLocked() {
-    if (mFocusedApplication) {
-        mFocusedApplication = NULL;
-        mFocusedApplicationStorage.inputApplicationHandle.clear();
-    }
-}
-
 void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
 #if DEBUG_FOCUS
     LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3315,15 +3311,15 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        const InputWindow* fromWindow = getWindowLocked(fromChannel);
-        const InputWindow* toWindow = getWindowLocked(toChannel);
-        if (! fromWindow || ! toWindow) {
+        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
+        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
+        if (fromWindowHandle == NULL || toWindowHandle == NULL) {
 #if DEBUG_FOCUS
             LOGD("Cannot transfer focus because from or to window not found.");
 #endif
             return false;
         }
-        if (fromWindow == toWindow) {
+        if (fromWindowHandle == toWindowHandle) {
 #if DEBUG_FOCUS
             LOGD("Trivial transfer to same window.");
 #endif
@@ -3333,7 +3329,7 @@
         bool found = false;
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            if (touchedWindow.window == fromWindow) {
+            if (touchedWindow.windowHandle == fromWindowHandle) {
                 int32_t oldTargetFlags = touchedWindow.targetFlags;
                 BitSet32 pointerIds = touchedWindow.pointerIds;
 
@@ -3342,7 +3338,7 @@
                 int32_t newTargetFlags = oldTargetFlags
                         & (InputTarget::FLAG_FOREGROUND
                                 | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
-                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
+                mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
 
                 found = true;
                 break;
@@ -3392,7 +3388,7 @@
     resetTargetsLocked();
 
     mTouchState.reset();
-    mLastHoverWindow = NULL;
+    mLastHoverWindowHandle.clear();
 }
 
 void InputDispatcher::logDispatchStateLocked() {
@@ -3415,15 +3411,15 @@
     dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
     dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
 
-    if (mFocusedApplication) {
+    if (mFocusedApplicationHandle != NULL) {
         dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
-                mFocusedApplication->name.string(),
-                mFocusedApplication->dispatchingTimeout / 1000000.0);
+                mFocusedApplicationHandle->name.string(),
+                mFocusedApplicationHandle->dispatchingTimeout / 1000000.0);
     } else {
         dump.append(INDENT "FocusedApplication: <null>\n");
     }
     dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
-            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
+            mFocusedWindowHandle != NULL ? mFocusedWindowHandle->name.string() : "<null>");
 
     dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
     dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
@@ -3434,37 +3430,37 @@
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             const TouchedWindow& touchedWindow = mTouchState.windows[i];
             dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
-                    i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
+                    i, touchedWindow.windowHandle->name.string(), touchedWindow.pointerIds.value,
                     touchedWindow.targetFlags);
         }
     } else {
         dump.append(INDENT "TouchedWindows: <none>\n");
     }
 
-    if (!mWindows.isEmpty()) {
+    if (!mWindowHandles.isEmpty()) {
         dump.append(INDENT "Windows:\n");
-        for (size_t i = 0; i < mWindows.size(); i++) {
-            const InputWindow& window = mWindows[i];
+        for (size_t i = 0; i < mWindowHandles.size(); i++) {
+            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
             dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
                     "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                     "frame=[%d,%d][%d,%d], scale=%f, "
                     "touchableRegion=",
-                    i, window.name.string(),
-                    toString(window.paused),
-                    toString(window.hasFocus),
-                    toString(window.hasWallpaper),
-                    toString(window.visible),
-                    toString(window.canReceiveKeys),
-                    window.layoutParamsFlags, window.layoutParamsType,
-                    window.layer,
-                    window.frameLeft, window.frameTop,
-                    window.frameRight, window.frameBottom,
-                    window.scaleFactor);
-            dumpRegion(dump, window.touchableRegion);
-            dump.appendFormat(", inputFeatures=0x%08x", window.inputFeatures);
+                    i, windowHandle->name.string(),
+                    toString(windowHandle->paused),
+                    toString(windowHandle->hasFocus),
+                    toString(windowHandle->hasWallpaper),
+                    toString(windowHandle->visible),
+                    toString(windowHandle->canReceiveKeys),
+                    windowHandle->layoutParamsFlags, windowHandle->layoutParamsType,
+                    windowHandle->layer,
+                    windowHandle->frameLeft, windowHandle->frameTop,
+                    windowHandle->frameRight, windowHandle->frameBottom,
+                    windowHandle->scaleFactor);
+            dumpRegion(dump, windowHandle->touchableRegion);
+            dump.appendFormat(", inputFeatures=0x%08x", windowHandle->inputFeatures);
             dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                    window.ownerPid, window.ownerUid,
-                    window.dispatchingTimeout / 1000000.0);
+                    windowHandle->ownerPid, windowHandle->ownerUid,
+                    windowHandle->dispatchingTimeout / 1000000.0);
         }
     } else {
         dump.append(INDENT "Windows: <none>\n");
@@ -3636,23 +3632,19 @@
 }
 
 void InputDispatcher::onANRLocked(
-        nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+        nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
         nsecs_t eventTime, nsecs_t waitStartTime) {
     LOGI("Application is not responding: %s.  "
             "%01.1fms since event, %01.1fms since wait started",
-            getApplicationWindowLabelLocked(application, window).string(),
+            getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
             (currentTime - eventTime) / 1000000.0,
             (currentTime - waitStartTime) / 1000000.0);
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
-    if (application) {
-        commandEntry->inputApplicationHandle = application->inputApplicationHandle;
-    }
-    if (window) {
-        commandEntry->inputWindowHandle = window->inputWindowHandle;
-        commandEntry->inputChannel = window->inputChannel;
-    }
+    commandEntry->inputApplicationHandle = applicationHandle;
+    commandEntry->inputWindowHandle = windowHandle;
 }
 
 void InputDispatcher::doNotifyConfigurationChangedInterruptible(
@@ -3686,7 +3678,9 @@
 
     mLock.lock();
 
-    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
+    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
+            commandEntry->inputWindowHandle != NULL
+                    ? commandEntry->inputWindowHandle->inputChannel : NULL);
 }
 
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -3706,7 +3700,7 @@
     entry->interceptKeyResult = consumed
             ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
             : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-    mAllocator.releaseKeyEntry(entry);
+    entry->release();
 }
 
 void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
@@ -3716,7 +3710,7 @@
 
     bool skipNext = false;
     if (!connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
         if (dispatchEntry->inProgress) {
             if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
                 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
@@ -3798,7 +3792,7 @@
                 return true; // skip next cycle
             }
 
-            LOG_ASSERT(connection->outboundQueue.headSentinel.next == dispatchEntry);
+            LOG_ASSERT(connection->outboundQueue.head == dispatchEntry);
 
             // Latch the fallback keycode for this key on an initial down.
             // The fallback keycode cannot change at any other point in the lifecycle.
@@ -3931,230 +3925,137 @@
 template <typename T>
 uint32_t InputDispatcher::Queue<T>::count() const {
     uint32_t result = 0;
-    for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
+    for (const T* entry = head; entry; entry = entry->next) {
         result += 1;
     }
     return result;
 }
 
 
-// --- InputDispatcher::Allocator ---
+// --- InputDispatcher::InjectionState ---
 
-InputDispatcher::Allocator::Allocator() {
+InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
+        refCount(1),
+        injectorPid(injectorPid), injectorUid(injectorUid),
+        injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false),
+        pendingForegroundDispatches(0) {
 }
 
-InputDispatcher::InjectionState*
-InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
-    InjectionState* injectionState = mInjectionStatePool.alloc();
-    injectionState->refCount = 1;
-    injectionState->injectorPid = injectorPid;
-    injectionState->injectorUid = injectorUid;
-    injectionState->injectionIsAsync = false;
-    injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    injectionState->pendingForegroundDispatches = 0;
-    return injectionState;
+InputDispatcher::InjectionState::~InjectionState() {
 }
 
-void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
-        nsecs_t eventTime, uint32_t policyFlags) {
-    entry->type = type;
-    entry->refCount = 1;
-    entry->dispatchInProgress = false;
-    entry->eventTime = eventTime;
-    entry->policyFlags = policyFlags;
-    entry->injectionState = NULL;
-}
-
-void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
-    if (entry->injectionState) {
-        releaseInjectionState(entry->injectionState);
-        entry->injectionState = NULL;
+void InputDispatcher::InjectionState::release() {
+    refCount -= 1;
+    if (refCount == 0) {
+        delete this;
+    } else {
+        LOG_ASSERT(refCount > 0);
     }
 }
 
-InputDispatcher::ConfigurationChangedEntry*
-InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
-    ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
-    return entry;
+
+// --- InputDispatcher::EventEntry ---
+
+InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) :
+        refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags),
+        injectionState(NULL), dispatchInProgress(false) {
 }
 
-InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
+InputDispatcher::EventEntry::~EventEntry() {
+    releaseInjectionState();
+}
+
+void InputDispatcher::EventEntry::release() {
+    refCount -= 1;
+    if (refCount == 0) {
+        delete this;
+    } else {
+        LOG_ASSERT(refCount > 0);
+    }
+}
+
+void InputDispatcher::EventEntry::releaseInjectionState() {
+    if (injectionState) {
+        injectionState->release();
+        injectionState = NULL;
+    }
+}
+
+
+// --- InputDispatcher::ConfigurationChangedEntry ---
+
+InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) :
+        EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
+}
+
+InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
+}
+
+
+// --- InputDispatcher::KeyEntry ---
+
+InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
         int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
         int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-        int32_t repeatCount, nsecs_t downTime) {
-    KeyEntry* entry = mKeyEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
-
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->keyCode = keyCode;
-    entry->scanCode = scanCode;
-    entry->metaState = metaState;
-    entry->repeatCount = repeatCount;
-    entry->downTime = downTime;
-    entry->syntheticRepeat = false;
-    entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-    return entry;
+        int32_t repeatCount, nsecs_t downTime) :
+        EventEntry(TYPE_KEY, eventTime, policyFlags),
+        deviceId(deviceId), source(source), action(action), flags(flags),
+        keyCode(keyCode), scanCode(scanCode), metaState(metaState),
+        repeatCount(repeatCount), downTime(downTime),
+        syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
 }
 
-InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
-        int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
-        int32_t metaState, int32_t buttonState,
-        int32_t edgeFlags, float xPrecision, float yPrecision,
-        nsecs_t downTime, uint32_t pointerCount,
-        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
-    MotionEntry* entry = mMotionEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
+InputDispatcher::KeyEntry::~KeyEntry() {
+}
 
-    entry->eventTime = eventTime;
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->metaState = metaState;
-    entry->buttonState = buttonState;
-    entry->edgeFlags = edgeFlags;
-    entry->xPrecision = xPrecision;
-    entry->yPrecision = yPrecision;
-    entry->downTime = downTime;
-    entry->pointerCount = pointerCount;
-    entry->firstSample.eventTime = eventTime;
-    entry->firstSample.eventTimeBeforeCoalescing = eventTime;
-    entry->firstSample.next = NULL;
-    entry->lastSample = & entry->firstSample;
+void InputDispatcher::KeyEntry::recycle() {
+    releaseInjectionState();
+
+    dispatchInProgress = false;
+    syntheticRepeat = false;
+    interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+}
+
+
+// --- InputDispatcher::MotionSample ---
+
+InputDispatcher::MotionSample::MotionSample(nsecs_t eventTime,
+        const PointerCoords* pointerCoords, uint32_t pointerCount) :
+        next(NULL), eventTime(eventTime), eventTimeBeforeCoalescing(eventTime) {
     for (uint32_t i = 0; i < pointerCount; i++) {
-        entry->pointerProperties[i].copyFrom(pointerProperties[i]);
-        entry->firstSample.pointerCoords[i].copyFrom(pointerCoords[i]);
+        this->pointerCoords[i].copyFrom(pointerCoords[i]);
     }
-    return entry;
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
-        EventEntry* eventEntry,
-        int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) {
-    DispatchEntry* entry = mDispatchEntryPool.alloc();
-    entry->eventEntry = eventEntry;
-    eventEntry->refCount += 1;
-    entry->targetFlags = targetFlags;
-    entry->xOffset = xOffset;
-    entry->yOffset = yOffset;
-    entry->scaleFactor = scaleFactor;
-    entry->inProgress = false;
-    entry->headMotionSample = NULL;
-    entry->tailMotionSample = NULL;
-    return entry;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
-    CommandEntry* entry = mCommandEntryPool.alloc();
-    entry->command = command;
-    return entry;
-}
-
-void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
-    injectionState->refCount -= 1;
-    if (injectionState->refCount == 0) {
-        mInjectionStatePool.free(injectionState);
-    } else {
-        LOG_ASSERT(injectionState->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
-    switch (entry->type) {
-    case EventEntry::TYPE_CONFIGURATION_CHANGED:
-        releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
-        break;
-    case EventEntry::TYPE_KEY:
-        releaseKeyEntry(static_cast<KeyEntry*>(entry));
-        break;
-    case EventEntry::TYPE_MOTION:
-        releaseMotionEntry(static_cast<MotionEntry*>(entry));
-        break;
-    default:
-        LOG_ASSERT(false);
-        break;
-    }
-}
-
-void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
-        ConfigurationChangedEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mConfigurationChangeEntryPool.free(entry);
-    } else {
-        LOG_ASSERT(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mKeyEntryPool.free(entry);
-    } else {
-        LOG_ASSERT(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
-            MotionSample* next = sample->next;
-            mMotionSamplePool.free(sample);
-            sample = next;
-        }
-        mMotionEntryPool.free(entry);
-    } else {
-        LOG_ASSERT(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::freeMotionSample(MotionSample* sample) {
-    mMotionSamplePool.free(sample);
-}
-
-void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
-    releaseEventEntry(entry->eventEntry);
-    mDispatchEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
-    mCommandEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
-        nsecs_t eventTime, const PointerCoords* pointerCoords) {
-    MotionSample* sample = mMotionSamplePool.alloc();
-    sample->eventTime = eventTime;
-    sample->eventTimeBeforeCoalescing = eventTime;
-    uint32_t pointerCount = motionEntry->pointerCount;
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        sample->pointerCoords[i].copyFrom(pointerCoords[i]);
-    }
-
-    sample->next = NULL;
-    motionEntry->lastSample->next = sample;
-    motionEntry->lastSample = sample;
-}
-
-void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
-    releaseEventEntryInjectionState(keyEntry);
-
-    keyEntry->dispatchInProgress = false;
-    keyEntry->syntheticRepeat = false;
-    keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
 }
 
 
 // --- InputDispatcher::MotionEntry ---
 
+InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
+        int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
+        int32_t metaState, int32_t buttonState,
+        int32_t edgeFlags, float xPrecision, float yPrecision,
+        nsecs_t downTime, uint32_t pointerCount,
+        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
+        EventEntry(TYPE_MOTION, eventTime, policyFlags),
+        deviceId(deviceId), source(source), action(action), flags(flags),
+        metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
+        xPrecision(xPrecision), yPrecision(yPrecision),
+        downTime(downTime), pointerCount(pointerCount),
+        firstSample(eventTime, pointerCoords, pointerCount),
+        lastSample(&firstSample) {
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        this->pointerProperties[i].copyFrom(pointerProperties[i]);
+    }
+}
+
+InputDispatcher::MotionEntry::~MotionEntry() {
+    for (MotionSample* sample = firstSample.next; sample != NULL; ) {
+        MotionSample* next = sample->next;
+        delete sample;
+        sample = next;
+    }
+}
+
 uint32_t InputDispatcher::MotionEntry::countSamples() const {
     uint32_t count = 1;
     for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
@@ -4178,6 +4079,31 @@
     return true;
 }
 
+void InputDispatcher::MotionEntry::appendSample(
+        nsecs_t eventTime, const PointerCoords* pointerCoords) {
+    MotionSample* sample = new MotionSample(eventTime, pointerCoords, pointerCount);
+
+    lastSample->next = sample;
+    lastSample = sample;
+}
+
+
+// --- InputDispatcher::DispatchEntry ---
+
+InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
+        int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) :
+        eventEntry(eventEntry), targetFlags(targetFlags),
+        xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
+        inProgress(false),
+        resolvedAction(0), resolvedFlags(0),
+        headMotionSample(NULL), tailMotionSample(NULL) {
+    eventEntry->refCount += 1;
+}
+
+InputDispatcher::DispatchEntry::~DispatchEntry() {
+    eventEntry->release();
+}
+
 
 // --- InputDispatcher::InputState ---
 
@@ -4382,12 +4308,11 @@
 }
 
 void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
-        Allocator* allocator, Vector<EventEntry*>& outEvents,
-        const CancelationOptions& options) {
+        Vector<EventEntry*>& outEvents, const CancelationOptions& options) {
     for (size_t i = 0; i < mKeyMementos.size(); i++) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (shouldCancelKey(memento, options)) {
-            outEvents.push(allocator->obtainKeyEntry(currentTime,
+            outEvents.push(new KeyEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
@@ -4397,7 +4322,7 @@
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (shouldCancelMotion(memento, options)) {
-            outEvents.push(allocator->obtainMotionEntry(currentTime,
+            outEvents.push(new MotionEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     memento.hovering
                             ? AMOTION_EVENT_ACTION_HOVER_EXIT
@@ -4518,8 +4443,8 @@
 
 InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
         const EventEntry* eventEntry) const {
-    for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
-            dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
+    for (DispatchEntry* dispatchEntry = outboundQueue.tail; dispatchEntry;
+            dispatchEntry = dispatchEntry->prev) {
         if (dispatchEntry->eventEntry == eventEntry) {
             return dispatchEntry;
         }
@@ -4530,8 +4455,8 @@
 
 // --- InputDispatcher::CommandEntry ---
 
-InputDispatcher::CommandEntry::CommandEntry() :
-    keyEntry(NULL) {
+InputDispatcher::CommandEntry::CommandEntry(Command command) :
+    command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), handled(false) {
 }
 
 InputDispatcher::CommandEntry::~CommandEntry() {
@@ -4560,11 +4485,10 @@
     split = other.split;
     deviceId = other.deviceId;
     source = other.source;
-    windows.clear();
-    windows.appendVector(other.windows);
+    windows = other.windows;
 }
 
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
+void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
         int32_t targetFlags, BitSet32 pointerIds) {
     if (targetFlags & InputTarget::FLAG_SPLIT) {
         split = true;
@@ -4572,7 +4496,7 @@
 
     for (size_t i = 0; i < windows.size(); i++) {
         TouchedWindow& touchedWindow = windows.editItemAt(i);
-        if (touchedWindow.window == window) {
+        if (touchedWindow.windowHandle == windowHandle) {
             touchedWindow.targetFlags |= targetFlags;
             if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
                 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
@@ -4585,10 +4509,9 @@
     windows.push();
 
     TouchedWindow& touchedWindow = windows.editTop();
-    touchedWindow.window = window;
+    touchedWindow.windowHandle = windowHandle;
     touchedWindow.targetFlags = targetFlags;
     touchedWindow.pointerIds = pointerIds;
-    touchedWindow.channel = window->inputChannel;
 }
 
 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
@@ -4605,11 +4528,11 @@
     }
 }
 
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const {
+sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
     for (size_t i = 0; i < windows.size(); i++) {
         const TouchedWindow& window = windows.itemAt(i);
         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return window.window;
+            return window.windowHandle;
         }
     }
     return NULL;
@@ -4621,8 +4544,8 @@
     for (size_t i = 0; i < windows.size(); i++) {
         const TouchedWindow& window = windows.itemAt(i);
         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            if (haveSlipperyForegroundWindow
-                    || !(window.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) {
+            if (haveSlipperyForegroundWindow || !(window.windowHandle->layoutParamsFlags
+                    & InputWindowHandle::FLAG_SLIPPERY)) {
                 return false;
             }
             haveSlipperyForegroundWindow = true;
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index bdd1922..1d39b2e 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -26,7 +26,6 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Looper.h>
-#include <utils/Pool.h>
 #include <utils/BitSet.h>
 
 #include <stddef.h>
@@ -321,13 +320,14 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
 
     /* Sets the focused application.
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
+    virtual void setFocusedApplication(
+            const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
 
     /* Sets the input dispatching mode.
      *
@@ -406,8 +406,8 @@
             int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
             uint32_t policyFlags);
 
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
-    virtual void setFocusedApplication(const InputApplication* inputApplication);
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
+    virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
     virtual void setInputDispatchMode(bool enabled, bool frozen);
     virtual void setInputFilterEnabled(bool enabled);
 
@@ -433,11 +433,16 @@
         int32_t injectionResult;  // initially INPUT_EVENT_INJECTION_PENDING
         bool injectionIsAsync; // set to true if injection is not waiting for the result
         int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
+
+        InjectionState(int32_t injectorPid, int32_t injectorUid);
+        void release();
+
+    private:
+        ~InjectionState();
     };
 
     struct EventEntry : Link<EventEntry> {
         enum {
-            TYPE_SENTINEL,
             TYPE_CONFIGURATION_CHANGED,
             TYPE_KEY,
             TYPE_MOTION
@@ -452,9 +457,20 @@
         bool dispatchInProgress; // initially false, set to true while dispatching
 
         inline bool isInjected() const { return injectionState != NULL; }
+
+        void release();
+
+    protected:
+        EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags);
+        virtual ~EventEntry();
+        void releaseInjectionState();
     };
 
     struct ConfigurationChangedEntry : EventEntry {
+        ConfigurationChangedEntry(nsecs_t eventTime);
+
+    protected:
+        virtual ~ConfigurationChangedEntry();
     };
 
     struct KeyEntry : EventEntry {
@@ -476,6 +492,15 @@
             INTERCEPT_KEY_RESULT_CONTINUE,
         };
         InterceptKeyResult interceptKeyResult; // set based on the interception result
+
+        KeyEntry(nsecs_t eventTime,
+                int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
+                int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+                int32_t repeatCount, nsecs_t downTime);
+        void recycle();
+
+    protected:
+        virtual ~KeyEntry();
     };
 
     struct MotionSample {
@@ -484,6 +509,9 @@
         nsecs_t eventTime; // may be updated during coalescing
         nsecs_t eventTimeBeforeCoalescing; // not updated during coalescing
         PointerCoords pointerCoords[MAX_POINTERS];
+
+        MotionSample(nsecs_t eventTime, const PointerCoords* pointerCoords,
+                uint32_t pointerCount);
     };
 
     struct MotionEntry : EventEntry {
@@ -504,11 +532,23 @@
         MotionSample firstSample;
         MotionSample* lastSample;
 
+        MotionEntry(nsecs_t eventTime,
+                int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
+                int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+                float xPrecision, float yPrecision,
+                nsecs_t downTime, uint32_t pointerCount,
+                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
+
         uint32_t countSamples() const;
 
         // Checks whether we can append samples, assuming the device id and source are the same.
         bool canAppendSamples(int32_t action, uint32_t pointerCount,
                 const PointerProperties* pointerProperties) const;
+
+        void appendSample(nsecs_t eventTime, const PointerCoords* pointerCoords);
+
+    protected:
+        virtual ~MotionEntry();
     };
 
     // Tracks the progress of dispatching a particular event to a particular connection.
@@ -539,6 +579,10 @@
         //   will be set to NULL.
         MotionSample* tailMotionSample;
 
+        DispatchEntry(EventEntry* eventEntry,
+                int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
+        ~DispatchEntry();
+
         inline bool hasForegroundTarget() const {
             return targetFlags & InputTarget::FLAG_FOREGROUND;
         }
@@ -569,7 +613,7 @@
 
     class Connection;
     struct CommandEntry : Link<CommandEntry> {
-        CommandEntry();
+        CommandEntry(Command command);
         ~CommandEntry();
 
         Command command;
@@ -578,7 +622,6 @@
         sp<Connection> connection;
         nsecs_t eventTime;
         KeyEntry* keyEntry;
-        sp<InputChannel> inputChannel;
         sp<InputApplicationHandle> inputApplicationHandle;
         sp<InputWindowHandle> inputWindowHandle;
         int32_t userActivityEventType;
@@ -588,99 +631,65 @@
     // Generic queue implementation.
     template <typename T>
     struct Queue {
-        T headSentinel;
-        T tailSentinel;
+        T* head;
+        T* tail;
 
-        inline Queue() {
-            headSentinel.prev = NULL;
-            headSentinel.next = & tailSentinel;
-            tailSentinel.prev = & headSentinel;
-            tailSentinel.next = NULL;
+        inline Queue() : head(NULL), tail(NULL) {
         }
 
         inline bool isEmpty() const {
-            return headSentinel.next == & tailSentinel;
+            return !head;
         }
 
         inline void enqueueAtTail(T* entry) {
-            T* last = tailSentinel.prev;
-            last->next = entry;
-            entry->prev = last;
-            entry->next = & tailSentinel;
-            tailSentinel.prev = entry;
+            entry->prev = tail;
+            if (tail) {
+                tail->next = entry;
+            } else {
+                head = entry;
+            }
+            entry->next = NULL;
+            tail = entry;
         }
 
         inline void enqueueAtHead(T* entry) {
-            T* first = headSentinel.next;
-            headSentinel.next = entry;
-            entry->prev = & headSentinel;
-            entry->next = first;
-            first->prev = entry;
+            entry->next = head;
+            if (head) {
+                head->prev = entry;
+            } else {
+                tail = entry;
+            }
+            entry->prev = NULL;
+            head = entry;
         }
 
         inline void dequeue(T* entry) {
-            entry->prev->next = entry->next;
-            entry->next->prev = entry->prev;
+            if (entry->prev) {
+                entry->prev->next = entry->next;
+            } else {
+                head = entry->next;
+            }
+            if (entry->next) {
+                entry->next->prev = entry->prev;
+            } else {
+                tail = entry->prev;
+            }
         }
 
         inline T* dequeueAtHead() {
-            T* first = headSentinel.next;
-            dequeue(first);
-            return first;
+            T* entry = head;
+            head = entry->next;
+            if (head) {
+                head->prev = NULL;
+            } else {
+                tail = NULL;
+            }
+            return entry;
         }
 
         uint32_t count() const;
     };
 
-    /* Allocates queue entries and performs reference counting as needed. */
-    class Allocator {
-    public:
-        Allocator();
-
-        InjectionState* obtainInjectionState(int32_t injectorPid, int32_t injectorUid);
-        ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime);
-        KeyEntry* obtainKeyEntry(nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-                int32_t repeatCount, nsecs_t downTime);
-        MotionEntry* obtainMotionEntry(nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
-                float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
-                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
-        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
-                int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
-        CommandEntry* obtainCommandEntry(Command command);
-
-        void releaseInjectionState(InjectionState* injectionState);
-        void releaseEventEntry(EventEntry* entry);
-        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
-        void releaseKeyEntry(KeyEntry* entry);
-        void releaseMotionEntry(MotionEntry* entry);
-        void freeMotionSample(MotionSample* sample);
-        void releaseDispatchEntry(DispatchEntry* entry);
-        void releaseCommandEntry(CommandEntry* entry);
-
-        void recycleKeyEntry(KeyEntry* entry);
-
-        void appendMotionSample(MotionEntry* motionEntry,
-                nsecs_t eventTime, const PointerCoords* pointerCoords);
-
-    private:
-        Pool<InjectionState> mInjectionStatePool;
-        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
-        Pool<KeyEntry> mKeyEntryPool;
-        Pool<MotionEntry> mMotionEntryPool;
-        Pool<MotionSample> mMotionSamplePool;
-        Pool<DispatchEntry> mDispatchEntryPool;
-        Pool<CommandEntry> mCommandEntryPool;
-
-        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
-                uint32_t policyFlags);
-        void releaseEventEntryInjectionState(EventEntry* entry);
-    };
-
     /* Specifies which events are to be canceled and why. */
     struct CancelationOptions {
         enum Mode {
@@ -728,7 +737,7 @@
         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,
+        void synthesizeCancelationEvents(nsecs_t currentTime,
                 Vector<EventEntry*>& outEvents, const CancelationOptions& options);
 
         // Clears the current state.
@@ -856,7 +865,6 @@
 
     Mutex mLock;
 
-    Allocator mAllocator;
     sp<Looper> mLooper;
 
     EventEntry* mPendingEvent;
@@ -894,7 +902,7 @@
     // to transfer focus to a new application.
     EventEntry* mNextUnblockedEvent;
 
-    const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y);
 
     // All registered connections mapped by receive pipe file descriptor.
     KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@@ -953,19 +961,19 @@
     bool mDispatchFrozen;
     bool mInputFilterEnabled;
 
-    Vector<InputWindow> mWindows;
+    Vector<sp<InputWindowHandle> > mWindowHandles;
 
-    const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
+    sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
+    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
 
     // Focus tracking for keys, trackball, etc.
-    const InputWindow* mFocusedWindow;
+    sp<InputWindowHandle> mFocusedWindowHandle;
 
     // Focus tracking for touch.
     struct TouchedWindow {
-        const InputWindow* window;
+        sp<InputWindowHandle> windowHandle;
         int32_t targetFlags;
         BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
-        sp<InputChannel> channel;
     };
     struct TouchState {
         bool down;
@@ -978,9 +986,10 @@
         ~TouchState();
         void reset();
         void copyFrom(const TouchState& other);
-        void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds);
+        void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+                int32_t targetFlags, BitSet32 pointerIds);
         void filterNonAsIsTouchWindows();
-        const InputWindow* getFirstForegroundWindow() const;
+        sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
         bool isSlippery() const;
     };
 
@@ -988,9 +997,7 @@
     TouchState mTempTouchState;
 
     // Focused application.
-    InputApplication* mFocusedApplication;
-    InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
-    void releaseFocusedApplicationLocked();
+    sp<InputApplicationHandle> mFocusedApplicationHandle;
 
     // Dispatch inbound events.
     bool dispatchConfigurationChangedLocked(
@@ -1021,16 +1028,17 @@
     nsecs_t mInputTargetWaitStartTime;
     nsecs_t mInputTargetWaitTimeoutTime;
     bool mInputTargetWaitTimeoutExpired;
-    sp<InputApplicationHandle> mInputTargetWaitApplication;
+    sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
 
     // Contains the last window which received a hover event.
-    const InputWindow* mLastHoverWindow;
+    sp<InputWindowHandle> mLastHoverWindowHandle;
 
     // Finding targets for input events.
     void resetTargetsLocked();
     void commitTargetsLocked();
     int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
-            const InputApplication* application, const InputWindow* window,
+            const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
             nsecs_t* nextWakeupTime);
     void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
             const sp<InputChannel>& inputChannel);
@@ -1043,15 +1051,17 @@
             nsecs_t* nextWakeupTime, bool* outConflictingPointerActions,
             const MotionSample** outSplitBatchAfterSample);
 
-    void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-            BitSet32 pointerIds);
+    void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t targetFlags, BitSet32 pointerIds);
     void addMonitoringTargetsLocked();
     void pokeUserActivityLocked(const EventEntry* eventEntry);
-    bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
-    bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
-    bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
-    String8 getApplicationWindowLabelLocked(const InputApplication* application,
-            const InputWindow* window);
+    bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+            const InjectionState* injectionState);
+    bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t x, int32_t y) const;
+    bool isWindowFinishedWithPreviousInputLocked(const sp<InputWindowHandle>& windowHandle);
+    String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle);
 
     // Manage the dispatch cycle for a single connection.
     // These methods are deliberately not Interruptible because doing all of the work
@@ -1100,7 +1110,8 @@
     void onDispatchCycleBrokenLocked(
             nsecs_t currentTime, const sp<Connection>& connection);
     void onANRLocked(
-            nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+            nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
             nsecs_t eventTime, nsecs_t waitStartTime);
 
     // Outbound policy interactions.
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 49cb864..db312ad 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -120,59 +120,37 @@
 static const size_t keyCodeRotationMapSize =
         sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
 
-int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
     return rotateValueUsingRotationMap(keyCode, orientation,
             keyCodeRotationMap, keyCodeRotationMapSize);
 }
 
-static const int32_t edgeFlagRotationMap[][4] = {
-        // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
-        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
-        { AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT,
-                AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT },
-        { AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP,
-                AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM },
-        { AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT,
-                AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT },
-        { AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM,
-                AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP },
-};
-static const size_t edgeFlagRotationMapSize =
-        sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
+static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
+    float temp;
+    switch (orientation) {
+    case DISPLAY_ORIENTATION_90:
+        temp = *deltaX;
+        *deltaX = *deltaY;
+        *deltaY = -temp;
+        break;
 
-static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
-    return rotateValueUsingRotationMap(edgeFlag, orientation,
-            edgeFlagRotationMap, edgeFlagRotationMapSize);
+    case DISPLAY_ORIENTATION_180:
+        *deltaX = -*deltaX;
+        *deltaY = -*deltaY;
+        break;
+
+    case DISPLAY_ORIENTATION_270:
+        temp = *deltaX;
+        *deltaX = -*deltaY;
+        *deltaY = temp;
+        break;
+    }
 }
 
 static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
     return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
 }
 
-static uint32_t getButtonStateForScanCode(int32_t scanCode) {
-    // Currently all buttons are mapped to the primary button.
-    switch (scanCode) {
-    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_FORWARD:
-    case BTN_EXTRA:
-        return AMOTION_EVENT_BUTTON_FORWARD;
-    case BTN_BACK:
-        return AMOTION_EVENT_BUTTON_BACK;
-    case BTN_TASK:
-    default:
-        return 0;
-    }
-}
-
 // Returns true if the pointer should be reported as being down given the specified
 // button states.  This determines whether the event is reported as a touch event.
 static bool isPointerDown(int32_t buttonState) {
@@ -181,25 +159,6 @@
                     | AMOTION_EVENT_BUTTON_TERTIARY);
 }
 
-static int32_t calculateEdgeFlagsUsingPointerBounds(
-        const sp<PointerControllerInterface>& pointerController, float x, float y) {
-    int32_t edgeFlags = 0;
-    float minX, minY, maxX, maxY;
-    if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
-        if (x <= minX) {
-            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
-        } else if (x >= maxX) {
-            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
-        }
-        if (y <= minY) {
-            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
-        } else if (y >= maxY) {
-            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
-        }
-    }
-    return edgeFlags;
-}
-
 static float calculateCommonVector(float a, float b) {
     if (a > 0 && b > 0) {
         return a < b ? a : b;
@@ -1024,6 +983,378 @@
 }
 
 
+// --- CursorButtonAccumulator ---
+
+CursorButtonAccumulator::CursorButtonAccumulator() {
+    clearButtons();
+}
+
+void CursorButtonAccumulator::clearButtons() {
+    mBtnLeft = 0;
+    mBtnRight = 0;
+    mBtnMiddle = 0;
+    mBtnBack = 0;
+    mBtnSide = 0;
+    mBtnForward = 0;
+    mBtnExtra = 0;
+    mBtnTask = 0;
+}
+
+void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_KEY) {
+        switch (rawEvent->scanCode) {
+        case BTN_LEFT:
+            mBtnLeft = rawEvent->value;
+            break;
+        case BTN_RIGHT:
+            mBtnRight = rawEvent->value;
+            break;
+        case BTN_MIDDLE:
+            mBtnMiddle = rawEvent->value;
+            break;
+        case BTN_BACK:
+            mBtnBack = rawEvent->value;
+            break;
+        case BTN_SIDE:
+            mBtnSide = rawEvent->value;
+            break;
+        case BTN_FORWARD:
+            mBtnForward = rawEvent->value;
+            break;
+        case BTN_EXTRA:
+            mBtnExtra = rawEvent->value;
+            break;
+        case BTN_TASK:
+            mBtnTask = rawEvent->value;
+            break;
+        }
+    }
+}
+
+uint32_t CursorButtonAccumulator::getButtonState() const {
+    uint32_t result = 0;
+    if (mBtnLeft) {
+        result |= AMOTION_EVENT_BUTTON_PRIMARY;
+    }
+    if (mBtnRight) {
+        result |= AMOTION_EVENT_BUTTON_SECONDARY;
+    }
+    if (mBtnMiddle) {
+        result |= AMOTION_EVENT_BUTTON_TERTIARY;
+    }
+    if (mBtnBack || mBtnSide) {
+        result |= AMOTION_EVENT_BUTTON_BACK;
+    }
+    if (mBtnForward || mBtnExtra) {
+        result |= AMOTION_EVENT_BUTTON_FORWARD;
+    }
+    return result;
+}
+
+
+// --- CursorMotionAccumulator ---
+
+CursorMotionAccumulator::CursorMotionAccumulator() :
+        mHaveRelWheel(false), mHaveRelHWheel(false) {
+    clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::configure(InputDevice* device) {
+    mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+    mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorMotionAccumulator::clearRelativeAxes() {
+    mRelX = 0;
+    mRelY = 0;
+    mRelWheel = 0;
+    mRelHWheel = 0;
+}
+
+void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_REL) {
+        switch (rawEvent->scanCode) {
+        case REL_X:
+            mRelX = rawEvent->value;
+            break;
+        case REL_Y:
+            mRelY = rawEvent->value;
+            break;
+        case REL_WHEEL:
+            mRelWheel = rawEvent->value;
+            break;
+        case REL_HWHEEL:
+            mRelHWheel = rawEvent->value;
+            break;
+        }
+    }
+}
+
+
+// --- TouchButtonAccumulator ---
+
+TouchButtonAccumulator::TouchButtonAccumulator() :
+        mHaveBtnTouch(false) {
+    clearButtons();
+}
+
+void TouchButtonAccumulator::configure(InputDevice* device) {
+    mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH);
+}
+
+void TouchButtonAccumulator::clearButtons() {
+    mBtnTouch = 0;
+    mBtnStylus = 0;
+    mBtnStylus2 = 0;
+    mBtnToolFinger = 0;
+    mBtnToolPen = 0;
+    mBtnToolRubber = 0;
+}
+
+void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_KEY) {
+        switch (rawEvent->scanCode) {
+        case BTN_TOUCH:
+            mBtnTouch = rawEvent->value;
+            break;
+        case BTN_STYLUS:
+            mBtnStylus = rawEvent->value;
+            break;
+        case BTN_STYLUS2:
+            mBtnStylus2 = rawEvent->value;
+            break;
+        case BTN_TOOL_FINGER:
+            mBtnToolFinger = rawEvent->value;
+            break;
+        case BTN_TOOL_PEN:
+            mBtnToolPen = rawEvent->value;
+            break;
+        case BTN_TOOL_RUBBER:
+            mBtnToolRubber = rawEvent->value;
+            break;
+        }
+    }
+}
+
+uint32_t TouchButtonAccumulator::getButtonState() const {
+    uint32_t result = 0;
+    if (mBtnStylus) {
+        result |= AMOTION_EVENT_BUTTON_SECONDARY;
+    }
+    if (mBtnStylus2) {
+        result |= AMOTION_EVENT_BUTTON_TERTIARY;
+    }
+    return result;
+}
+
+int32_t TouchButtonAccumulator::getToolType() const {
+    if (mBtnToolRubber) {
+        return AMOTION_EVENT_TOOL_TYPE_ERASER;
+    }
+    if (mBtnToolPen) {
+        return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+    }
+    if (mBtnToolFinger) {
+        return AMOTION_EVENT_TOOL_TYPE_FINGER;
+    }
+    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+bool TouchButtonAccumulator::isActive() const {
+    return mBtnTouch || mBtnToolFinger || mBtnToolPen
+            || mBtnToolRubber || mBtnStylus || mBtnStylus2;
+}
+
+bool TouchButtonAccumulator::isHovering() const {
+    return mHaveBtnTouch && !mBtnTouch;
+}
+
+
+// --- SingleTouchMotionAccumulator ---
+
+SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
+    clearAbsoluteAxes();
+}
+
+void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
+    mAbsX = 0;
+    mAbsY = 0;
+    mAbsPressure = 0;
+    mAbsToolWidth = 0;
+    mAbsDistance = 0;
+}
+
+void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_ABS) {
+        switch (rawEvent->scanCode) {
+        case ABS_X:
+            mAbsX = rawEvent->value;
+            break;
+        case ABS_Y:
+            mAbsY = rawEvent->value;
+            break;
+        case ABS_PRESSURE:
+            mAbsPressure = rawEvent->value;
+            break;
+        case ABS_TOOL_WIDTH:
+            mAbsToolWidth = rawEvent->value;
+            break;
+        case ABS_DISTANCE:
+            mAbsDistance = rawEvent->value;
+            break;
+        }
+    }
+}
+
+
+// --- MultiTouchMotionAccumulator ---
+
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
+        mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
+}
+
+MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
+    delete[] mSlots;
+}
+
+void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
+    mSlotCount = slotCount;
+    mUsingSlotsProtocol = usingSlotsProtocol;
+
+    delete[] mSlots;
+    mSlots = new Slot[slotCount];
+}
+
+void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
+    for (size_t i = 0; i < mSlotCount; i++) {
+        mSlots[i].clearIfInUse();
+    }
+    mCurrentSlot = initialSlot;
+}
+
+void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+    if (rawEvent->type == EV_ABS) {
+        bool newSlot = false;
+        if (mUsingSlotsProtocol) {
+            if (rawEvent->scanCode == ABS_MT_SLOT) {
+                mCurrentSlot = rawEvent->value;
+                newSlot = true;
+            }
+        } else if (mCurrentSlot < 0) {
+            mCurrentSlot = 0;
+        }
+
+        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+#if DEBUG_POINTERS
+            if (newSlot) {
+                LOGW("MultiTouch device emitted invalid slot index %d but it "
+                        "should be between 0 and %d; ignoring this slot.",
+                        mCurrentSlot, mSlotCount - 1);
+            }
+#endif
+        } else {
+            Slot* slot = &mSlots[mCurrentSlot];
+
+            switch (rawEvent->scanCode) {
+            case ABS_MT_POSITION_X:
+                slot->mInUse = true;
+                slot->mAbsMTPositionX = rawEvent->value;
+                break;
+            case ABS_MT_POSITION_Y:
+                slot->mInUse = true;
+                slot->mAbsMTPositionY = rawEvent->value;
+                break;
+            case ABS_MT_TOUCH_MAJOR:
+                slot->mInUse = true;
+                slot->mAbsMTTouchMajor = rawEvent->value;
+                break;
+            case ABS_MT_TOUCH_MINOR:
+                slot->mInUse = true;
+                slot->mAbsMTTouchMinor = rawEvent->value;
+                slot->mHaveAbsMTTouchMinor = true;
+                break;
+            case ABS_MT_WIDTH_MAJOR:
+                slot->mInUse = true;
+                slot->mAbsMTWidthMajor = rawEvent->value;
+                break;
+            case ABS_MT_WIDTH_MINOR:
+                slot->mInUse = true;
+                slot->mAbsMTWidthMinor = rawEvent->value;
+                slot->mHaveAbsMTWidthMinor = true;
+                break;
+            case ABS_MT_ORIENTATION:
+                slot->mInUse = true;
+                slot->mAbsMTOrientation = rawEvent->value;
+                break;
+            case ABS_MT_TRACKING_ID:
+                if (mUsingSlotsProtocol && rawEvent->value < 0) {
+                    slot->clearIfInUse();
+                } else {
+                    slot->mInUse = true;
+                    slot->mAbsMTTrackingId = rawEvent->value;
+                }
+                break;
+            case ABS_MT_PRESSURE:
+                slot->mInUse = true;
+                slot->mAbsMTPressure = rawEvent->value;
+                break;
+            case ABS_MT_TOOL_TYPE:
+                slot->mInUse = true;
+                slot->mAbsMTToolType = rawEvent->value;
+                slot->mHaveAbsMTToolType = true;
+                break;
+            }
+        }
+    } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
+        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+        mCurrentSlot += 1;
+    }
+}
+
+
+// --- MultiTouchMotionAccumulator::Slot ---
+
+MultiTouchMotionAccumulator::Slot::Slot() {
+    clear();
+}
+
+void MultiTouchMotionAccumulator::Slot::clearIfInUse() {
+    if (mInUse) {
+        clear();
+    }
+}
+
+void MultiTouchMotionAccumulator::Slot::clear() {
+    mInUse = false;
+    mHaveAbsMTTouchMinor = false;
+    mHaveAbsMTWidthMinor = false;
+    mHaveAbsMTToolType = false;
+    mAbsMTPositionX = 0;
+    mAbsMTPositionY = 0;
+    mAbsMTTouchMajor = 0;
+    mAbsMTTouchMinor = 0;
+    mAbsMTWidthMajor = 0;
+    mAbsMTWidthMinor = 0;
+    mAbsMTOrientation = 0;
+    mAbsMTTrackingId = -1;
+    mAbsMTPressure = 0;
+    mAbsMTToolType = 0;
+    mAbsMTDistance = 0;
+}
+
+int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
+    if (mHaveAbsMTToolType) {
+        switch (mAbsMTToolType) {
+        case MT_TOOL_FINGER:
+            return AMOTION_EVENT_TOOL_TYPE_FINGER;
+        case MT_TOOL_PEN:
+            return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+        }
+    }
+    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+
 // --- InputMapper ---
 
 InputMapper::InputMapper(InputDevice* device) :
@@ -1174,7 +1505,10 @@
     getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
+    mParameters.associatedDisplayId = -1;
+    if (mParameters.orientationAware) {
+        mParameters.associatedDisplayId = 0;
+    }
 }
 
 void KeyboardInputMapper::dumpParameters(String8& dump) {
@@ -1246,7 +1580,7 @@
             if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
                 int32_t orientation;
                 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                        NULL, NULL, & orientation)) {
+                        false /*external*/, NULL, NULL, & orientation)) {
                     orientation = DISPLAY_ORIENTATION_0;
                 }
 
@@ -1416,10 +1750,10 @@
     }
     info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
 
-    if (mHaveVWheel) {
+    if (mCursorMotionAccumulator.haveRelativeVWheel()) {
         info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
     }
-    if (mHaveHWheel) {
+    if (mCursorMotionAccumulator.haveRelativeHWheel()) {
         info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
     }
 }
@@ -1433,8 +1767,10 @@
         dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
         dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
         dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
-        dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
-        dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
+        dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
+                toString(mCursorMotionAccumulator.haveRelativeVWheel()));
+        dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
+                toString(mCursorMotionAccumulator.haveRelativeHWheel()));
         dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
         dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
         dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
@@ -1447,6 +1783,8 @@
     InputMapper::configure(config, changes);
 
     if (!changes) { // first time only
+        mCursorMotionAccumulator.configure(getDevice());
+
         // Configure basic parameters.
         configureParameters();
 
@@ -1471,9 +1809,6 @@
 
         mVWheelScale = 1.0f;
         mHWheelScale = 1.0f;
-
-        mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
-        mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
     }
 
     if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
@@ -1498,8 +1833,10 @@
     getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
-            || mParameters.orientationAware ? 0 : -1;
+    mParameters.associatedDisplayId = -1;
+    if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
+        mParameters.associatedDisplayId = 0;
+    }
 }
 
 void CursorInputMapper::dumpParameters(String8& dump) {
@@ -1523,7 +1860,8 @@
 }
 
 void CursorInputMapper::initializeLocked() {
-    mAccumulator.clear();
+    mCursorButtonAccumulator.clearButtons();
+    mCursorMotionAccumulator.clearRelativeAxes();
 
     mLocked.buttonState = 0;
     mLocked.downTime = 0;
@@ -1549,10 +1887,8 @@
 
         // Synthesize button up event on reset.
         nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        mAccumulator.clear();
-        mAccumulator.buttonDown = 0;
-        mAccumulator.buttonUp = buttonState;
-        mAccumulator.fields = Accumulator::FIELD_BUTTONS;
+        mCursorButtonAccumulator.clearButtons();
+        mCursorMotionAccumulator.clearRelativeAxes();
         sync(when);
     }
 
@@ -1560,66 +1896,16 @@
 }
 
 void CursorInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY: {
-        int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
-        if (buttonState) {
-            if (rawEvent->value) {
-                mAccumulator.buttonDown = buttonState;
-                mAccumulator.buttonUp = 0;
-            } else {
-                mAccumulator.buttonDown = 0;
-                mAccumulator.buttonUp = buttonState;
-            }
-            mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
+    mCursorButtonAccumulator.process(rawEvent);
+    mCursorMotionAccumulator.process(rawEvent);
 
-            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
-            // we need to ensure that we report the up/down promptly.
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-
-    case EV_REL:
-        switch (rawEvent->scanCode) {
-        case REL_X:
-            mAccumulator.fields |= Accumulator::FIELD_REL_X;
-            mAccumulator.relX = rawEvent->value;
-            break;
-        case REL_Y:
-            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
-            mAccumulator.relY = rawEvent->value;
-            break;
-        case REL_WHEEL:
-            mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
-            mAccumulator.relWheel = rawEvent->value;
-            break;
-        case REL_HWHEEL:
-            mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
-            mAccumulator.relHWheel = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
+    if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+        sync(rawEvent->when);
     }
 }
 
 void CursorInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
     int32_t motionEventAction;
-    int32_t motionEventEdgeFlags;
     int32_t lastButtonState, currentButtonState;
     PointerProperties pointerProperties;
     PointerCoords pointerCoords;
@@ -1629,34 +1915,21 @@
         AutoMutex _l(mLock);
 
         lastButtonState = mLocked.buttonState;
+        currentButtonState = mCursorButtonAccumulator.getButtonState();
+        mLocked.buttonState = currentButtonState;
 
-        bool down, downChanged;
-        bool wasDown = isPointerDown(mLocked.buttonState);
-        bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
-        if (buttonsChanged) {
-            mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
-                    & ~mAccumulator.buttonUp;
-
-            down = isPointerDown(mLocked.buttonState);
-
-            if (!wasDown && down) {
-                mLocked.downTime = when;
-                downChanged = true;
-            } else if (wasDown && !down) {
-                downChanged = true;
-            } else {
-                downChanged = false;
-            }
+        bool wasDown = isPointerDown(lastButtonState);
+        bool down = isPointerDown(currentButtonState);
+        bool downChanged;
+        if (!wasDown && down) {
+            mLocked.downTime = when;
+            downChanged = true;
+        } else if (wasDown && !down) {
+            downChanged = true;
         } else {
-            down = wasDown;
             downChanged = false;
         }
-
-        currentButtonState = mLocked.buttonState;
-
         downTime = mLocked.downTime;
-        float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
-        float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
 
         if (downChanged) {
             motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
@@ -1666,64 +1939,39 @@
             motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
         }
 
+        float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
+        float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
+
         if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
                 && (deltaX != 0.0f || deltaY != 0.0f)) {
             // Rotate motion based on display orientation if needed.
             // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
             int32_t orientation;
             if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                    NULL, NULL, & orientation)) {
+                    false /*external*/, NULL, NULL, & orientation)) {
                 orientation = DISPLAY_ORIENTATION_0;
             }
 
-            float temp;
-            switch (orientation) {
-            case DISPLAY_ORIENTATION_90:
-                temp = deltaX;
-                deltaX = deltaY;
-                deltaY = -temp;
-                break;
-
-            case DISPLAY_ORIENTATION_180:
-                deltaX = -deltaX;
-                deltaY = -deltaY;
-                break;
-
-            case DISPLAY_ORIENTATION_270:
-                temp = deltaX;
-                deltaX = -deltaY;
-                deltaY = temp;
-                break;
-            }
+            rotateDelta(orientation, &deltaX, &deltaY);
         }
 
-        motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
-
         pointerProperties.clear();
         pointerProperties.id = 0;
         pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
 
         pointerCoords.clear();
 
-        if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
-            vscroll = mAccumulator.relWheel;
-        } else {
-            vscroll = 0;
-        }
-        mWheelYVelocityControl.move(when, NULL, &vscroll);
+        vscroll = mCursorMotionAccumulator.getRelativeVWheel();
+        hscroll = mCursorMotionAccumulator.getRelativeHWheel();
 
-        if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
-            hscroll = mAccumulator.relHWheel;
-        } else {
-            hscroll = 0;
-        }
+        mWheelYVelocityControl.move(when, NULL, &vscroll);
         mWheelXVelocityControl.move(when, &hscroll, NULL);
 
         mPointerVelocityControl.move(when, &deltaX, &deltaY);
 
         if (mPointerController != NULL) {
             if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
-                    || buttonsChanged) {
+                    || currentButtonState != lastButtonState) {
                 mPointerController->setPresentation(
                         PointerControllerInterface::PRESENTATION_POINTER);
 
@@ -1731,8 +1979,8 @@
                     mPointerController->move(deltaX, deltaY);
                 }
 
-                if (buttonsChanged) {
-                    mPointerController->setButtonState(mLocked.buttonState);
+                if (currentButtonState != lastButtonState) {
+                    mPointerController->setButtonState(currentButtonState);
                 }
 
                 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
@@ -1742,11 +1990,6 @@
             mPointerController->getPosition(&x, &y);
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-
-            if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
-                motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds(
-                        mPointerController, x, y);
-            }
         } else {
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
@@ -1771,7 +2014,7 @@
     // Send motion event.
     int32_t metaState = mContext->getGlobalMetaState();
     getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
-            motionEventAction, 0, metaState, currentButtonState, motionEventEdgeFlags,
+            motionEventAction, 0, metaState, currentButtonState, 0,
             1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
 
     // Send hover move after UP to tell the application that the mouse is hovering now.
@@ -1798,7 +2041,7 @@
     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
             policyFlags, lastButtonState, currentButtonState);
 
-    mAccumulator.clear();
+    mCursorMotionAccumulator.clearRelativeAxes();
 }
 
 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
@@ -1924,10 +2167,11 @@
             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,
+                    "orientation=%d, distance=%d, toolType=%d, isHovering=%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));
+                    pointer.orientation, pointer.distance,
+                    pointer.toolType, toString(pointer.isHovering));
         }
 
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
@@ -2069,10 +2313,16 @@
     getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = mParameters.orientationAware
+    mParameters.associatedDisplayId = -1;
+    mParameters.associatedDisplayIsExternal = false;
+    if (mParameters.orientationAware
             || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
-            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
-            ? 0 : -1;
+            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+        mParameters.associatedDisplayIsExternal =
+                mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+                        && getDevice()->isExternal();
+        mParameters.associatedDisplayId = 0;
+    }
 }
 
 void TouchInputMapper::dumpParameters(String8& dump) {
@@ -2154,6 +2404,7 @@
     if (mParameters.associatedDisplayId >= 0) {
         // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
         if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+                mParameters.associatedDisplayIsExternal,
                 &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
                 &mLocked.associatedDisplayOrientation)) {
             return false;
@@ -2967,6 +3218,7 @@
         calculatePointerIds();
     }
 
+    // Handle initial down events.
     uint32_t policyFlags = 0;
     if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
@@ -3168,9 +3420,8 @@
     }
 
     // Update current touch coordinates.
-    int32_t edgeFlags;
     float xPrecision, yPrecision;
-    prepareTouches(&edgeFlags, &xPrecision, &yPrecision);
+    prepareTouches(&xPrecision, &yPrecision);
 
     // Dispatch motions.
     BitSet32 currentIdBits = mCurrentTouch.idBits;
@@ -3239,13 +3490,10 @@
             if (dispatchedIdBits.count() == 1) {
                 // First pointer is going down.  Set down time.
                 mDownTime = when;
-            } else {
-                // Only send edge flags with first pointer down.
-                edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
             }
 
             dispatchMotion(when, policyFlags, mTouchSource,
-                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
+                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
                     mCurrentTouchProperties, mCurrentTouchCoords,
                     mCurrentTouch.idToIndex, dispatchedIdBits, downId,
                     xPrecision, yPrecision, mDownTime);
@@ -3259,8 +3507,7 @@
     }
 }
 
-void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
-        float* outXPrecision, float* outYPrecision) {
+void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision) {
     uint32_t currentPointerCount = mCurrentTouch.pointerCount;
     uint32_t lastPointerCount = mLastTouch.pointerCount;
 
@@ -3468,29 +3715,7 @@
         PointerProperties& properties = mCurrentTouchProperties[i];
         properties.clear();
         properties.id = mCurrentTouch.pointers[i].id;
-        properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus);
-    }
-
-    // Check edge flags by looking only at the first pointer since the flags are
-    // global to the event.
-    *outEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
-    if (lastPointerCount == 0 && currentPointerCount > 0) {
-        const PointerData& in = mCurrentTouch.pointers[0];
-
-        if (in.x <= mRawAxes.x.minValue) {
-            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
-                    mLocked.surfaceOrientation);
-        } else if (in.x >= mRawAxes.x.maxValue) {
-            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
-                    mLocked.surfaceOrientation);
-        }
-        if (in.y <= mRawAxes.y.minValue) {
-            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
-                    mLocked.surfaceOrientation);
-        } else if (in.y >= mRawAxes.y.maxValue) {
-            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
-                    mLocked.surfaceOrientation);
-        }
+        properties.toolType = mCurrentTouch.pointers[i].toolType;
     }
 
     *outXPrecision = mLocked.orientedXPrecision;
@@ -3640,19 +3865,12 @@
             downGestureIdBits.clearBit(id);
             dispatchedGestureIdBits.markBit(id);
 
-            int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
             if (dispatchedGestureIdBits.count() == 1) {
-                // First pointer is going down.  Calculate edge flags and set down time.
-                uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
-                const PointerCoords& downCoords = mPointerGesture.currentGestureCoords[index];
-                edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
-                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
-                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
                 mPointerGesture.downTime = when;
             }
 
             dispatchMotion(when, policyFlags, mPointerSource,
-                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
+                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
                     mPointerGesture.currentGestureProperties,
                     mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
                     dispatchedGestureIdBits, id,
@@ -3681,7 +3899,7 @@
         PointerProperties pointerProperties;
         pointerProperties.clear();
         pointerProperties.id = 0;
-        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
 
         PointerCoords pointerCoords;
         pointerCoords.clear();
@@ -3895,6 +4113,7 @@
             float deltaY = (currentPointer.y - lastPointer.y)
                     * mLocked.pointerGestureYMovementScale;
 
+            rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
             mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
 
             // Move the pointer using a relative motion.
@@ -3914,8 +4133,7 @@
         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
         mPointerGesture.currentGestureProperties[0].clear();
         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
-        mPointerGesture.currentGestureProperties[0].toolType =
-                AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
         mPointerGesture.currentGestureCoords[0].clear();
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -3956,7 +4174,7 @@
                     mPointerGesture.currentGestureProperties[0].id =
                             mPointerGesture.activeGestureId;
                     mPointerGesture.currentGestureProperties[0].toolType =
-                            AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+                            AMOTION_EVENT_TOOL_TYPE_FINGER;
                     mPointerGesture.currentGestureCoords[0].clear();
                     mPointerGesture.currentGestureCoords[0].setAxisValue(
                             AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
@@ -4033,6 +4251,7 @@
             float deltaY = (currentPointer.y - lastPointer.y)
                     * mLocked.pointerGestureYMovementScale;
 
+            rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
             mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
 
             // Move the pointer using a relative motion.
@@ -4068,7 +4287,7 @@
         mPointerGesture.currentGestureProperties[0].clear();
         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
         mPointerGesture.currentGestureProperties[0].toolType =
-                AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+                AMOTION_EVENT_TOOL_TYPE_FINGER;
         mPointerGesture.currentGestureCoords[0].clear();
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -4290,6 +4509,8 @@
 
             commonDeltaX *= mLocked.pointerGestureXMovementScale;
             commonDeltaY *= mLocked.pointerGestureYMovementScale;
+
+            rotateDelta(mLocked.surfaceOrientation, &commonDeltaX, &commonDeltaY);
             mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
 
             mPointerGesture.referenceGestureX += commonDeltaX;
@@ -4297,10 +4518,11 @@
         }
 
         // Report gestures.
-        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
-            // PRESS mode.
+        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
+                || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+            // PRESS or SWIPE mode.
 #if DEBUG_GESTURES
-            LOGD("Gestures: PRESS activeTouchId=%d,"
+            LOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
                     "activeGestureId=%d, currentTouchPointerCount=%d",
                     activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
 #endif
@@ -4312,29 +4534,7 @@
             mPointerGesture.currentGestureProperties[0].clear();
             mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
             mPointerGesture.currentGestureProperties[0].toolType =
-                    AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
-            mPointerGesture.currentGestureCoords[0].clear();
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
-                    mPointerGesture.referenceGestureX);
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
-                    mPointerGesture.referenceGestureY);
-            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
-            // SWIPE mode.
-#if DEBUG_GESTURES
-            LOGD("Gestures: SWIPE activeTouchId=%d,"
-                    "activeGestureId=%d, currentTouchPointerCount=%d",
-                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
-#endif
-            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
-            mPointerGesture.currentGestureIdBits.clear();
-            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
-            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
-            mPointerGesture.currentGestureProperties[0].clear();
-            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
-            mPointerGesture.currentGestureProperties[0].toolType =
-                    AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+                    AMOTION_EVENT_TOOL_TYPE_FINGER;
             mPointerGesture.currentGestureCoords[0].clear();
             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
                     mPointerGesture.referenceGestureX);
@@ -4416,20 +4616,21 @@
                 mPointerGesture.currentGestureIdBits.markBit(gestureId);
                 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
 
-                float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
-                        * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
-                float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
-                        * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
+                float deltaX = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
+                        * mLocked.pointerGestureXZoomScale;
+                float deltaY = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
+                        * mLocked.pointerGestureYZoomScale;
+                rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
 
                 mPointerGesture.currentGestureProperties[i].clear();
                 mPointerGesture.currentGestureProperties[i].id = gestureId;
                 mPointerGesture.currentGestureProperties[i].toolType =
-                        AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+                        AMOTION_EVENT_TOOL_TYPE_FINGER;
                 mPointerGesture.currentGestureCoords[i].clear();
                 mPointerGesture.currentGestureCoords[i].setAxisValue(
-                        AMOTION_EVENT_AXIS_X, x);
+                        AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
                 mPointerGesture.currentGestureCoords[i].setAxisValue(
-                        AMOTION_EVENT_AXIS_Y, y);
+                        AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
                 mPointerGesture.currentGestureCoords[i].setAxisValue(
                         AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
             }
@@ -4566,15 +4767,6 @@
     } // release lock
 }
 
-int32_t TouchInputMapper::getTouchToolType(bool isStylus) const {
-    if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
-        return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER;
-    } else {
-        return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS
-                : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
-    }
-}
-
 bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
     return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
             && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
@@ -4853,14 +5045,9 @@
 }
 
 void SingleTouchInputMapper::clearState() {
-    mAccumulator.clear();
-
-    mDown = false;
-    mX = 0;
-    mY = 0;
-    mPressure = 0; // default to 0 for devices that don't report pressure
-    mToolWidth = 0; // default to 0 for devices that don't report tool width
-    mButtonState = 0;
+    mCursorButtonAccumulator.clearButtons();
+    mTouchButtonAccumulator.clearButtons();
+    mSingleTouchMotionAccumulator.clearAbsoluteAxes();
 }
 
 void SingleTouchInputMapper::reset() {
@@ -4870,144 +5057,79 @@
  }
 
 void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY:
-        switch (rawEvent->scanCode) {
-        case BTN_TOUCH:
-            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
-            mAccumulator.btnTouch = rawEvent->value != 0;
-            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
-            // not have received valid position information yet.  This logic assumes that
-            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
-            break;
-        default:
-            if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
-                int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
-                if (buttonState) {
-                    if (rawEvent->value) {
-                        mAccumulator.buttonDown |= buttonState;
-                    } else {
-                        mAccumulator.buttonUp |= buttonState;
-                    }
-                    mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
-                }
-            }
-            break;
-        }
-        break;
+    mCursorButtonAccumulator.process(rawEvent);
+    mTouchButtonAccumulator.process(rawEvent);
+    mSingleTouchMotionAccumulator.process(rawEvent);
 
-    case EV_ABS:
-        switch (rawEvent->scanCode) {
-        case ABS_X:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
-            mAccumulator.absX = rawEvent->value;
-            break;
-        case ABS_Y:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
-            mAccumulator.absY = rawEvent->value;
-            break;
-        case ABS_PRESSURE:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
-            mAccumulator.absPressure = rawEvent->value;
-            break;
-        case ABS_TOOL_WIDTH:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
-            mAccumulator.absToolWidth = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
+    if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+        sync(rawEvent->when);
     }
 }
 
 void SingleTouchInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
-    if (fields & Accumulator::FIELD_BTN_TOUCH) {
-        mDown = mAccumulator.btnTouch;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_X) {
-        mX = mAccumulator.absX;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_Y) {
-        mY = mAccumulator.absY;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
-        mPressure = mAccumulator.absPressure;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
-        mToolWidth = mAccumulator.absToolWidth;
-    }
-
-    if (fields & Accumulator::FIELD_BUTTONS) {
-        mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
-    }
-
     mCurrentTouch.clear();
 
-    if (mDown) {
+    if (mTouchButtonAccumulator.isActive()) {
+        uint32_t buttonState = mTouchButtonAccumulator.getButtonState();
+        bool isHovering = mTouchButtonAccumulator.isHovering();
+        if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) {
+            isHovering = true;
+        }
+
         mCurrentTouch.pointerCount = 1;
-        mCurrentTouch.pointers[0].id = 0;
-        mCurrentTouch.pointers[0].x = mX;
-        mCurrentTouch.pointers[0].y = mY;
-        mCurrentTouch.pointers[0].pressure = mPressure;
-        mCurrentTouch.pointers[0].touchMajor = 0;
-        mCurrentTouch.pointers[0].touchMinor = 0;
-        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
-        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
-        mCurrentTouch.pointers[0].orientation = 0;
-        mCurrentTouch.pointers[0].distance = 0;
-        mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus
         mCurrentTouch.idToIndex[0] = 0;
         mCurrentTouch.idBits.markBit(0);
-        mCurrentTouch.buttonState = mButtonState;
+        mCurrentTouch.buttonState = buttonState;
+
+        PointerData& outPointer = mCurrentTouch.pointers[0];
+        outPointer.id = 0;
+        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
+        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
+        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+        outPointer.touchMajor = 0;
+        outPointer.touchMinor = 0;
+        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+        outPointer.orientation = 0;
+        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+        outPointer.toolType = mTouchButtonAccumulator.getToolType();
+        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+        }
+        outPointer.isHovering = isHovering;
     }
 
     syncTouch(when, true);
-
-    mAccumulator.clear();
 }
 
 void SingleTouchInputMapper::configureRawAxes() {
     TouchInputMapper::configureRawAxes();
 
+    mTouchButtonAccumulator.configure(getDevice());
+
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance);
 }
 
 
 // --- MultiTouchInputMapper ---
 
 MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
-        TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) {
+        TouchInputMapper(device) {
 }
 
 MultiTouchInputMapper::~MultiTouchInputMapper() {
 }
 
 void MultiTouchInputMapper::clearState() {
-    mAccumulator.clearSlots(mSlotCount);
-    mAccumulator.clearButtons();
-    mButtonState = 0;
+    mCursorButtonAccumulator.clearButtons();
+    mTouchButtonAccumulator.clearButtons();
     mPointerIdBits.clear();
 
-    if (mUsingSlotsProtocol) {
+    if (mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
         // 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
@@ -5017,12 +5139,16 @@
         // 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.
+        int32_t initialSlot;
         status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
-                &mAccumulator.currentSlot);
+                &initialSlot);
         if (status) {
             LOGW("Could not retrieve current multitouch slot index.  status=%d", status);
-            mAccumulator.currentSlot = -1;
+            initialSlot = -1;
         }
+        mMultiTouchMotionAccumulator.clearSlots(initialSlot);
+    } else {
+        mMultiTouchMotionAccumulator.clearSlots(-1);
     }
 }
 
@@ -5033,124 +5159,26 @@
 }
 
 void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY: {
-        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
-            int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
-            if (buttonState) {
-                if (rawEvent->value) {
-                    mAccumulator.buttonDown |= buttonState;
-                } else {
-                    mAccumulator.buttonUp |= buttonState;
-                }
-            }
-        }
-        break;
-    }
+    mCursorButtonAccumulator.process(rawEvent);
+    mTouchButtonAccumulator.process(rawEvent);
+    mMultiTouchMotionAccumulator.process(rawEvent);
 
-    case EV_ABS: {
-        bool newSlot = false;
-        if (mUsingSlotsProtocol && rawEvent->scanCode == ABS_MT_SLOT) {
-            mAccumulator.currentSlot = rawEvent->value;
-            newSlot = true;
-        }
-
-        if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
-            if (newSlot) {
-                LOGW("MultiTouch device %s emitted invalid slot index %d but it "
-                        "should be between 0 and %d; ignoring this slot.",
-                        getDeviceName().string(), mAccumulator.currentSlot, mSlotCount);
-            }
-#endif
-            break;
-        }
-
-        Accumulator::Slot* slot = &mAccumulator.slots[mAccumulator.currentSlot];
-
-        switch (rawEvent->scanCode) {
-        case ABS_MT_POSITION_X:
-            slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
-            slot->absMTPositionX = rawEvent->value;
-            break;
-        case ABS_MT_POSITION_Y:
-            slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
-            slot->absMTPositionY = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MAJOR:
-            slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
-            slot->absMTTouchMajor = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MINOR:
-            slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
-            slot->absMTTouchMinor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MAJOR:
-            slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
-            slot->absMTWidthMajor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MINOR:
-            slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
-            slot->absMTWidthMinor = rawEvent->value;
-            break;
-        case ABS_MT_ORIENTATION:
-            slot->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
-            slot->absMTOrientation = rawEvent->value;
-            break;
-        case ABS_MT_TRACKING_ID:
-            if (mUsingSlotsProtocol && rawEvent->value < 0) {
-                slot->clear();
-            } else {
-                slot->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
-                slot->absMTTrackingId = rawEvent->value;
-            }
-            break;
-        case ABS_MT_PRESSURE:
-            slot->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
-            slot->absMTPressure = rawEvent->value;
-            break;
-        case ABS_MT_TOOL_TYPE:
-            slot->fields |= Accumulator::FIELD_ABS_MT_TOOL_TYPE;
-            slot->absMTToolType = rawEvent->value;
-            break;
-        }
-        break;
-    }
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_MT_REPORT: {
-            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
-            mAccumulator.currentSlot += 1;
-            break;
-        }
-
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
+    if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+        sync(rawEvent->when);
     }
 }
 
 void MultiTouchInputMapper::sync(nsecs_t when) {
-    static const uint32_t REQUIRED_FIELDS =
-            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
-    size_t inCount = mSlotCount;
+    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
     size_t outCount = 0;
     bool havePointerIds = true;
 
     mCurrentTouch.clear();
 
     for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
-        const Accumulator::Slot& inSlot = mAccumulator.slots[inIndex];
-        uint32_t fields = inSlot.fields;
-
-        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
-            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
-            // This may also indicate an unused slot.
-            // Drop this finger.
+        const MultiTouchMotionAccumulator::Slot* inSlot =
+                mMultiTouchMotionAccumulator.getSlot(inIndex);
+        if (!inSlot->isInUse()) {
             continue;
         }
 
@@ -5164,76 +5192,32 @@
         }
 
         PointerData& outPointer = mCurrentTouch.pointers[outCount];
-        outPointer.x = inSlot.absMTPositionX;
-        outPointer.y = inSlot.absMTPositionY;
+        outPointer.x = inSlot->getX();
+        outPointer.y = inSlot->getY();
+        outPointer.pressure = inSlot->getPressure();
+        outPointer.touchMajor = inSlot->getTouchMajor();
+        outPointer.touchMinor = inSlot->getTouchMinor();
+        outPointer.toolMajor = inSlot->getToolMajor();
+        outPointer.toolMinor = inSlot->getToolMinor();
+        outPointer.orientation = inSlot->getOrientation();
+        outPointer.distance = inSlot->getDistance();
 
-        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
-            outPointer.pressure = inSlot.absMTPressure;
-        } else {
-            // Default pressure to 0 if absent.
-            outPointer.pressure = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
-            if (inSlot.absMTTouchMajor <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
-                // a pointer going up.  Drop this finger.
-                continue;
+        outPointer.toolType = inSlot->getToolType();
+        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+            outPointer.toolType = mTouchButtonAccumulator.getToolType();
+            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
             }
-            outPointer.touchMajor = inSlot.absMTTouchMajor;
-        } else {
-            // Default touch area to 0 if absent.
-            outPointer.touchMajor = 0;
         }
 
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
-            outPointer.touchMinor = inSlot.absMTTouchMinor;
-        } else {
-            // Assume touch area is circular.
-            outPointer.touchMinor = outPointer.touchMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
-            outPointer.toolMajor = inSlot.absMTWidthMajor;
-        } else {
-            // Default tool area to 0 if absent.
-            outPointer.toolMajor = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
-            outPointer.toolMinor = inSlot.absMTWidthMinor;
-        } else {
-            // Assume tool area is circular.
-            outPointer.toolMinor = outPointer.toolMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
-            outPointer.orientation = inSlot.absMTOrientation;
-        } else {
-            // Default orientation to vertical if absent.
-            outPointer.orientation = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_DISTANCE) {
-            outPointer.distance = inSlot.absMTDistance;
-        } else {
-            // Default distance is 0 (direct contact).
-            outPointer.distance = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOOL_TYPE) {
-            outPointer.isStylus = (inSlot.absMTToolType == MT_TOOL_PEN);
-        } else {
-            // Assume this is not a stylus.
-            outPointer.isStylus = false;
-        }
+        outPointer.isHovering = mTouchButtonAccumulator.isHovering()
+                || inSlot->getDistance() > 0;
 
         // Assign pointer id using tracking id if available.
         if (havePointerIds) {
+            int32_t trackingId = inSlot->getTrackingId();
             int32_t id = -1;
-            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
-                int32_t trackingId = inSlot.absMTTrackingId;
-
+            if (trackingId >= 0) {
                 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
                     uint32_t n = idBits.firstMarkedBit();
                     idBits.clearBit(n);
@@ -5263,23 +5247,22 @@
     }
 
     mCurrentTouch.pointerCount = outCount;
-
-    mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
-    mCurrentTouch.buttonState = mButtonState;
+    mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState();
 
     mPointerIdBits = mCurrentTouch.idBits;
 
     syncTouch(when, havePointerIds);
 
-    if (!mUsingSlotsProtocol) {
-        mAccumulator.clearSlots(mSlotCount);
+    if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
+        mMultiTouchMotionAccumulator.clearSlots(-1);
     }
-    mAccumulator.clearButtons();
 }
 
 void MultiTouchInputMapper::configureRawAxes() {
     TouchInputMapper::configureRawAxes();
 
+    mTouchButtonAccumulator.configure(getDevice());
+
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x);
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y);
     getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor);
@@ -5294,21 +5277,18 @@
 
     if (mRawAxes.trackingId.valid
             && mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) {
-        mSlotCount = mRawAxes.slot.maxValue + 1;
-        if (mSlotCount > MAX_SLOTS) {
+        size_t slotCount = mRawAxes.slot.maxValue + 1;
+        if (slotCount > MAX_SLOTS) {
             LOGW("MultiTouch Device %s reported %d slots but the framework "
                     "only supports a maximum of %d slots at this time.",
-                    getDeviceName().string(), mSlotCount, MAX_SLOTS);
-            mSlotCount = MAX_SLOTS;
+                    getDeviceName().string(), slotCount, MAX_SLOTS);
+            slotCount = MAX_SLOTS;
         }
-        mUsingSlotsProtocol = true;
+        mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
     } else {
-        mSlotCount = MAX_POINTERS;
-        mUsingSlotsProtocol = false;
+        mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
     }
 
-    mAccumulator.allocateSlots(mSlotCount);
-
     clearState();
 }
 
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 69fa6b4..ee6990b 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -180,9 +180,11 @@
     };
 
     /* Gets information about the display with the specified id.
+     * If external is true, returns the size of the external mirrored
+     * counterpart of the specified display.
      * Returns true if the display info is available, false otherwise.
      */
-    virtual bool getDisplayInfo(int32_t displayId,
+    virtual bool getDisplayInfo(int32_t displayId, bool external,
             int32_t* width, int32_t* height, int32_t* orientation) = 0;
 
     /* Gets the input reader configuration. */
@@ -430,9 +432,8 @@
 
     void fadePointer();
 
-    inline const PropertyMap& getConfiguration() {
-        return mConfiguration;
-    }
+    inline const PropertyMap& getConfiguration() { return mConfiguration; }
+    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
 
 private:
     InputReaderContext* mContext;
@@ -452,6 +453,171 @@
 };
 
 
+/* Keeps track of the state of mouse or touch pad buttons. */
+class CursorButtonAccumulator {
+public:
+    CursorButtonAccumulator();
+
+    void clearButtons();
+    void process(const RawEvent* rawEvent);
+
+    uint32_t getButtonState() const;
+
+private:
+    bool mBtnLeft;
+    bool mBtnRight;
+    bool mBtnMiddle;
+    bool mBtnBack;
+    bool mBtnSide;
+    bool mBtnForward;
+    bool mBtnExtra;
+    bool mBtnTask;
+};
+
+
+/* Keeps track of cursor movements. */
+
+class CursorMotionAccumulator {
+public:
+    CursorMotionAccumulator();
+    void configure(InputDevice* device);
+
+    void clearRelativeAxes();
+    void process(const RawEvent* rawEvent);
+
+    inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
+    inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
+
+    inline int32_t getRelativeX() const { return mRelX; }
+    inline int32_t getRelativeY() const { return mRelY; }
+    inline int32_t getRelativeVWheel() const { return mRelWheel; }
+    inline int32_t getRelativeHWheel() const { return mRelHWheel; }
+
+private:
+    bool mHaveRelWheel;
+    bool mHaveRelHWheel;
+
+    int32_t mRelX;
+    int32_t mRelY;
+    int32_t mRelWheel;
+    int32_t mRelHWheel;
+};
+
+
+/* Keeps track of the state of touch, stylus and tool buttons. */
+class TouchButtonAccumulator {
+public:
+    TouchButtonAccumulator();
+    void configure(InputDevice* device);
+
+    void clearButtons();
+    void process(const RawEvent* rawEvent);
+
+    uint32_t getButtonState() const;
+    int32_t getToolType() const;
+    bool isActive() const;
+    bool isHovering() const;
+
+private:
+    bool mHaveBtnTouch;
+
+    bool mBtnTouch;
+    bool mBtnStylus;
+    bool mBtnStylus2;
+    bool mBtnToolFinger;
+    bool mBtnToolPen;
+    bool mBtnToolRubber;
+};
+
+
+/* Keeps track of the state of single-touch protocol. */
+class SingleTouchMotionAccumulator {
+public:
+    SingleTouchMotionAccumulator();
+
+    void clearAbsoluteAxes();
+    void process(const RawEvent* rawEvent);
+
+    inline int32_t getAbsoluteX() const { return mAbsX; }
+    inline int32_t getAbsoluteY() const { return mAbsY; }
+    inline int32_t getAbsolutePressure() const { return mAbsPressure; }
+    inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
+    inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+
+private:
+    int32_t mAbsX;
+    int32_t mAbsY;
+    int32_t mAbsPressure;
+    int32_t mAbsToolWidth;
+    int32_t mAbsDistance;
+};
+
+
+/* Keeps track of the state of multi-touch protocol. */
+class MultiTouchMotionAccumulator {
+public:
+    class Slot {
+    public:
+        inline bool isInUse() const { return mInUse; }
+        inline int32_t getX() const { return mAbsMTPositionX; }
+        inline int32_t getY() const { return mAbsMTPositionY; }
+        inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
+        inline int32_t getTouchMinor() const {
+            return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
+        inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
+        inline int32_t getToolMinor() const {
+            return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
+        inline int32_t getOrientation() const { return mAbsMTOrientation; }
+        inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
+        inline int32_t getPressure() const { return mAbsMTPressure; }
+        inline int32_t getDistance() const { return mAbsMTDistance; }
+        inline int32_t getToolType() const;
+
+    private:
+        friend class MultiTouchMotionAccumulator;
+
+        bool mInUse;
+        bool mHaveAbsMTTouchMinor;
+        bool mHaveAbsMTWidthMinor;
+        bool mHaveAbsMTToolType;
+
+        int32_t mAbsMTPositionX;
+        int32_t mAbsMTPositionY;
+        int32_t mAbsMTTouchMajor;
+        int32_t mAbsMTTouchMinor;
+        int32_t mAbsMTWidthMajor;
+        int32_t mAbsMTWidthMinor;
+        int32_t mAbsMTOrientation;
+        int32_t mAbsMTTrackingId;
+        int32_t mAbsMTPressure;
+        int32_t mAbsMTToolType;
+        int32_t mAbsMTDistance;
+
+        Slot();
+        void clearIfInUse();
+        void clear();
+    };
+
+    MultiTouchMotionAccumulator();
+    ~MultiTouchMotionAccumulator();
+
+    void configure(size_t slotCount, bool usingSlotsProtocol);
+    void process(const RawEvent* rawEvent);
+
+    void clearSlots(int32_t initialSlot);
+
+    inline bool isUsingSlotsProtocol() const { return mUsingSlotsProtocol; }
+    inline size_t getSlotCount() const { return mSlotCount; }
+    inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+
+private:
+    int32_t mCurrentSlot;
+    Slot* mSlots;
+    size_t mSlotCount;
+    bool mUsingSlotsProtocol;
+};
+
+
 /* An input mapper transforms raw input events into cooked event data.
  * A single input device can have multiple associated input mappers in order to interpret
  * different classes of events.
@@ -615,29 +781,8 @@
         bool orientationAware;
     } mParameters;
 
-    struct Accumulator {
-        enum {
-            FIELD_BUTTONS = 1,
-            FIELD_REL_X = 2,
-            FIELD_REL_Y = 4,
-            FIELD_REL_WHEEL = 8,
-            FIELD_REL_HWHEEL = 16,
-        };
-
-        uint32_t fields;
-
-        uint32_t buttonDown;
-        uint32_t buttonUp;
-
-        int32_t relX;
-        int32_t relY;
-        int32_t relWheel;
-        int32_t relHWheel;
-
-        inline void clear() {
-            fields = 0;
-        }
-    } mAccumulator;
+    CursorButtonAccumulator mCursorButtonAccumulator;
+    CursorMotionAccumulator mCursorMotionAccumulator;
 
     int32_t mSource;
     float mXScale;
@@ -645,8 +790,6 @@
     float mXPrecision;
     float mYPrecision;
 
-    bool mHaveVWheel;
-    bool mHaveHWheel;
     float mVWheelScale;
     float mHWheelScale;
 
@@ -722,7 +865,8 @@
         int32_t toolMinor;
         int32_t orientation;
         int32_t distance;
-        bool isStylus;
+        int32_t toolType; // AMOTION_EVENT_TOOL_TYPE constant
+        bool isHovering;
 
         inline bool operator== (const PointerData& other) const {
             return id == other.id
@@ -734,7 +878,9 @@
                     && toolMajor == other.toolMajor
                     && toolMinor == other.toolMinor
                     && orientation == other.orientation
-                    && distance == other.distance;
+                    && distance == other.distance
+                    && toolType == other.toolType
+                    && isHovering == other.isHovering;
         }
         inline bool operator!= (const PointerData& other) const {
             return !(*this == other);
@@ -800,6 +946,7 @@
 
         DeviceType deviceType;
         int32_t associatedDisplayId;
+        bool associatedDisplayIsExternal;
         bool orientationAware;
 
         enum GestureMode {
@@ -1176,7 +1323,7 @@
 
     TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
     void dispatchTouches(nsecs_t when, uint32_t policyFlags);
-    void prepareTouches(int32_t* outEdgeFlags, float* outXPrecision, float* outYPrecision);
+    void prepareTouches(float* outXPrecision, float* outYPrecision);
     void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
     bool preparePointerGestures(nsecs_t when,
             bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout);
@@ -1201,7 +1348,6 @@
 
     void suppressSwipeOntoVirtualKeys(nsecs_t when);
 
-    int32_t getTouchToolType(bool isStylus) const;
     bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
     const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
 
@@ -1221,40 +1367,9 @@
     virtual void configureRawAxes();
 
 private:
-    struct Accumulator {
-        enum {
-            FIELD_BTN_TOUCH = 1,
-            FIELD_ABS_X = 2,
-            FIELD_ABS_Y = 4,
-            FIELD_ABS_PRESSURE = 8,
-            FIELD_ABS_TOOL_WIDTH = 16,
-            FIELD_BUTTONS = 32,
-        };
-
-        uint32_t fields;
-
-        bool btnTouch;
-        int32_t absX;
-        int32_t absY;
-        int32_t absPressure;
-        int32_t absToolWidth;
-
-        uint32_t buttonDown;
-        uint32_t buttonUp;
-
-        inline void clear() {
-            fields = 0;
-            buttonDown = 0;
-            buttonUp = 0;
-        }
-    } mAccumulator;
-
-    bool mDown;
-    int32_t mX;
-    int32_t mY;
-    int32_t mPressure;
-    int32_t mToolWidth;
-    int32_t mButtonState;
+    CursorButtonAccumulator mCursorButtonAccumulator;
+    TouchButtonAccumulator mTouchButtonAccumulator;
+    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
 
     void clearState();
 
@@ -1274,83 +1389,9 @@
     virtual void configureRawAxes();
 
 private:
-    struct Accumulator {
-        enum {
-            FIELD_ABS_MT_POSITION_X = 1 << 0,
-            FIELD_ABS_MT_POSITION_Y = 1 << 1,
-            FIELD_ABS_MT_TOUCH_MAJOR = 1 << 2,
-            FIELD_ABS_MT_TOUCH_MINOR = 1 << 3,
-            FIELD_ABS_MT_WIDTH_MAJOR = 1 << 4,
-            FIELD_ABS_MT_WIDTH_MINOR = 1 << 5,
-            FIELD_ABS_MT_ORIENTATION = 1 << 6,
-            FIELD_ABS_MT_TRACKING_ID = 1 << 7,
-            FIELD_ABS_MT_PRESSURE = 1 << 8,
-            FIELD_ABS_MT_TOOL_TYPE = 1 << 9,
-            FIELD_ABS_MT_DISTANCE = 1 << 10,
-        };
-
-        struct Slot {
-            uint32_t fields; // 0 if slot is unused
-
-            int32_t absMTPositionX;
-            int32_t absMTPositionY;
-            int32_t absMTTouchMajor;
-            int32_t absMTTouchMinor;
-            int32_t absMTWidthMajor;
-            int32_t absMTWidthMinor;
-            int32_t absMTOrientation;
-            int32_t absMTTrackingId;
-            int32_t absMTPressure;
-            int32_t absMTToolType;
-            int32_t absMTDistance;
-
-            inline Slot() {
-                clear();
-            }
-
-            inline void clear() {
-                fields = 0;
-            }
-        };
-
-        // Current slot index.
-        int32_t currentSlot;
-
-        // Array of slots.
-        Slot* slots;
-
-        // Bitfield of buttons that went down or up.
-        uint32_t buttonDown;
-        uint32_t buttonUp;
-
-        Accumulator() : currentSlot(0), slots(NULL), buttonDown(0), buttonUp(0) {
-        }
-
-        ~Accumulator() {
-            delete[] slots;
-        }
-
-        void allocateSlots(size_t slotCount) {
-            slots = new Slot[slotCount];
-        }
-
-        void clearSlots(size_t slotCount) {
-            for (size_t i = 0; i < slotCount; i++) {
-                slots[i].clear();
-            }
-            currentSlot = 0;
-        }
-
-        void clearButtons() {
-            buttonDown = 0;
-            buttonUp = 0;
-        }
-    } mAccumulator;
-
-    size_t mSlotCount;
-    bool mUsingSlotsProtocol;
-
-    int32_t mButtonState;
+    CursorButtonAccumulator mCursorButtonAccumulator;
+    TouchButtonAccumulator mTouchButtonAccumulator;
+    MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
 
     // Specifies the pointer id bits that are in use, and their associated tracking id.
     BitSet32 mPointerIdBits;
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
index b552f6d..0ce8867 100644
--- a/services/input/InputWindow.cpp
+++ b/services/input/InputWindow.cpp
@@ -22,25 +22,25 @@
 
 namespace android {
 
-// --- InputWindow ---
+// --- InputWindowHandle ---
 
-bool InputWindow::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::touchableRegionContainsPoint(int32_t x, int32_t y) const {
     return touchableRegion.contains(x, y);
 }
 
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::frameContainsPoint(int32_t x, int32_t y) const {
     return x >= frameLeft && x <= frameRight
             && y >= frameTop && y <= frameBottom;
 }
 
-bool InputWindow::isTrustedOverlay() const {
+bool InputWindowHandle::isTrustedOverlay() const {
     return layoutParamsType == TYPE_INPUT_METHOD
             || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
-bool InputWindow::supportsSplitTouch() const {
-    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+bool InputWindowHandle::supportsSplitTouch() const {
+    return layoutParamsFlags & FLAG_SPLIT_TOUCH;
 }
 
 } // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index d166ad4..272081c 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -31,29 +31,14 @@
 
 /*
  * A handle to a window that can receive input.
+ *
  * Used by the native input dispatcher to indirectly refer to the window manager objects
  * that describe a window.
  */
 class InputWindowHandle : public RefBase {
-protected:
-    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
-            mInputApplicationHandle(inputApplicationHandle) { }
-    virtual ~InputWindowHandle() { }
-
 public:
-    inline sp<InputApplicationHandle> getInputApplicationHandle() {
-        return mInputApplicationHandle;
-    }
+    const sp<InputApplicationHandle> inputApplicationHandle;
 
-private:
-    sp<InputApplicationHandle> mInputApplicationHandle;
-};
-
-
-/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
     // Window flags from WindowManager.LayoutParams
     enum {
         FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
@@ -164,6 +149,22 @@
     bool isTrustedOverlay() const;
 
     bool supportsSplitTouch() const;
+
+    /**
+     * Requests that the state of this object be updated to reflect
+     * the most current available information about the application.
+     *
+     * This method should only be called from within the input dispatcher's
+     * critical section.
+     *
+     * Returns true on success, or false if the handle is no longer valid.
+     */
+    virtual bool update() = 0;
+
+protected:
+    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+            inputApplicationHandle(inputApplicationHandle) { }
+    virtual ~InputWindowHandle() { }
 };
 
 } // namespace android
diff --git a/services/input/tests/Android.mk b/services/input/tests/Android.mk
index d92fc74..171db3c 100644
--- a/services/input/tests/Android.mk
+++ b/services/input/tests/Android.mk
@@ -42,4 +42,4 @@
 )
 
 # Build the manual test programs.
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 67067de..8533743 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -157,7 +157,7 @@
     }
 
 private:
-    virtual bool getDisplayInfo(int32_t displayId,
+    virtual bool getDisplayInfo(int32_t displayId, bool external /*currently ignored*/,
             int32_t* width, int32_t* height, int32_t* orientation) {
         ssize_t index = mDisplayInfos.indexOfKey(displayId);
         if (index >= 0) {
@@ -369,11 +369,12 @@
         return INPUT_EVENT_INJECTION_FAILED;
     }
 
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
         ADD_FAILURE() << "Should never be called by input reader.";
     }
 
-    virtual void setFocusedApplication(const InputApplication* inputApplication) {
+    virtual void setFocusedApplication(
+            const sp<InputApplicationHandle>& inputApplicationHandle) {
         ADD_FAILURE() << "Should never be called by input reader.";
     }
 
@@ -706,6 +707,15 @@
         return result;
     }
 
+    virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keys.indexOfKey(scanCode);
+            return index >= 0;
+        }
+        return false;
+    }
+
     virtual bool hasLed(int32_t deviceId, int32_t led) const {
         Device* device = getDevice(deviceId);
         return device && device->leds.indexOfKey(led) >= 0;
@@ -2115,6 +2125,7 @@
     // Button press.
     // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
     ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2136,6 +2147,7 @@
 
     // Button release.  Should have same down time.
     process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
     ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2189,6 +2201,7 @@
 
     // Button press without following sync.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2196,6 +2209,7 @@
 
     // Button release without following sync.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2232,6 +2246,7 @@
 
     // Release Button.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2247,10 +2262,12 @@
 
     // Button press.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
 
     // Button release.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
 
     // Reset.  Should not synthesize button up since button is not pressed.
@@ -2268,6 +2285,7 @@
 
     // Button press.
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
 
     // Reset.  Should synthesize button up.
@@ -2444,6 +2462,7 @@
 
 class SingleTouchInputMapperTest : public TouchInputMapperTest {
 protected:
+    void prepareButtons();
     void prepareAxes(int axes);
 
     void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
@@ -2454,6 +2473,10 @@
     void processSync(SingleTouchInputMapper* mapper);
 };
 
+void SingleTouchInputMapperTest::prepareButtons() {
+    mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0);
+}
+
 void SingleTouchInputMapperTest::prepareAxes(int axes) {
     if (axes & POSITION) {
         mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X,
@@ -2503,6 +2526,7 @@
 
 TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareButtons();
     prepareAxes(POSITION);
     addMapperAndConfigure(mapper);
 
@@ -2513,6 +2537,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
     mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
+    prepareButtons();
     prepareAxes(POSITION);
     addMapperAndConfigure(mapper);
 
@@ -2521,6 +2546,7 @@
 
 TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareButtons();
     prepareAxes(POSITION);
     addConfigurationProperty("touch.deviceType", "touchPad");
     addMapperAndConfigure(mapper);
@@ -2530,6 +2556,7 @@
 
 TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareButtons();
     prepareAxes(POSITION);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     addMapperAndConfigure(mapper);
@@ -2541,6 +2568,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2569,6 +2597,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2597,6 +2626,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2614,6 +2644,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2648,6 +2679,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2675,6 +2707,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2725,6 +2758,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2846,6 +2880,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -2919,6 +2954,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION);
     prepareVirtualKeys();
     addMapperAndConfigure(mapper);
@@ -3008,6 +3044,7 @@
 TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
+    prepareButtons();
     prepareAxes(POSITION);
     addConfigurationProperty("touch.orientationAware", "0");
     addMapperAndConfigure(mapper);
@@ -3031,6 +3068,7 @@
 TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
+    prepareButtons();
     prepareAxes(POSITION);
     addMapperAndConfigure(mapper);
 
@@ -3093,6 +3131,7 @@
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
     prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
     prepareAxes(POSITION | PRESSURE | TOOL);
     addMapperAndConfigure(mapper);
 
@@ -3814,6 +3853,7 @@
     FakeInputDispatcher::NotifyMotionArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             args.action);
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 0b15221..a679ca7 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -230,8 +230,14 @@
                         pw.println(':');
                 pw.print("    min=("); pw.print(info.minWidth);
                         pw.print("x"); pw.print(info.minHeight);
+                pw.print(")   minResize=("); pw.print(info.minResizeWidth);
+                        pw.print("x"); pw.print(info.minResizeHeight);
                         pw.print(") updatePeriodMillis=");
                         pw.print(info.updatePeriodMillis);
+                        pw.print(" resizeMode=");
+                        pw.print(info.resizeMode);
+                        pw.print(" autoAdvanceViewId=");
+                        pw.print(info.autoAdvanceViewId);
                         pw.print(" initialLayout=#");
                         pw.print(Integer.toHexString(info.initialLayout));
                         pw.print(" zombie="); pw.println(p.zombie);
@@ -1022,6 +1028,12 @@
             info.minWidth = value != null ? value.data : 0; 
             value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
             info.minHeight = value != null ? value.data : 0;
+            value = sa.peekValue(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
+            info.minResizeWidth = value != null ? value.data : info.minWidth;
+            value = sa.peekValue(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
+            info.minResizeHeight = value != null ? value.data : info.minHeight;
 
             info.updatePeriodMillis = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 786f2fa..e9e66cb 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -76,6 +76,7 @@
 import com.android.internal.backup.LocalTransport;
 import com.android.server.PackageManagerBackupAgent.Metadata;
 
+import java.io.DataInputStream;
 import java.io.EOFException;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -86,8 +87,10 @@
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -96,6 +99,10 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
 
 class BackupManagerService extends IBackupManager.Stub {
     private static final String TAG = "BackupManagerService";
@@ -104,6 +111,8 @@
     // Name and current contents version of the full-backup manifest file
     static final String BACKUP_MANIFEST_FILENAME = "_manifest";
     static final int BACKUP_MANIFEST_VERSION = 1;
+    static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n";
+    static final int BACKUP_FILE_VERSION = 1;
 
     // How often we perform a backup pass.  Privileged external callers can
     // trigger an immediate pass.
@@ -1679,6 +1688,7 @@
 
     class PerformFullBackupTask implements Runnable {
         ParcelFileDescriptor mOutputFile;
+        DeflaterOutputStream mDeflater;
         IFullBackupRestoreObserver mObserver;
         boolean mIncludeApks;
         boolean mIncludeShared;
@@ -1688,6 +1698,55 @@
         File mFilesDir;
         File mManifestFile;
 
+        class FullBackupRunner implements Runnable {
+            PackageInfo mPackage;
+            IBackupAgent mAgent;
+            ParcelFileDescriptor mPipe;
+            int mToken;
+            boolean mSendApk;
+
+            FullBackupRunner(PackageInfo pack, IBackupAgent agent, ParcelFileDescriptor pipe,
+                    int token, boolean sendApk)  throws IOException {
+                mPackage = pack;
+                mAgent = agent;
+                mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor());
+                mToken = token;
+                mSendApk = sendApk;
+            }
+
+            @Override
+            public void run() {
+                try {
+                    BackupDataOutput output = new BackupDataOutput(
+                            mPipe.getFileDescriptor());
+
+                    if (DEBUG) Slog.d(TAG, "Writing manifest for " + mPackage.packageName);
+                    writeAppManifest(mPackage, mManifestFile, mSendApk);
+                    FullBackup.backupToTar(mPackage.packageName, null, null,
+                            mFilesDir.getAbsolutePath(),
+                            mManifestFile.getAbsolutePath(),
+                            output);
+
+                    if (mSendApk) {
+                        writeApkToBackup(mPackage, output);
+                    }
+
+                    if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
+                    prepareOperationTimeout(mToken, TIMEOUT_FULL_BACKUP_INTERVAL);
+                    mAgent.doFullBackup(mPipe, mToken, mBackupManagerBinder);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Error running full backup for " + mPackage.packageName);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote agent vanished during full backup of "
+                            + mPackage.packageName);
+                } finally {
+                    try {
+                        mPipe.close();
+                    } catch (IOException e) {}
+                }
+            }
+        }
+
         PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer, 
                 boolean includeApks, boolean includeShared,
                 boolean doAllApps, String[] packages, AtomicBoolean latch) {
@@ -1736,13 +1795,47 @@
                 }
             }
 
+            FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor());
+
+            // Set up the compression stage
+            Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+            DeflaterOutputStream out = new DeflaterOutputStream(ofstream, deflater, true);
+
             PackageInfo pkg = null;
             try {
+
+                // !!! TODO: if using encryption, set up the encryption stage
+                // and emit the tar header stating the password salt.
+
+                // Write the global file header.  All strings are UTF-8 encoded; lines end
+                // with a '\n' byte.  Actual backup data begins immediately following the
+                // final '\n'.
+                //
+                // line 1: "ANDROID BACKUP"
+                // line 2: backup file format version, currently "1"
+                // line 3: compressed?  "0" if not compressed, "1" if compressed.
+                // line 4: encryption salt?  "-" if not encrypted, otherwise this
+                //         line contains the encryption salt with which the user-
+                //         supplied password is to be expanded, in hexadecimal.
+                StringBuffer headerbuf = new StringBuffer(256);
+                // !!! TODO: programmatically build the compressed / encryption salt fields
+                headerbuf.append(BACKUP_FILE_HEADER_MAGIC);
+                headerbuf.append("1\n1\n-\n");
+
+                try {
+                    byte[] header = headerbuf.toString().getBytes("UTF-8");
+                    ofstream.write(header);
+                } catch (Exception e) {
+                    // Should never happen!
+                    Slog.e(TAG, "Unable to emit archive header", e);
+                    return;
+                }
+
                 // Now back up the app data via the agent mechanism
                 int N = packagesToBackup.size();
                 for (int i = 0; i < N; i++) {
                     pkg = packagesToBackup.get(i);
-                    backupOnePackage(pkg);
+                    backupOnePackage(pkg, out);
                 }
 
                 // Finally, shared storage if requested
@@ -1754,6 +1847,7 @@
             } finally {
                 tearDown(pkg);
                 try {
+                    out.close();
                     mOutputFile.close();
                 } catch (IOException e) {
                     /* nothing we can do about this */
@@ -1771,13 +1865,17 @@
             }
         }
 
-        private void backupOnePackage(PackageInfo pkg) throws RemoteException {
+        private void backupOnePackage(PackageInfo pkg, DeflaterOutputStream out)
+                throws RemoteException {
             Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
 
             IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo,
                     IApplicationThread.BACKUP_MODE_FULL);
             if (agent != null) {
+                ParcelFileDescriptor[] pipes = null;
                 try {
+                     pipes = ParcelFileDescriptor.createPipe();
+
                     ApplicationInfo app = pkg.applicationInfo;
                     final boolean sendApk = mIncludeApks
                             && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0)
@@ -1786,31 +1884,54 @@
 
                     sendOnBackupPackage(pkg.packageName);
 
-                    BackupDataOutput output = new BackupDataOutput(
-                            mOutputFile.getFileDescriptor());
+                    final int token = generateToken();
+                    FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
+                            token, sendApk);
+                    pipes[1].close();   // the runner has dup'd it
+                    pipes[1] = null;
+                    Thread t = new Thread(runner);
+                    t.start();
 
-                    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);
+                    // Now pull data from the app and stuff it into the compressor
+                    try {
+                        FileInputStream raw = new FileInputStream(pipes[0].getFileDescriptor());
+                        DataInputStream in = new DataInputStream(raw);
 
-                    if (sendApk) {
-                        writeApkToBackup(pkg, output);
+                        byte[] buffer = new byte[16 * 1024];
+                        int chunkTotal;
+                        while ((chunkTotal = in.readInt()) > 0) {
+                            while (chunkTotal > 0) {
+                                int toRead = (chunkTotal > buffer.length)
+                                        ? buffer.length : chunkTotal;
+                                int nRead = in.read(buffer, 0, toRead);
+                                out.write(buffer, 0, nRead);
+                                chunkTotal -= nRead;
+                            }
+                        }
+                    } catch (IOException e) {
+                        Slog.i(TAG, "Caught exception reading from agent", e);
                     }
 
-                    if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
-                    final int token = generateToken();
-                    prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL);
-                    agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
                     if (!waitUntilOperationComplete(token)) {
                         Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
                     } else {
-                        if (DEBUG) Slog.d(TAG, "Full backup success: " + pkg.packageName);
+                        if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
                     }
+
                 } catch (IOException e) {
                     Slog.e(TAG, "Error backing up " + pkg.packageName, e);
+                } finally {
+                    try {
+                        if (pipes != null) {
+                            if (pipes[0] != null) pipes[0].close();
+                            if (pipes[1] != null) pipes[1].close();
+                        }
+
+                        // Apply a full sync/flush after each application's data
+                        out.flush();
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Error bringing down backup stack");
+                    }
                 }
             } else {
                 Slog.w(TAG, "Unable to bind to full agent for " + pkg.packageName);
@@ -2084,14 +2205,56 @@
             try {
                 mBytes = 0;
                 byte[] buffer = new byte[32 * 1024];
-                FileInputStream instream = new FileInputStream(mInputFile.getFileDescriptor());
+                FileInputStream rawInStream = new FileInputStream(mInputFile.getFileDescriptor());
+
+                // First, parse out the unencrypted/uncompressed header
+                boolean compressed = false;
+                boolean encrypted = false;
+                final InputStream in;
+
+                boolean okay = false;
+                final int headerLen = BACKUP_FILE_HEADER_MAGIC.length();
+                byte[] streamHeader = new byte[headerLen];
+                try {
+                    int got;
+                    if ((got = rawInStream.read(streamHeader, 0, headerLen)) == headerLen) {
+                        byte[] magicBytes = BACKUP_FILE_HEADER_MAGIC.getBytes("UTF-8");
+                        if (Arrays.equals(magicBytes, streamHeader)) {
+                            // okay, header looks good.  now parse out the rest of the fields.
+                            String s = readHeaderLine(rawInStream);
+                            if (Integer.parseInt(s) == BACKUP_FILE_VERSION) {
+                                // okay, it's a version we recognize
+                                s = readHeaderLine(rawInStream);
+                                compressed = (Integer.parseInt(s) != 0);
+                                s = readHeaderLine(rawInStream);
+                                if (!s.startsWith("-")) {
+                                    encrypted = true;
+                                    // TODO: parse out the salt here and process with the user pw
+                                }
+                                okay = true;
+                            } else Slog.e(TAG, "Wrong header version: " + s);
+                        } else Slog.e(TAG, "Didn't read the right header magic");
+                    } else Slog.e(TAG, "Only read " + got + " bytes of header");
+                } catch (NumberFormatException e) {
+                    Slog.e(TAG, "Can't parse restore data header");
+                }
+
+                if (!okay) {
+                    Slog.e(TAG, "Invalid restore data; aborting.");
+                    return;
+                }
+
+                // okay, use the right stream layer based on compression
+                in = (compressed) ? new InflaterInputStream(rawInStream) : rawInStream;
 
                 boolean didRestore;
                 do {
-                    didRestore = restoreOneFile(instream, buffer);
+                    didRestore = restoreOneFile(in, buffer);
                 } while (didRestore);
 
                 if (DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes);
+            } catch (IOException e) {
+                Slog.e(TAG, "Unable to read restore input");
             } finally {
                 tearDownPipes();
                 tearDownAgent(mTargetApp);
@@ -2115,6 +2278,16 @@
             }
         }
 
+        String readHeaderLine(InputStream in) throws IOException {
+            int c;
+            StringBuffer buffer = new StringBuffer(80);
+            while ((c = in.read()) >= 0) {
+                if (c == '\n') break;   // consume and discard the newlines
+                buffer.append((char)c);
+            }
+            return buffer.toString();
+        }
+
         boolean restoreOneFile(InputStream instream, byte[] buffer) {
             FileMetadata info;
             try {
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index b9ff8d0..6665614 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -17,7 +17,6 @@
 package com.android.server;
 
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -28,7 +27,6 @@
 import android.os.FileUtils;
 import android.os.RecoverySystem;
 import android.os.SystemProperties;
-import android.provider.Settings;
 import android.util.Slog;
 
 import java.io.File;
@@ -59,17 +57,6 @@
 
     @Override
     public void onReceive(final Context context, Intent intent) {
-        try {
-            // Start the load average overlay, if activated
-            ContentResolver res = context.getContentResolver();
-            if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
-                Intent loadavg = new Intent(context, com.android.server.LoadAverageService.class);
-                context.startService(loadavg);
-            }
-        } catch (Exception e) {
-            Slog.e(TAG, "Can't start load average service", e);
-        }
-
         // Log boot events in the background to avoid blocking the main thread with I/O
         new Thread() {
             @Override
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 41450d2..9a9cc8f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -33,7 +33,9 @@
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
+import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.LinkProperties.CompareResult;
 import android.net.MobileDataStateTracker;
 import android.net.NetworkConfig;
 import android.net.NetworkInfo;
@@ -76,6 +78,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
@@ -92,6 +96,7 @@
 public class ConnectivityService extends IConnectivityManager.Stub {
 
     private static final boolean DBG = true;
+    private static final boolean VDBG = true;
     private static final String TAG = "ConnectivityService";
 
     private static final boolean LOGD_RULES = false;
@@ -126,6 +131,11 @@
     private NetworkStateTracker mNetTrackers[];
 
     /**
+     * The link properties that define the current links
+     */
+    private LinkProperties mCurrentLinkProperties[];
+
+    /**
      * A per Net list of the PID's that requested access to the net
      * used both as a refcount and for per-PID DNS selection
      */
@@ -145,7 +155,9 @@
     private boolean mInetConditionChangeInFlight = false;
     private int mDefaultConnectionSequence = 0;
 
+    private Object mDnsLock = new Object();
     private int mNumDnsEntries;
+    private boolean mDnsOverridden = false;
 
     private boolean mTestMode;
     private static ConnectivityService sServiceInstance;
@@ -234,11 +246,18 @@
     private static final int EVENT_SET_DEPENDENCY_MET =
             MAX_NETWORK_STATE_TRACKER_EVENT + 10;
 
+    /**
+     * used internally to restore DNS properties back to the
+     * default network
+     */
+    private static final int EVENT_RESTORE_DNS =
+            MAX_NETWORK_STATE_TRACKER_EVENT + 11;
+
     private Handler mHandler;
 
     // list of DeathRecipients used to make sure features are turned off when
     // a process dies
-    private List mFeatureUsers;
+    private List<FeatureUser> mFeatureUsers;
 
     private boolean mSystemReady;
     private Intent mInitialBroadcast;
@@ -250,6 +269,10 @@
 
     private InetAddress mDefaultDns;
 
+    // this collection is used to refcount the added routes - if there are none left
+    // it's time to remove the route from the route table
+    private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
+
     // used in DBG mode to track inet condition reports
     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
     private ArrayList mInetLog;
@@ -332,6 +355,7 @@
 
         mNetTrackers = new NetworkStateTracker[
                 ConnectivityManager.MAX_NETWORK_TYPE+1];
+        mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
 
         mNetworkPreference = getPersistedNetworkPreference();
 
@@ -421,7 +445,7 @@
             mNetRequestersPids[i] = new ArrayList();
         }
 
-        mFeatureUsers = new ArrayList();
+        mFeatureUsers = new ArrayList<FeatureUser>();
 
         mNumDnsEntries = 0;
 
@@ -468,6 +492,8 @@
                         mNetConfigs[netType].radio);
                 continue;
             }
+            mCurrentLinkProperties[netType] = null;
+            if (mNetConfigs[netType].isDefault()) mNetTrackers[netType].reconnect();
         }
 
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -778,6 +804,20 @@
             stopUsingNetworkFeature(this, false);
         }
 
+        public boolean isSameUser(FeatureUser u) {
+            if (u == null) return false;
+
+            return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
+        }
+
+        public boolean isSameUser(int pid, int uid, int networkType, String feature) {
+            if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
+                TextUtils.equals(mFeature, feature)) {
+                return true;
+            }
+            return false;
+        }
+
         public String toString() {
             return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
                     (System.currentTimeMillis() - mCreateTime) + " mSec ago";
@@ -828,16 +868,29 @@
                     }
                 }
 
+                int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
+
                 synchronized(this) {
-                    mFeatureUsers.add(f);
+                    boolean addToList = true;
+                    if (restoreTimer < 0) {
+                        // In case there is no timer is specified for the feature,
+                        // make sure we don't add duplicate entry with the same request.
+                        for (FeatureUser u : mFeatureUsers) {
+                            if (u.isSameUser(f)) {
+                                // Duplicate user is found. Do not add.
+                                addToList = false;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (addToList) mFeatureUsers.add(f);
                     if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
                         // this gets used for per-pid dns when connected
                         mNetRequestersPids[usedNetworkType].add(currentPid);
                     }
                 }
 
-                int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
-
                 if (restoreTimer >= 0) {
                     mHandler.sendMessageDelayed(
                             mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
@@ -887,11 +940,9 @@
         boolean found = false;
 
         synchronized(this) {
-            for (int i = 0; i < mFeatureUsers.size() ; i++) {
-                u = (FeatureUser)mFeatureUsers.get(i);
-                if (uid == u.mUid && pid == u.mPid &&
-                        networkType == u.mNetworkType &&
-                        TextUtils.equals(feature, u.mFeature)) {
+            for (FeatureUser x : mFeatureUsers) {
+                if (x.isSameUser(pid, uid, networkType, feature)) {
+                    u = x;
                     found = true;
                     break;
                 }
@@ -943,11 +994,8 @@
             // do not pay attention to duplicate requests - in effect the
             // API does not refcount and a single stop will counter multiple starts.
             if (ignoreDups == false) {
-                for (int i = 0; i < mFeatureUsers.size() ; i++) {
-                    FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
-                    if (x.mUid == u.mUid && x.mPid == u.mPid &&
-                            x.mNetworkType == u.mNetworkType &&
-                            TextUtils.equals(x.mFeature, u.mFeature)) {
+                for (FeatureUser x : mFeatureUsers) {
+                    if (x.isSameUser(u)) {
                         if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
                         return 1;
                     }
@@ -1041,62 +1089,96 @@
         }
         try {
             InetAddress addr = InetAddress.getByAddress(hostAddress);
-            return addHostRoute(tracker, addr, 0);
+            LinkProperties lp = tracker.getLinkProperties();
+            return addRouteToAddress(lp, addr);
         } catch (UnknownHostException e) {}
         return false;
     }
 
-    /**
-     * Ensure that a network route exists to deliver traffic to the specified
-     * host via the mobile data network.
-     * @param hostAddress the IP address of the host to which the route is desired,
-     * in network byte order.
-     * TODO - deprecate
-     * @return {@code true} on success, {@code false} on failure
-     */
-    private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
-        LinkProperties lp = nt.getLinkProperties();
-        if ((lp == null) || (hostAddress == null)) return false;
-
-        String interfaceName = lp.getInterfaceName();
-        if (DBG) {
-            log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
-                    cycleCount);
-        }
-        if (interfaceName == null) {
-            if (DBG) loge("addHostRoute failed due to null interface name");
-            return false;
-        }
-
-        RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
-        InetAddress gatewayAddress = null;
-        if (bestRoute != null) {
-            gatewayAddress = bestRoute.getGateway();
-            // if the best route is ourself, don't relf-reference, just add the host route
-            if (hostAddress.equals(gatewayAddress)) gatewayAddress = null;
-        }
-        if (gatewayAddress != null) {
-            if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
-                loge("Error adding hostroute - too much recursion");
-                return false;
-            }
-            if (!addHostRoute(nt, gatewayAddress, cycleCount+1)) return false;
-        }
-
-        RouteInfo route = RouteInfo.makeHostRoute(hostAddress, gatewayAddress);
-
-        try {
-            mNetd.addRoute(interfaceName, route);
-            return true;
-        } catch (Exception ex) {
-            return false;
-        }
+    private boolean addRoute(LinkProperties p, RouteInfo r) {
+        return modifyRoute(p.getInterfaceName(), p, r, 0, true);
     }
 
-    // TODO support the removal of single host routes.  Keep a ref count of them so we
-    // aren't over-zealous
-    private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
-        return false;
+    private boolean removeRoute(LinkProperties p, RouteInfo r) {
+        return modifyRoute(p.getInterfaceName(), p, r, 0, false);
+    }
+
+    private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
+        return modifyRouteToAddress(lp, addr, true);
+    }
+
+    private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
+        return modifyRouteToAddress(lp, addr, false);
+    }
+
+    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
+        RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
+        if (bestRoute == null) {
+            bestRoute = RouteInfo.makeHostRoute(addr);
+        } else {
+            if (bestRoute.getGateway().equals(addr)) {
+                // if there is no better route, add the implied hostroute for our gateway
+                bestRoute = RouteInfo.makeHostRoute(addr);
+            } else {
+                // if we will connect to this through another route, add a direct route
+                // to it's gateway
+                bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
+            }
+        }
+        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
+    }
+
+    private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
+            boolean doAdd) {
+        if ((ifaceName == null) || (lp == null) || (r == null)) return false;
+
+        if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
+            loge("Error adding route - too much recursion");
+            return false;
+        }
+
+        if (r.isHostRoute() == false) {
+            RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
+            if (bestRoute != null) {
+                if (bestRoute.getGateway().equals(r.getGateway())) {
+                    // if there is no better route, add the implied hostroute for our gateway
+                    bestRoute = RouteInfo.makeHostRoute(r.getGateway());
+                } else {
+                    // if we will connect to our gateway through another route, add a direct
+                    // route to it's gateway
+                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
+                }
+                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
+            }
+        }
+        if (doAdd) {
+            if (DBG) log("Adding " + r + " for interface " + ifaceName);
+            mAddedRoutes.add(r);
+            try {
+                mNetd.addRoute(ifaceName, r);
+            } catch (Exception e) {
+                // never crash - catch them all
+                loge("Exception trying to add a route: " + e);
+                return false;
+            }
+        } else {
+            // if we remove this one and there are no more like it, then refcount==0 and
+            // we can remove it from the table
+            mAddedRoutes.remove(r);
+            if (mAddedRoutes.contains(r) == false) {
+                if (DBG) log("Removing " + r + " for interface " + ifaceName);
+                try {
+                    mNetd.removeRoute(ifaceName, r);
+                } catch (Exception e) {
+                    // never crash - catch them all
+                    loge("Exception trying to remove a route: " + e);
+                    return false;
+                }
+            } else {
+                if (DBG) log("not removing " + r + " as it's still in use");
+            }
+        }
+        return true;
     }
 
     /**
@@ -1145,9 +1227,6 @@
     public void setDataDependency(int networkType, boolean met) {
         enforceConnectivityInternalPermission();
 
-        if (DBG) {
-            log("setDataDependency(" + networkType + ", " + met + ")");
-        }
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
                 (met ? ENABLED : DISABLED), networkType));
     }
@@ -1563,49 +1642,78 @@
      * right routing table entries exist.
      */
     private void handleConnectivityChange(int netType, boolean doReset) {
+        int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
+
         /*
          * If a non-default network is enabled, add the host routes that
          * will allow it's DNS servers to be accessed.
          */
         handleDnsConfigurationChange(netType);
 
+        LinkProperties curLp = mCurrentLinkProperties[netType];
+        LinkProperties newLp = null;
+
         if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
+            newLp = mNetTrackers[netType].getLinkProperties();
+            if (VDBG) {
+                log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
+                        " doReset=" + doReset + " resetMask=" + resetMask +
+                        "\n   curLp=" + curLp +
+                        "\n   newLp=" + newLp);
+            }
+
+            if (curLp != null) {
+                if (curLp.isIdenticalInterfaceName(newLp)) {
+                    CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
+                    if ((car.removed.size() != 0) || (car.added.size() != 0)) {
+                        for (LinkAddress linkAddr : car.removed) {
+                            if (linkAddr.getAddress() instanceof Inet4Address) {
+                                resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
+                            }
+                            if (linkAddr.getAddress() instanceof Inet6Address) {
+                                resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
+                            }
+                        }
+                        if (DBG) {
+                            log("handleConnectivityChange: addresses changed" +
+                                    " linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
+                                    "\n   car=" + car);
+                        }
+                    } else {
+                        if (DBG) {
+                            log("handleConnectivityChange: address are the same reset per doReset" +
+                                   " linkProperty[" + netType + "]:" +
+                                   " resetMask=" + resetMask);
+                        }
+                    }
+                } else {
+                    resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
+                    log("handleConnectivityChange: interface not not equivalent reset both" +
+                            " linkProperty[" + netType + "]:" +
+                            " resetMask=" + resetMask);
+                }
+            }
             if (mNetConfigs[netType].isDefault()) {
                 handleApplyDefaultProxy(netType);
-                addDefaultRoute(mNetTrackers[netType]);
-            } else {
-                // many radios add a default route even when we don't want one.
-                // remove the default route unless we need it for our active network
-                if (mActiveDefaultNetwork != -1) {
-                    LinkProperties defaultLinkProperties =
-                            mNetTrackers[mActiveDefaultNetwork].getLinkProperties();
-                    LinkProperties newLinkProperties =
-                            mNetTrackers[netType].getLinkProperties();
-                    String defaultIface = defaultLinkProperties.getInterfaceName();
-                    if (defaultIface != null &&
-                            !defaultIface.equals(newLinkProperties.getInterfaceName())) {
-                        removeDefaultRoute(mNetTrackers[netType]);
-                    }
-                }
-                addPrivateDnsRoutes(mNetTrackers[netType]);
             }
         } else {
-            if (mNetConfigs[netType].isDefault()) {
-                removeDefaultRoute(mNetTrackers[netType]);
-            } else {
-                removePrivateDnsRoutes(mNetTrackers[netType]);
+            if (VDBG) {
+                log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
+                        " doReset=" + doReset + " resetMask=" + resetMask +
+                        "\n  curLp=" + curLp +
+                        "\n  newLp= null");
             }
         }
+        mCurrentLinkProperties[netType] = newLp;
+        updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
 
-        if (doReset) {
+        if (doReset || resetMask != 0) {
             LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
             if (linkProperties != null) {
                 String iface = linkProperties.getInterfaceName();
                 if (TextUtils.isEmpty(iface) == false) {
-                    if (DBG) {
-                        log("resetConnections(" + iface + ", NetworkUtils.RESET_ALL_ADDRESSES)");
-                    }
-                    NetworkUtils.resetConnections(iface, NetworkUtils.RESET_ALL_ADDRESSES);
+                    if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
+                    NetworkUtils.resetConnections(iface, resetMask);
                 }
             }
         }
@@ -1621,108 +1729,65 @@
         }
     }
 
-    private void addPrivateDnsRoutes(NetworkStateTracker nt) {
-        boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
-        LinkProperties p = nt.getLinkProperties();
-        if (p == null) return;
-        String interfaceName = p.getInterfaceName();
-
-        if (DBG) {
-            log("addPrivateDnsRoutes for " + nt +
-                    "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet);
+    /**
+     * Add and remove routes using the old properties (null if not previously connected),
+     * new properties (null if becoming disconnected).  May even be double null, which
+     * is a noop.
+     * Uses isLinkDefault to determine if default routes should be set or conversely if
+     * host routes should be set to the dns servers
+     */
+    private void updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) {
+        Collection<RouteInfo> routesToAdd = null;
+        CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
+        CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
+        if (curLp != null) {
+            // check for the delta between the current set and the new
+            routeDiff = curLp.compareRoutes(newLp);
+            dnsDiff = curLp.compareDnses(newLp);
+        } else if (newLp != null) {
+            routeDiff.added = newLp.getRoutes();
+            dnsDiff.added = newLp.getDnses();
         }
-        if (interfaceName != null && !privateDnsRouteSet) {
-            Collection<InetAddress> dnsList = p.getDnses();
-            for (InetAddress dns : dnsList) {
-                addHostRoute(nt, dns, 0);
+
+        for (RouteInfo r : routeDiff.removed) {
+            if (isLinkDefault || ! r.isDefaultRoute()) {
+                removeRoute(curLp, r);
             }
-            nt.privateDnsRouteSet(true);
         }
-    }
 
-    private void removePrivateDnsRoutes(NetworkStateTracker nt) {
-        LinkProperties p = nt.getLinkProperties();
-        if (p == null) return;
-        String interfaceName = p.getInterfaceName();
-        boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
-        if (interfaceName != null && privateDnsRouteSet) {
-            if (DBG) {
-                log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
-                        " (" + interfaceName + ")");
+        for (RouteInfo r :  routeDiff.added) {
+            if (isLinkDefault || ! r.isDefaultRoute()) {
+                addRoute(newLp, r);
             }
+        }
 
-            Collection<InetAddress> dnsList = p.getDnses();
-            for (InetAddress dns : dnsList) {
-                if (DBG) log("  removing " + dns);
-                RouteInfo route = RouteInfo.makeHostRoute(dns);
-                try {
-                    mNetd.removeRoute(interfaceName, route);
-                } catch (Exception ex) {
-                    loge("error (" + ex + ") removing dns route " + route);
+        if (!isLinkDefault) {
+            // handle DNS routes
+            if (routeDiff.removed.size() == 0 && routeDiff.added.size() == 0) {
+                // no change in routes, check for change in dns themselves
+                for (InetAddress oldDns : dnsDiff.removed) {
+                    removeRouteToAddress(curLp, oldDns);
                 }
-            }
-            nt.privateDnsRouteSet(false);
-        }
-    }
-
-
-    private void addDefaultRoute(NetworkStateTracker nt) {
-        LinkProperties p = nt.getLinkProperties();
-        if (p == null) return;
-        String interfaceName = p.getInterfaceName();
-        if (TextUtils.isEmpty(interfaceName)) return;
-
-        for (RouteInfo route : p.getRoutes()) {
-            //TODO - handle non-default routes
-            if (route.isDefaultRoute()) {
-                if (DBG) log("adding default route " + route);
-                InetAddress gateway = route.getGateway();
-                if (addHostRoute(nt, gateway, 0)) {
-                    try {
-                        mNetd.addRoute(interfaceName, route);
-                    } catch (Exception e) {
-                        loge("error adding default route " + route);
-                        continue;
+                for (InetAddress newDns : dnsDiff.added) {
+                    addRouteToAddress(newLp, newDns);
+                }
+            } else {
+                // routes changed - remove all old dns entries and add new
+                if (curLp != null) {
+                    for (InetAddress oldDns : curLp.getDnses()) {
+                        removeRouteToAddress(curLp, oldDns);
                     }
-                    if (DBG) {
-                        NetworkInfo networkInfo = nt.getNetworkInfo();
-                        log("addDefaultRoute for " + networkInfo.getTypeName() +
-                                " (" + interfaceName + "), GatewayAddr=" +
-                                gateway.getHostAddress());
+                }
+                if (newLp != null) {
+                    for (InetAddress newDns : newLp.getDnses()) {
+                        addRouteToAddress(newLp, newDns);
                     }
-                } else {
-                    loge("error adding host route for default route " + route);
                 }
             }
         }
     }
 
 
-    public void removeDefaultRoute(NetworkStateTracker nt) {
-        LinkProperties p = nt.getLinkProperties();
-        if (p == null) return;
-        String interfaceName = p.getInterfaceName();
-
-        if (interfaceName == null) return;
-
-        for (RouteInfo route : p.getRoutes()) {
-            //TODO - handle non-default routes
-            if (route.isDefaultRoute()) {
-                try {
-                    mNetd.removeRoute(interfaceName, route);
-                } catch (Exception ex) {
-                    loge("error (" + ex + ") removing default route " + route);
-                    continue;
-                }
-                if (DBG) {
-                    NetworkInfo networkInfo = nt.getNetworkInfo();
-                    log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
-                            interfaceName + ")");
-                }
-            }
-        }
-    }
-
    /**
      * Reads the network specific TCP buffer sizes from SystemProperties
      * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
@@ -1860,6 +1925,59 @@
         mContext.sendBroadcast(intent);
     }
 
+    // Caller must grab mDnsLock.
+    private boolean updateDns(String network, String iface,
+            Collection<InetAddress> dnses, String domains) {
+        boolean changed = false;
+        int last = 0;
+        if (dnses.size() == 0 && mDefaultDns != null) {
+            ++last;
+            String value = mDefaultDns.getHostAddress();
+            if (!value.equals(SystemProperties.get("net.dns1"))) {
+                if (DBG) {
+                    log("no dns provided for " + network + " - using " + value);
+                }
+                changed = true;
+                SystemProperties.set("net.dns1", value);
+            }
+        } else {
+            for (InetAddress dns : dnses) {
+                ++last;
+                String key = "net.dns" + last;
+                String value = dns.getHostAddress();
+                if (!changed && value.equals(SystemProperties.get(key))) {
+                    continue;
+                }
+                if (DBG) {
+                    log("adding dns " + value + " for " + network);
+                }
+                changed = true;
+                SystemProperties.set(key, value);
+            }
+        }
+        for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+            String key = "net.dns" + i;
+            if (DBG) log("erasing " + key);
+            changed = true;
+            SystemProperties.set(key, "");
+        }
+        mNumDnsEntries = last;
+
+        if (changed) {
+            try {
+                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
+                mNetd.setDefaultInterfaceForDns(iface);
+            } catch (Exception e) {
+                Slog.e(TAG, "exception setting default dns interface: " + e);
+            }
+        }
+        if (!domains.equals(SystemProperties.get("net.dns.search"))) {
+            SystemProperties.set("net.dns.search", domains);
+            changed = true;
+        }
+        return changed;
+    }
+
     private void handleDnsConfigurationChange(int netType) {
         // add default net's dns entries
         NetworkStateTracker nt = mNetTrackers[netType];
@@ -1869,41 +1987,19 @@
             Collection<InetAddress> dnses = p.getDnses();
             boolean changed = false;
             if (mNetConfigs[netType].isDefault()) {
-                int j = 1;
-                if (dnses.size() == 0 && mDefaultDns != null) {
-                    String dnsString = mDefaultDns.getHostAddress();
-                    if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
-                        if (DBG) {
-                            log("no dns provided - using " + dnsString);
-                        }
-                        changed = true;
-                        SystemProperties.set("net.dns1", dnsString);
-                    }
-                    j++;
-                } else {
-                    for (InetAddress dns : dnses) {
-                        String dnsString = dns.getHostAddress();
-                        if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
-                            j++;
-                            continue;
-                        }
-                        if (DBG) {
-                            log("adding dns " + dns + " for " +
-                                    nt.getNetworkInfo().getTypeName());
-                        }
-                        changed = true;
-                        SystemProperties.set("net.dns" + j++, dnsString);
+                String network = nt.getNetworkInfo().getTypeName();
+                synchronized (mDnsLock) {
+                    if (!mDnsOverridden) {
+                        changed = updateDns(network, p.getInterfaceName(), dnses, "");
                     }
                 }
-                for (int k=j ; k<mNumDnsEntries; k++) {
-                    if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
-                        if (DBG) log("erasing net.dns" + k);
-                        changed = true;
-                        SystemProperties.set("net.dns" + k, "");
-                    }
-                }
-                mNumDnsEntries = j;
             } else {
+                try {
+                    mNetd.setDnsServersForInterface(p.getInterfaceName(),
+                            NetworkUtils.makeStrings(dnses));
+                } catch (Exception e) {
+                    Slog.e(TAG, "exception setting dns servers: " + e);
+                }
                 // set per-pid dns for attached secondary nets
                 List pids = mNetRequestersPids[netType];
                 for (int y=0; y< pids.size(); y++) {
@@ -2109,6 +2205,13 @@
                     handleSetDependencyMet(msg.arg2, met);
                     break;
                 }
+                case EVENT_RESTORE_DNS:
+                {
+                    if (mActiveDefaultNetwork != -1) {
+                        handleDnsConfigurationChange(mActiveDefaultNetwork);
+                    }
+                    break;
+                }
             }
         }
     }
@@ -2174,6 +2277,15 @@
         }
     }
 
+    public int setUsbTethering(boolean enable) {
+        enforceTetherAccessPermission();
+        if (isTetheringSupported()) {
+            return mTethering.setUsbTethering(enable);
+        } else {
+            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
+        }
+    }
+
     // TODO - move iface listing, queries, etc to new module
     // javadoc from interface
     public String[] getTetherableIfaces() {
@@ -2477,8 +2589,23 @@
      * @hide
      */
     @Override
-    public void protectVpn(ParcelFileDescriptor socket) {
-        mVpn.protect(socket, getDefaultInterface());
+    public boolean protectVpn(ParcelFileDescriptor socket) {
+        try {
+            int type = mActiveDefaultNetwork;
+            if (ConnectivityManager.isNetworkTypeValid(type)) {
+                mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
+                return true;
+            }
+        } catch (Exception e) {
+            // ignore
+        } finally {
+            try {
+                socket.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        return false;
     }
 
     /**
@@ -2526,19 +2653,6 @@
         return mVpn.getLegacyVpnInfo();
     }
 
-    private String getDefaultInterface() {
-        if (ConnectivityManager.isNetworkTypeValid(mActiveDefaultNetwork)) {
-            NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork];
-            if (tracker != null) {
-                LinkProperties properties = tracker.getLinkProperties();
-                if (properties != null) {
-                    return properties.getInterfaceName();
-                }
-            }
-        }
-        throw new IllegalStateException("No default interface");
-    }
-
     /**
      * Callback for VPN subsystem. Currently VPN is not adapted to the service
      * through NetworkStateTracker since it works differently. For example, it
@@ -2554,12 +2668,57 @@
         private VpnCallback() {
         }
 
-        public synchronized void override(List<String> dnsServers, List<String> searchDomains) {
-            // TODO: override DNS servers and http proxy.
+        public void override(List<String> dnsServers, List<String> searchDomains) {
+            if (dnsServers == null) {
+                restore();
+                return;
+            }
+
+            // Convert DNS servers into addresses.
+            List<InetAddress> addresses = new ArrayList<InetAddress>();
+            for (String address : dnsServers) {
+                // Double check the addresses and remove invalid ones.
+                try {
+                    addresses.add(InetAddress.parseNumericAddress(address));
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            if (addresses.isEmpty()) {
+                restore();
+                return;
+            }
+
+            // Concatenate search domains into a string.
+            StringBuilder buffer = new StringBuilder();
+            if (searchDomains != null) {
+                for (String domain : searchDomains) {
+                    buffer.append(domain).append(' ');
+                }
+            }
+            String domains = buffer.toString().trim();
+
+            // Apply DNS changes.
+            boolean changed = false;
+            synchronized (mDnsLock) {
+                changed = updateDns("VPN", "VPN", addresses, domains);
+                mDnsOverridden = true;
+            }
+            if (changed) {
+                bumpDns();
+            }
+
+            // TODO: temporarily remove http proxy?
         }
 
-        public synchronized void restore() {
-            // TODO: restore VPN changes.
+        public void restore() {
+            synchronized (mDnsLock) {
+                if (!mDnsOverridden) {
+                    return;
+                }
+                mDnsOverridden = false;
+            }
+            mHandler.sendEmptyMessage(EVENT_RESTORE_DNS);
         }
     }
 }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 18d393f..73d790a 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -35,6 +35,7 @@
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -47,7 +48,9 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
@@ -160,9 +163,10 @@
 
     // Ongoing notification
     private final NotificationManager mNotificationManager;
+    private final KeyguardManager mKeyguardManager;
     private final Notification mImeSwitcherNotification;
     private final PendingIntent mImeSwitchPendingIntent;
-    private final boolean mShowOngoingImeSwitcherForPhones;
+    private boolean mShowOngoingImeSwitcherForPhones;
     private boolean mNotificationShown;
 
     class SessionState {
@@ -520,6 +524,8 @@
             }
         });
 
+        mKeyguardManager = (KeyguardManager)
+                mContext.getSystemService(Context.KEYGUARD_SERVICE);
         mNotificationManager = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         mImeSwitcherNotification = new Notification();
@@ -532,8 +538,8 @@
         mImeSwitcherNotification.vibrate = null;
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
         mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
-        mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
-                com.android.internal.R.bool.show_ongoing_ime_switcher);
+
+        mShowOngoingImeSwitcherForPhones = false;
 
         synchronized (mMethodMap) {
             mFileManager = new InputMethodFileManager(mMethodMap);
@@ -606,6 +612,8 @@
         synchronized (mMethodMap) {
             if (!mSystemReady) {
                 mSystemReady = true;
+                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
+                        com.android.internal.R.bool.show_ongoing_ime_switcher);
                 try {
                     startInputInnerLocked();
                 } catch (RuntimeException e) {
@@ -1041,7 +1049,16 @@
                     mStatusBar.setIconVisibility("ime", false);
                 } else if (packageName != null) {
                     if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
-                    mStatusBar.setIcon("ime", packageName, iconId, 0);
+                    CharSequence contentDescription = null;
+                    try {
+                        PackageManager packageManager = mContext.getPackageManager();
+                        contentDescription = packageManager.getApplicationLabel(
+                                packageManager.getApplicationInfo(packageName, 0));
+                    } catch (NameNotFoundException nnfe) {
+                        /* ignore */
+                    }
+                    mStatusBar.setIcon("ime", packageName, iconId, 0,
+                            contentDescription  != null ? contentDescription.toString() : null);
                     mStatusBar.setIconVisibility("ime", true);
                 }
             }
@@ -1110,13 +1127,21 @@
                 mBackDisposition = backDisposition;
                 mStatusBar.setImeWindowStatus(token, vis, backDisposition);
                 final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0;
-                if (iconVisibility && needsToShowImeSwitchOngoingNotification()) {
+                final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+                if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
                     final PackageManager pm = mContext.getPackageManager();
-                    final CharSequence label = mMethodMap.get(mCurMethodId).loadLabel(pm);
                     final CharSequence title = mRes.getText(
                             com.android.internal.R.string.select_input_method);
+                    final CharSequence imiLabel = imi.loadLabel(pm);
+                    final CharSequence summary = mCurrentSubtype != null
+                            ? TextUtils.concat(mCurrentSubtype.getDisplayName(mContext,
+                                        imi.getPackageName(), imi.getServiceInfo().applicationInfo),
+                                                (TextUtils.isEmpty(imiLabel) ?
+                                                        "" : " (" + imiLabel + ")"))
+                            : imiLabel;
+
                     mImeSwitcherNotification.setLatestEventInfo(
-                            mContext, title, label, mImeSwitchPendingIntent);
+                            mContext, title, summary, mImeSwitchPendingIntent);
                     mNotificationManager.notify(
                             com.android.internal.R.string.select_input_method,
                             mImeSwitcherNotification);
@@ -1632,19 +1657,27 @@
     }
 
     @Override
-    public boolean setAdditionalInputMethodSubtypes(IBinder token, InputMethodSubtype[] subtypes) {
-        if (token == null || mCurToken != token) {
-            return false;
-        }
-        if (subtypes == null || subtypes.length == 0) return false;
+    public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+        // By this IPC call, only a process which shares the same uid with the IME can add
+        // additional input method subtypes to the IME.
+        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return false;
         synchronized (mMethodMap) {
-            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+            final InputMethodInfo imi = mMethodMap.get(imiId);
             if (imi == null) return false;
-            final int N = subtypes.length;
-            mFileManager.addInputMethodSubtypes(imi, subtypes);
-            buildInputMethodListLocked(mMethodList, mMethodMap);
-            return true;
+            final PackageManager pm = mContext.getPackageManager();
+            final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid());
+            if (packageInfos != null) {
+                final int packageNum = packageInfos.length;
+                for (int i = 0; i < packageNum; ++i) {
+                    if (packageInfos[i].equals(imi.getPackageName())) {
+                        mFileManager.addInputMethodSubtypes(imi, subtypes);
+                        buildInputMethodListLocked(mMethodList, mMethodMap);
+                        return true;
+                    }
+                }
+            }
         }
+        return false;
     }
 
     private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
@@ -2118,7 +2151,8 @@
                         }
                     });
 
-            if (showSubtypes) {
+            if (showSubtypes && !(mKeyguardManager.isKeyguardLocked()
+                    && mKeyguardManager.isKeyguardSecure())) {
                 mDialogBuilder.setPositiveButton(
                         com.android.internal.R.string.configure_input_methods,
                         new DialogInterface.OnClickListener() {
diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/java/com/android/server/MasterClearReceiver.java
index bdb5a24..86f57d1 100644
--- a/services/java/com/android/server/MasterClearReceiver.java
+++ b/services/java/com/android/server/MasterClearReceiver.java
@@ -43,11 +43,7 @@
             @Override
             public void run() {
                 try {
-                    if (intent.hasExtra("enableEFS")) {
-                        RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false));
-                    } else {
-                        RecoverySystem.rebootWipeUserData(context);
-                    }
+                    RecoverySystem.rebootWipeUserData(context);
                     Log.wtf(TAG, "Still running after master clear?!");
                 } catch (IOException e) {
                     Slog.e(TAG, "Can't perform master clear/factory reset", e);
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 2e54c99..7f61c635 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1339,7 +1339,11 @@
             String state = mVolumeStates.get(mountPoint);
             if (state == null) {
                 Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
-                throw new IllegalArgumentException();
+                if (SystemProperties.get("vold.encrypt_progress").length() != 0) {
+                    state = Environment.MEDIA_REMOVED;
+                } else {
+                    throw new IllegalArgumentException();
+                }
             }
 
             return state;
@@ -2361,6 +2365,19 @@
                 pw.print(" -> "); pw.println(e.getValue().toString());
             }
         }
+
+        pw.println("");
+
+        synchronized (mVolumes) {
+            pw.println("  mVolumes:");
+
+            final int N = mVolumes.size();
+            for (int i = 0; i < N; i++) {
+                final StorageVolume v = mVolumes.get(i);
+                pw.print("    ");
+                pw.println(v.toString());
+            }
+        }
     }
 }
 
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 829df39..39d2b1c 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -93,6 +93,7 @@
     private static final String KEY_TX = "tx_bytes";
 
     class NetdResponseCode {
+        /* Keep in sync with system/netd/ResponseCode.h */
         public static final int InterfaceListResult       = 110;
         public static final int TetherInterfaceListResult = 111;
         public static final int TetherDnsFwdTgtListResult = 112;
@@ -108,6 +109,7 @@
         public static final int InterfaceTxThrottleResult = 219;
 
         public static final int InterfaceChange           = 600;
+        public static final int BandwidthControl          = 601;
     }
 
     /**
@@ -123,10 +125,14 @@
     private Thread mThread;
     private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
 
+    // TODO: replace with RemoteCallbackList
     private ArrayList<INetworkManagementEventObserver> mObservers;
 
+    private Object mQuotaLock = new Object();
     /** Set of interfaces with active quotas. */
-    private HashSet<String> mInterfaceQuota = Sets.newHashSet();
+    private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
+    /** Set of interfaces with active alerts. */
+    private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
     /** Set of UIDs with active reject rules. */
     private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
 
@@ -196,6 +202,9 @@
         } else {
             Slog.d(TAG, "not enabling bandwidth control");
         }
+
+        SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
+                mBandwidthControlEnabled ? "1" : "0");
     }
 
     public void registerObserver(INetworkManagementEventObserver obs) {
@@ -262,6 +271,20 @@
     }
 
     /**
+     * Notify our observers of a limit reached.
+     */
+    private void notifyLimitReached(String limitName, String iface) {
+        for (INetworkManagementEventObserver obs : mObservers) {
+            try {
+                obs.limitReached(limitName, iface);
+                Slog.d(TAG, "Observer notified limit reached for " + limitName + " " + iface);
+            } catch (Exception ex) {
+                Slog.w(TAG, "Observer notifier failed", ex);
+            }
+        }
+    }
+
+    /**
      * Let us know the daemon is connected
      */
     protected void onConnected() {
@@ -283,33 +306,52 @@
             }.start();
         }
         public boolean onEvent(int code, String raw, String[] cooked) {
-            if (code == NetdResponseCode.InterfaceChange) {
-                /*
-                 * a network interface change occured
-                 * Format: "NNN Iface added <name>"
-                 *         "NNN Iface removed <name>"
-                 *         "NNN Iface changed <name> <up/down>"
-                 *         "NNN Iface linkstatus <name> <up/down>"
-                 */
-                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
+            switch (code) {
+            case NetdResponseCode.InterfaceChange:
+                    /*
+                     * a network interface change occured
+                     * Format: "NNN Iface added <name>"
+                     *         "NNN Iface removed <name>"
+                     *         "NNN Iface changed <name> <up/down>"
+                     *         "NNN Iface linkstatus <name> <up/down>"
+                     */
+                    if (cooked.length < 4 || !cooked[1].equals("Iface")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    if (cooked[2].equals("added")) {
+                        notifyInterfaceAdded(cooked[3]);
+                        return true;
+                    } else if (cooked[2].equals("removed")) {
+                        notifyInterfaceRemoved(cooked[3]);
+                        return true;
+                    } else if (cooked[2].equals("changed") && cooked.length == 5) {
+                        notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+                        return true;
+                    } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+                        notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
+                        return true;
+                    }
                     throw new IllegalStateException(
                             String.format("Invalid event from daemon (%s)", raw));
-                }
-                if (cooked[2].equals("added")) {
-                    notifyInterfaceAdded(cooked[3]);
-                    return true;
-                } else if (cooked[2].equals("removed")) {
-                    notifyInterfaceRemoved(cooked[3]);
-                    return true;
-                } else if (cooked[2].equals("changed") && cooked.length == 5) {
-                    notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
-                    return true;
-                } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
-                    notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
-                    return true;
-                }
-                throw new IllegalStateException(
-                        String.format("Invalid event from daemon (%s)", raw));
+                    // break;
+            case NetdResponseCode.BandwidthControl:
+                    /*
+                     * Bandwidth control needs some attention
+                     * Format: "NNN limit alert <alertName> <ifaceName>"
+                     */
+                    if (cooked.length < 5 || !cooked[1].equals("limit")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    if (cooked[2].equals("alert")) {
+                        notifyLimitReached(cooked[3], cooked[4]);
+                        return true;
+                    }
+                    throw new IllegalStateException(
+                            String.format("Invalid event from daemon (%s)", raw));
+                    // break;
+            default: break;
             }
             return false;
         }
@@ -811,7 +853,6 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
         try {
-            mConnector.doCommand(String.format("softap stop " + wlanIface));
             mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP"));
             mConnector.doCommand(String.format("softap start " + wlanIface));
             if (wifiConfig == null) {
@@ -859,13 +900,15 @@
         }
     }
 
-    public void stopAccessPoint() throws IllegalStateException {
+    public void stopAccessPoint(String wlanIface) throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
         try {
             mConnector.doCommand("softap stopap");
+            mConnector.doCommand("softap stop " + wlanIface);
+            mConnector.doCommand(String.format("softap fwreload " + wlanIface + " STA"));
         } catch (NativeDaemonConnectorException e) {
             throw new IllegalStateException("Error communicating to native daemon to stop soft AP",
                     e);
@@ -1019,26 +1062,25 @@
     }
 
     @Override
-    public void setInterfaceQuota(String iface, long quota) {
+    public void setInterfaceQuota(String iface, long quotaBytes) {
         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;
+        synchronized (mQuotaLock) {
+            if (mActiveQuotaIfaces.contains(iface)) {
+                throw new IllegalStateException("iface " + iface + " already has quota");
             }
 
             final StringBuilder command = new StringBuilder();
-            command.append("bandwidth setiquota ").append(iface).append(" ").append(quota);
+            command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes);
 
             try {
-                // TODO: add support for quota shared across interfaces
+                // TODO: support quota shared across interfaces
                 mConnector.doCommand(command.toString());
-                mInterfaceQuota.add(iface);
+                mActiveQuotaIfaces.add(iface);
             } catch (NativeDaemonConnectorException e) {
                 throw new IllegalStateException("Error communicating to native daemon", e);
             }
@@ -1053,8 +1095,8 @@
         // TODO: eventually migrate to be always enabled
         if (!mBandwidthControlEnabled) return;
 
-        synchronized (mInterfaceQuota) {
-            if (!mInterfaceQuota.contains(iface)) {
+        synchronized (mQuotaLock) {
+            if (!mActiveQuotaIfaces.contains(iface)) {
                 // TODO: eventually consider throwing
                 return;
             }
@@ -1063,9 +1105,10 @@
             command.append("bandwidth removeiquota ").append(iface);
 
             try {
-                // TODO: add support for quota shared across interfaces
+                // TODO: support quota shared across interfaces
                 mConnector.doCommand(command.toString());
-                mInterfaceQuota.remove(iface);
+                mActiveQuotaIfaces.remove(iface);
+                mActiveAlertIfaces.remove(iface);
             } catch (NativeDaemonConnectorException e) {
                 throw new IllegalStateException("Error communicating to native daemon", e);
             }
@@ -1073,6 +1116,83 @@
     }
 
     @Override
+    public void setInterfaceAlert(String iface, long alertBytes) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        // quick sanity check
+        if (!mActiveQuotaIfaces.contains(iface)) {
+            throw new IllegalStateException("setting alert requires existing quota on iface");
+        }
+
+        synchronized (mQuotaLock) {
+            if (mActiveAlertIfaces.contains(iface)) {
+                throw new IllegalStateException("iface " + iface + " already has alert");
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth setinterfacealert ").append(iface).append(" ").append(
+                    alertBytes);
+
+            try {
+                // TODO: support alert shared across interfaces
+                mConnector.doCommand(command.toString());
+                mActiveAlertIfaces.add(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void removeInterfaceAlert(String iface) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        synchronized (mQuotaLock) {
+            if (!mActiveAlertIfaces.contains(iface)) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth removeinterfacealert ").append(iface);
+
+            try {
+                // TODO: support alert shared across interfaces
+                mConnector.doCommand(command.toString());
+                mActiveAlertIfaces.remove(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void setGlobalAlert(long alertBytes) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        final StringBuilder command = new StringBuilder();
+        command.append("bandwidth setglobalalert ").append(alertBytes);
+
+        try {
+            mConnector.doCommand(command.toString());
+        } 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);
 
@@ -1336,18 +1456,17 @@
         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();
+                InetAddress a = NetworkUtils.numericToInetAddress(s);
+                if (a.isAnyLocalAddress() == false) {
+                    cmd += " " + a.getHostAddress();
                 }
             }
-
             mConnector.doCommand(cmd);
-        } catch (UnknownHostException e) {
-            throw new IllegalStateException("failed to resolve dns address.", e);
+        } catch (IllegalArgumentException e) {
+            throw new IllegalStateException("Error setting dnsn for interface", e);
         } catch (NativeDaemonConnectorException e) {
             throw new IllegalStateException(
-                    "Error communicating with native deamon to set dns for interface", e);
+                    "Error communicating with native daemon to set dns for interface", e);
         }
     }
 
@@ -1373,7 +1492,7 @@
             mConnector.doCommand(cmd);
         } catch (NativeDaemonConnectorException e) {
             throw new IllegalStateException(
-                    "Error communicating with native deamon to flush interface " + iface, e);
+                    "Error communicating with native daemon to flush interface " + iface, e);
         }
     }
 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 4ecdfed..8031c4e 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -262,7 +262,7 @@
 
         public void onNotificationClick(String pkg, String tag, int id) {
             cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
-                    Notification.FLAG_FOREGROUND_SERVICE, true);
+                    Notification.FLAG_FOREGROUND_SERVICE, false);
         }
 
         public void onNotificationClear(String pkg, String tag, int id) {
@@ -469,6 +469,24 @@
                     record = mToastQueue.get(index);
                     record.update(duration);
                 } else {
+                    // Limit the number of toasts that any given package except the android
+                    // package can enqueue.  Prevents DOS attacks and deals with leaks.
+                    if (!"android".equals(pkg)) {
+                        int count = 0;
+                        final int N = mToastQueue.size();
+                        for (int i=0; i<N; i++) {
+                             final ToastRecord r = mToastQueue.get(i);
+                             if (r.pkg.equals(pkg)) {
+                                 count++;
+                                 if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+                                     Slog.e(TAG, "Package has already posted " + count
+                                            + " toasts. Not showing more. Package=" + pkg);
+                                     return;
+                                 }
+                             }
+                        }
+                    }
+
                     record = new ToastRecord(callingPid, pkg, callback, duration);
                     mToastQueue.add(record);
                     index = mToastQueue.size() - 1;
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 286a937..4ced83c 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -22,10 +22,10 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Slog;
 import android.view.View;
 
@@ -175,7 +175,8 @@
         }
     }
 
-    public void setIcon(String slot, String iconPackage, int iconId, int iconLevel) {
+    public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
+            String contentDescription) {
         enforceStatusBar();
 
         synchronized (mIcons) {
@@ -184,7 +185,8 @@
                 throw new SecurityException("invalid status bar icon slot: " + slot);
             }
 
-            StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel);
+            StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0,
+                    contentDescription);
             //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
             mIcons.setIcon(index, icon);
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8c7e279..f15eca6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -37,6 +37,7 @@
 import android.server.BluetoothA2dpService;
 import android.server.BluetoothService;
 import android.server.search.SearchManagerService;
+import android.server.WifiP2pService;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Slog;
@@ -108,6 +109,7 @@
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
+        WifiP2pService wifiP2p = null;
         IPackageManager pm = null;
         Context context = null;
         WindowManagerService wm = null;
@@ -230,6 +232,7 @@
         WallpaperManagerService wallpaper = null;
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
+        TextServicesManagerService tsms = null;
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
             try {
@@ -273,6 +276,14 @@
             }
 
             try {
+                Slog.i(TAG, "Text Service Manager Service");
+                tsms = new TextServicesManagerService(context);
+                ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting Text Service Manager Service", e);
+            }
+
+            try {
                 Slog.i(TAG, "NetworkStats Service");
                 networkStats = new NetworkStatsService(context, networkManagement, alarm);
                 ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
@@ -290,6 +301,14 @@
                 Slog.e(TAG, "Failure starting NetworkPolicy Service", e);
             }
 
+           try {
+                Slog.i(TAG, "Wi-Fi P2pService");
+                wifiP2p = new WifiP2pService(context);
+                ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting Wi-Fi P2pService", e);
+            }
+
             try {
                 Slog.i(TAG, "Connectivity Service");
                 connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
@@ -538,6 +557,7 @@
         final LocationManagerService locationF = location;
         final CountryDetectorService countryDetectorF = countryDetector;
         final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
+        final TextServicesManagerService textServiceManagerServiceF = tsms;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -571,6 +591,7 @@
                 if (countryDetectorF != null) countryDetectorF.systemReady();
                 if (throttleF != null) throttleF.systemReady();
                 if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady();
+                if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
             }
         });
 
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
new file mode 100644
index 0000000..3e76a3a1
--- /dev/null
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.service.textservice.SpellCheckerService;
+import android.util.Log;
+import android.util.Slog;
+import android.view.textservice.SpellCheckerInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class TextServicesManagerService extends ITextServicesManager.Stub {
+    private static final String TAG = TextServicesManagerService.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private final Context mContext;
+    private boolean mSystemReady;
+    private final TextServicesMonitor mMonitor;
+    private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap =
+            new HashMap<String, SpellCheckerInfo>();
+    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>();
+    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups =
+            new HashMap<String, SpellCheckerBindGroup>();
+
+    public void systemReady() {
+        if (!mSystemReady) {
+            mSystemReady = true;
+        }
+    }
+
+    public TextServicesManagerService(Context context) {
+        mSystemReady = false;
+        mContext = context;
+        mMonitor = new TextServicesMonitor();
+        mMonitor.register(context, true);
+        synchronized (mSpellCheckerMap) {
+            buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
+        }
+    }
+
+    private class TextServicesMonitor extends PackageMonitor {
+        @Override
+        public void onSomePackagesChanged() {
+            synchronized (mSpellCheckerMap) {
+                buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap);
+                // TODO: Update for each locale
+                SpellCheckerInfo sci = getCurrentSpellChecker(null);
+                if (sci == null) return;
+                final String packageName = sci.getPackageName();
+                final int change = isPackageDisappearing(packageName);
+                if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
+                    // Package disappearing
+                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                } else if (isPackageModified(packageName)) {
+                    // Package modified
+                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                }
+            }
+        }
+    }
+
+    private static void buildSpellCheckerMapLocked(Context context,
+            ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map) {
+        list.clear();
+        map.clear();
+        final PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> services = pm.queryIntentServices(
+                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+        final int N = services.size();
+        for (int i = 0; i < N; ++i) {
+            final ResolveInfo ri = services.get(i);
+            final ServiceInfo si = ri.serviceInfo;
+            final ComponentName compName = new ComponentName(si.packageName, si.name);
+            if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) {
+                Slog.w(TAG, "Skipping text service " + compName
+                        + ": it does not require the permission "
+                        + android.Manifest.permission.BIND_TEXT_SERVICE);
+                continue;
+            }
+            if (DBG) Slog.d(TAG, "Add: " + compName);
+            final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri);
+            list.add(sci);
+            map.put(sci.getId(), sci);
+        }
+        if (DBG) {
+            Slog.d(TAG, "buildSpellCheckerMapLocked: " + list.size() + "," + map.size());
+        }
+    }
+
+    // TODO: find an appropriate spell checker for specified locale
+    private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) {
+        final int spellCheckersCount = mSpellCheckerList.size();
+        if (spellCheckersCount == 0) {
+            Slog.w(TAG, "no available spell checker services found");
+            return null;
+        }
+        if (prefPackage != null) {
+            for (int i = 0; i < spellCheckersCount; ++i) {
+                final SpellCheckerInfo sci = mSpellCheckerList.get(i);
+                if (prefPackage.equals(sci.getPackageName())) {
+                    if (DBG) {
+                        Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName());
+                    }
+                    return sci;
+                }
+            }
+        }
+        if (spellCheckersCount > 1) {
+            Slog.w(TAG, "more than one spell checker service found, picking first");
+        }
+        return mSpellCheckerList.get(0);
+    }
+
+    // TODO: Save SpellCheckerService by supported languages. Currently only one spell
+    // checker is saved.
+    @Override
+    public SpellCheckerInfo getCurrentSpellChecker(String locale) {
+        synchronized (mSpellCheckerMap) {
+            String curSpellCheckerId =
+                    Settings.Secure.getString(mContext.getContentResolver(),
+                            Settings.Secure.SPELL_CHECKER_SERVICE);
+            if (DBG) {
+                Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
+            }
+            if (TextUtils.isEmpty(curSpellCheckerId)) {
+                final SpellCheckerInfo sci = findAvailSpellCheckerLocked(null, null);
+                if (sci == null) return null;
+                // Set the current spell checker if there is one or more spell checkers
+                // available. In this case, "sci" is the first one in the available spell
+                // checkers.
+                setCurrentSpellChecker(sci);
+                return sci;
+            }
+            return mSpellCheckerMap.get(curSpellCheckerId);
+        }
+    }
+
+    @Override
+    public void getSpellCheckerService(SpellCheckerInfo info, String locale,
+            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
+        if (!mSystemReady) {
+            return;
+        }
+        if (info == null || tsListener == null) {
+            Slog.e(TAG, "getSpellCheckerService: Invalid input.");
+            return;
+        }
+        final String sciId = info.getId();
+        synchronized(mSpellCheckerMap) {
+            if (!mSpellCheckerMap.containsKey(sciId)) {
+                return;
+            }
+            if (mSpellCheckerBindGroups.containsKey(sciId)) {
+                mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener);
+                return;
+            }
+            final InternalServiceConnection connection = new InternalServiceConnection(
+                    sciId, locale, scListener);
+            final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
+            serviceIntent.setComponent(info.getComponent());
+            if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+                Slog.e(TAG, "Failed to get a spell checker service.");
+                return;
+            }
+            final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
+                    connection, tsListener, locale, scListener);
+            mSpellCheckerBindGroups.put(sciId, group);
+        }
+        return;
+    }
+
+    @Override
+    public SpellCheckerInfo[] getEnabledSpellCheckers() {
+        if (DBG) {
+            Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size());
+            for (int i = 0; i < mSpellCheckerList.size(); ++i) {
+                Slog.d(TAG, "EnabledSpellCheckers: " + mSpellCheckerList.get(i).getPackageName());
+            }
+        }
+        return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]);
+    }
+
+    @Override
+    public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+        if (DBG) {
+            Slog.d(TAG, "FinishSpellCheckerService");
+        }
+        synchronized(mSpellCheckerMap) {
+            for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
+                if (group == null) continue;
+                group.removeListener(listener);
+            }
+        }
+    }
+
+    private void setCurrentSpellChecker(SpellCheckerInfo sci) {
+        if (DBG) {
+            Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
+        }
+        if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
+        Settings.Secure.putString(mContext.getContentResolver(),
+                Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+    }
+
+    // SpellCheckerBindGroup contains active text service session listeners.
+    // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
+    // mSpellCheckerBindGroups
+    private class SpellCheckerBindGroup {
+        final InternalServiceConnection mInternalConnection;
+        final ArrayList<InternalDeathRecipient> mListeners =
+                new ArrayList<InternalDeathRecipient>();
+
+        public SpellCheckerBindGroup(InternalServiceConnection connection,
+                ITextServicesSessionListener listener, String locale,
+                ISpellCheckerSessionListener scListener) {
+            mInternalConnection = connection;
+            addListener(listener, locale, scListener);
+        }
+
+        public void onServiceConnected(ISpellCheckerService spellChecker) {
+            if (DBG) {
+                Slog.d(TAG, "onServiceConnected");
+            }
+            synchronized(mSpellCheckerMap) {
+                for (InternalDeathRecipient listener : mListeners) {
+                    try {
+                        final ISpellCheckerSession session = spellChecker.getISpellCheckerSession(
+                                listener.mScLocale, listener.mScListener);
+                        listener.mTsListener.onServiceConnected(session);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+
+        public void addListener(ITextServicesSessionListener tsListener, String locale,
+                ISpellCheckerSessionListener scListener) {
+            if (DBG) {
+                Slog.d(TAG, "addListener: " + locale);
+            }
+            synchronized(mSpellCheckerMap) {
+                try {
+                    final int size = mListeners.size();
+                    for (int i = 0; i < size; ++i) {
+                        if (mListeners.get(i).hasSpellCheckerListener(scListener)) {
+                            // do not add the lister if the group already contains this.
+                            return;
+                        }
+                    }
+                    final InternalDeathRecipient recipient = new InternalDeathRecipient(
+                            this, tsListener, locale, scListener);
+                    scListener.asBinder().linkToDeath(recipient, 0);
+                    mListeners.add(new InternalDeathRecipient(
+                            this, tsListener, locale, scListener));
+                } catch(RemoteException e) {
+                    // do nothing
+                }
+                cleanLocked();
+            }
+        }
+
+        public void removeListener(ISpellCheckerSessionListener listener) {
+            if (DBG) {
+                Slog.d(TAG, "remove listener");
+            }
+            synchronized(mSpellCheckerMap) {
+                final int size = mListeners.size();
+                final ArrayList<InternalDeathRecipient> removeList =
+                        new ArrayList<InternalDeathRecipient>();
+                for (int i = 0; i < size; ++i) {
+                    final InternalDeathRecipient tempRecipient = mListeners.get(i);
+                    if(tempRecipient.hasSpellCheckerListener(listener)) {
+                        removeList.add(tempRecipient);
+                    }
+                }
+                final int removeSize = removeList.size();
+                for (int i = 0; i < removeSize; ++i) {
+                    mListeners.remove(removeList.get(i));
+                }
+                cleanLocked();
+            }
+        }
+
+        private void cleanLocked() {
+            if (DBG) {
+                Slog.d(TAG, "cleanLocked");
+            }
+            if (mListeners.isEmpty()) {
+                mSpellCheckerBindGroups.remove(this);
+                // Unbind service when there is no active clients.
+                mContext.unbindService(mInternalConnection);
+            }
+        }
+    }
+
+    private class InternalServiceConnection implements ServiceConnection {
+        private final ISpellCheckerSessionListener mListener;
+        private final String mSciId;
+        private final String mLocale;
+        public InternalServiceConnection(
+                String id, String locale, ISpellCheckerSessionListener listener) {
+            mSciId = id;
+            mLocale = locale;
+            mListener = listener;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized(mSpellCheckerMap) {
+                ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
+                final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
+                if (group != null) {
+                    group.onServiceConnected(spellChecker);
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mSpellCheckerBindGroups.remove(mSciId);
+        }
+    }
+
+    private class InternalDeathRecipient implements IBinder.DeathRecipient {
+        public final ITextServicesSessionListener mTsListener;
+        public final ISpellCheckerSessionListener mScListener;
+        public final String mScLocale;
+        private final SpellCheckerBindGroup mGroup;
+        public InternalDeathRecipient(SpellCheckerBindGroup group,
+                ITextServicesSessionListener tsListener, String scLocale,
+                ISpellCheckerSessionListener scListener) {
+            mTsListener = tsListener;
+            mScListener = scListener;
+            mScLocale = scLocale;
+            mGroup = group;
+        }
+
+        public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
+            return mScListener.equals(listener);
+        }
+
+        @Override
+        public void binderDied() {
+            mGroup.removeListener(mScListener);
+        }
+    }
+}
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index b8890aa..cd649ce 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -194,6 +194,7 @@
         }
 
         public void interfaceRemoved(String iface) {}
+        public void limitReached(String limitName, String iface) {}
     }
 
 
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index c39dc80..de25747 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -383,6 +383,12 @@
             if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 synchronized (mVibrations) {
                     doCancelVibrateLocked();
+
+                    int size = mVibrations.size();
+                    for(int i = 0; i < size; i++) {
+                        unlinkVibration(mVibrations.get(i));
+                    }
+
                     mVibrations.clear();
                 }
             }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5f0922e..f9f63b1 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -35,8 +35,8 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiStateMachine;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiWatchdogStateMachine;
 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;
@@ -343,7 +343,7 @@
      * Protected by mWifiStateTracker lock.
      */
     private final WorkSource mTmpWorkSource = new WorkSource();
-    private WifiWatchdogService mWifiWatchdogService;
+    private WifiWatchdogStateMachine mWifiWatchdogStateMachine;
 
     WifiService(Context context) {
         mContext = context;
@@ -434,8 +434,9 @@
                 (wifiEnabled ? "enabled" : "disabled"));
         setWifiEnabled(wifiEnabled);
 
-        //TODO: as part of WWS refactor, create only when needed
-        mWifiWatchdogService = new WifiWatchdogService(mContext);
+        mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
+               makeWifiWatchdogStateMachine(mContext);
+
     }
 
     private boolean testAndClearWifiSavedState() {
@@ -1162,8 +1163,8 @@
         mLocks.dump(pw);
 
         pw.println();
-        pw.println("WifiWatchdogService dump");
-        mWifiWatchdogService.dump(pw);
+        pw.println("WifiWatchdogStateMachine dump");
+        mWifiWatchdogStateMachine.dump(pw);
     }
 
     private class WifiLock extends DeathRecipient {
@@ -1460,7 +1461,7 @@
             if (mMulticasters.size() != 0) {
                 return;
             } else {
-                mWifiStateMachine.startPacketFiltering();
+                mWifiStateMachine.startFilteringMulticastV4Packets();
             }
         }
     }
@@ -1471,11 +1472,11 @@
         synchronized (mMulticasters) {
             mMulticastEnabled++;
             mMulticasters.add(new Multicaster(tag, binder));
-            // Note that we could call stopPacketFiltering only when
+            // Note that we could call stopFilteringMulticastV4Packets only when
             // our new size == 1 (first call), but this function won't
             // be called often and by making the stopPacket call each
             // time we're less fragile and self-healing.
-            mWifiStateMachine.stopPacketFiltering();
+            mWifiStateMachine.stopFilteringMulticastV4Packets();
         }
 
         int uid = Binder.getCallingUid();
@@ -1512,7 +1513,7 @@
             removed.unlinkDeathRecipient();
         }
         if (mMulticasters.size() == 0) {
-            mWifiStateMachine.startPacketFiltering();
+            mWifiStateMachine.startFilteringMulticastV4Packets();
         }
 
         Long ident = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 80cdf6b..d0f8843 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -49,6 +49,7 @@
 import android.view.IWindow;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -127,13 +128,15 @@
 
     private int mHandledFeedbackTypes = 0;
 
-    private boolean mIsEnabled;
+    private boolean mIsAccessibilityEnabled;
 
     private AccessibilityInputFilter mInputFilter;
 
+    private boolean mHasInputFilter;
+
     private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
 
-    private boolean mHasInputFilter;
+    private boolean mIsTouchExplorationEnabled;
 
     private final WindowManagerService mWindowManagerService;
 
@@ -187,7 +190,7 @@
                     manageServicesLocked();
                 }
             }
-            
+
             @Override
             public boolean onHandleForceStop(Intent intent, String[] packages,
                     int uid, boolean doit) {
@@ -230,16 +233,20 @@
                 if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
                     synchronized (mLock) {
                         populateAccessibilityServiceListLocked();
-                        // get the accessibility enabled setting on boot
-                        mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                        // get accessibility enabled setting on boot
+                        mIsAccessibilityEnabled = Settings.Secure.getInt(
+                                mContext.getContentResolver(),
                                 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
 
-                        // if accessibility is enabled inform our clients we are on
-                        if (mIsEnabled) {
-                            updateClientsLocked();
-                        }
-
                         manageServicesLocked();
+
+                        // get touch exploration enabled setting on boot
+                        mIsTouchExplorationEnabled = Settings.Secure.getInt(
+                                mContext.getContentResolver(),
+                                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+                        updateInputFilterLocked();
+
+                        sendStateToClientsLocked();
                     }
                     
                     return;
@@ -264,29 +271,49 @@
     private void registerSettingsContentObservers() {
         ContentResolver contentResolver = mContext.getContentResolver();
 
-        Uri enabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED);
-        contentResolver.registerContentObserver(enabledUri, false,
+        Uri accessibilityEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_ENABLED);
+        contentResolver.registerContentObserver(accessibilityEnabledUri, false,
             new ContentObserver(new Handler()) {
                 @Override
                 public void onChange(boolean selfChange) {
                     super.onChange(selfChange);
 
                     synchronized (mLock) {
-                        mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                        mIsAccessibilityEnabled = Settings.Secure.getInt(
+                                mContext.getContentResolver(),
                                 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-                        if (mIsEnabled) {
+                        if (mIsAccessibilityEnabled) {
                             manageServicesLocked();
                         } else {
                             unbindAllServicesLocked();
                         }
-                        updateClientsLocked();
+                        sendStateToClientsLocked();
                     }
                 }
             });
 
-        Uri providersUri =
+        Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
+                Settings.Secure.TOUCH_EXPLORATION_ENABLED);
+        contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
+                new ContentObserver(new Handler()) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        super.onChange(selfChange);
+
+                        synchronized (mLock) {
+                            mIsTouchExplorationEnabled = Settings.Secure.getInt(
+                                    mContext.getContentResolver(),
+                                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+                            updateInputFilterLocked();
+                            sendStateToClientsLocked();
+                        }
+                    }
+                });
+
+        Uri accessibilityServicesUri =
             Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        contentResolver.registerContentObserver(providersUri, false,
+        contentResolver.registerContentObserver(accessibilityServicesUri, false,
             new ContentObserver(new Handler()) {
                 @Override
                 public void onChange(boolean selfChange) {
@@ -299,7 +326,7 @@
             });
     }
 
-    public boolean addClient(IAccessibilityManagerClient client) throws RemoteException {
+    public int addClient(IAccessibilityManagerClient client) throws RemoteException {
         synchronized (mLock) {
             final IAccessibilityManagerClient addedClient = client;
             mClients.add(addedClient);
@@ -312,7 +339,7 @@
                     }
                 }
             }, 0);
-            return mIsEnabled;
+            return getState();
         }
     }
 
@@ -727,7 +754,7 @@
             Set<ComponentName> enabledServices) {
 
         Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
-        boolean isEnabled = mIsEnabled;
+        boolean isEnabled = mIsAccessibilityEnabled;
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = installedServices.get(i);
@@ -741,7 +768,7 @@
                         service = new Service(componentName, installedService, false);
                     }
                     service.bind();
-                } else if (!enabledServices.contains(componentName)) {
+                } else {
                     if (service != null) {
                         service.unbind();
                     }
@@ -755,12 +782,13 @@
     }
 
     /**
-     * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients.
+     * Sends the state to the clients.
      */
-    private void updateClientsLocked() {
+    private void sendStateToClientsLocked() {
+        final int state = getState();
         for (int i = 0, count = mClients.size(); i < count; i++) {
             try {
-                mClients.get(i).setEnabled(mIsEnabled);
+                mClients.get(i).setState(state);
             } catch (RemoteException re) {
                 mClients.remove(i);
                 count--;
@@ -770,29 +798,39 @@
     }
 
     /**
-     * Updates the input filter state. The filter is enabled if accessibility
-     * is enabled and there is at least one accessibility service providing
-     * spoken feedback.
+     * Gets the current state as a set of flags.
+     *
+     * @return The state.
+     */
+    private int getState() {
+        int state = 0;
+        if (mIsAccessibilityEnabled) {
+            state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+        }
+        // Touch exploration relies on enabled accessibility.
+        if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+            state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+        }
+        return state;
+    }
+
+    /**
+     * Updates the touch exploration state.
      */
     private void updateInputFilterLocked() {
-        if (mIsEnabled) {
-            final boolean hasSpokenFeedbackServices = !getEnabledAccessibilityServiceList(
-                    AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
-            if (hasSpokenFeedbackServices) {
-                if (mHasInputFilter) {
-                    return;
-                }
+        if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+            if (!mHasInputFilter) {
+                mHasInputFilter = true;
                 if (mInputFilter == null) {
                     mInputFilter = new AccessibilityInputFilter(mContext);
                 }
                 mWindowManagerService.setInputFilter(mInputFilter);
-                mHasInputFilter = true;
-                return;
             }
+            return;
         }
         if (mHasInputFilter) {
-            mWindowManagerService.setInputFilter(null);
             mHasInputFilter = false;
+            mWindowManagerService.setInputFilter(null);
         }
     }
 
@@ -935,9 +973,11 @@
             }
         }
 
-        public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) {
+        public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId)
+                throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
                 if (!permissionGranted) {
                     return null;
@@ -975,15 +1015,16 @@
         }
 
         public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
-                String text) {
+                String text) throws RemoteException {
             return findAccessibilityNodeInfosByViewText(text,
                     mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID);
         }
 
         public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text,
-                int accessibilityWindowId, int accessibilityViewId) {
+                int accessibilityWindowId, int accessibilityViewId) throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
                 if (!permissionGranted) {
@@ -1026,9 +1067,10 @@
         }
 
         public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
-                int accessibilityWindowId, int accessibilityViewId) {
+                int accessibilityWindowId, int accessibilityViewId) throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
                 if (!permissionGranted) {
@@ -1155,9 +1197,7 @@
             | AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
 
         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
-            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END
-            | AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START
-            | AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED
+            AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED
             | 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
@@ -1165,6 +1205,10 @@
             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
             | AccessibilityEvent.TYPE_VIEW_SCROLLED;
 
+        private static final int RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES =
+            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
+            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT;
+
         private int mRetrievalAlowingWindowId;
 
         private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
@@ -1176,9 +1220,10 @@
         public void updateRetrievalAllowingWindowAndEventSourceLocked(AccessibilityEvent event) {
             final int windowId = event.getWindowId();
             final int eventType = event.getEventType();
-            if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) != 0) {
+            if ((eventType & RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES) != 0) {
                 mRetrievalAlowingWindowId = windowId;
-            } else { 
+            }
+            if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
                 event.setSource(null);
             }
         }
@@ -1201,6 +1246,15 @@
             return service.mCanRetrieveScreenContent;
         }
 
+        public void enforceCanRetrieveWindowContent(Service service) throws RemoteException {
+            // This happens due to incorrect registration so make it apparent.
+            if (!canRetrieveWindowContent(service)) {
+                Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " +
+                        "declare android:canRetrieveWindowContent.");
+                throw new RemoteException();
+            }
+        }
+
         private boolean isRetrievalAllowingWindow(int windowId) {
             return (mRetrievalAlowingWindowId == windowId);
         }
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 1af7015..0ad58d0 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -19,21 +19,21 @@
 import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END;
 import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START;
 
-import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
-import com.android.server.wm.InputFilter;
-
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.WindowManagerPolicy;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
+import android.view.ViewConfiguration;
+import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
+import com.android.server.wm.InputFilter;
+
 import java.util.Arrays;
 
 /**
@@ -116,9 +116,6 @@
     // which would perform a click and tapping and holding a long press.
     private final int mTouchExplorationTapSlop;
 
-    // Context handle for accessing resources.
-    private final Context mContext;
-
     // The InputFilter this tracker is associated with i.e. the filter
     // which delegates event processing to this touch explorer.
     private final InputFilter mInputFilter;
@@ -149,6 +146,9 @@
     // Command for delayed sending of a hover event.
     private final SendHoverDelayed mSendHoverDelayed;
 
+    // Command for delayed sending of a long press.
+    private final PerformLongPressDelayed mPerformLongPressDelayed;
+
     /**
      * Creates a new instance.
      *
@@ -161,9 +161,9 @@
             ViewConfiguration.get(context).getScaledTouchExplorationTapSlop();
         mDraggingDistance = mTouchExplorationTapSlop * COEFFICIENT_DRAGGING_DISTANCE;
         mPointerTracker = new PointerTracker(context);
-        mContext = context;
         mHandler = new Handler(context.getMainLooper());
         mSendHoverDelayed = new SendHoverDelayed();
+        mPerformLongPressDelayed = new PerformLongPressDelayed();
         mAccessibilityManager = AccessibilityManager.getInstance(context);
     }
 
@@ -212,14 +212,7 @@
         final int activePointerCount = pointerTracker.getActivePointerCount();
 
         switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN: {
-                // Send a hover for every finger down so the user gets feedback
-                // where she is currently touching.
-                mSendHoverDelayed.forceSendAndRemove();
-                final int pointerIdBits = (1 << event.getActionIndex());
-                mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits,
-                        policyFlags, DELAY_SEND_HOVER_MOVE);
-            } break;
+            case MotionEvent.ACTION_DOWN:
             case MotionEvent.ACTION_POINTER_DOWN: {
                 switch (activePointerCount) {
                     case 0: {
@@ -227,13 +220,13 @@
                                 + "touch exploring state!");
                     }
                     case 1: {
-                        // Schedule a hover event which will lead to firing an
-                        // accessibility event from the hovered view.
-                        mSendHoverDelayed.remove();
+                        // Send hover if pending.
+                        mSendHoverDelayed.forceSendAndRemove();
+                        // Send a hover for every finger down so the user gets feedback.
                         final int pointerId = pointerTracker.getPrimaryActivePointerId();
                         final int pointerIdBits = (1 << pointerId);
                         final int lastAction = pointerTracker.getLastInjectedHoverAction();
-                        // If a schedules hover enter for another pointer is delivered we send move.
+                        // If a hover enter for another pointer is delivered we send move.
                         final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER)
                                 ? MotionEvent.ACTION_HOVER_MOVE
                                 : MotionEvent.ACTION_HOVER_ENTER;
@@ -247,7 +240,19 @@
                         // If more pointers down on the screen since the last touch
                         // exploration we discard the last cached touch explore event.
                         if (event.getPointerCount() != mLastTouchExploreEvent.getPointerCount()) {
-                           mLastTouchExploreEvent = null;
+                            mLastTouchExploreEvent = null;
+                            break;
+                        }
+
+                        // If the down is in the time slop => schedule a long press.
+                        final long pointerDownTime =
+                            pointerTracker.getReceivedPointerDownTime(pointerId);
+                        final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
+                        final long deltaTimeExplore = pointerDownTime - lastExploreTime;
+                        if (deltaTimeExplore <= ACTIVATION_TIME_SLOP) {
+                            mPerformLongPressDelayed.post(event, policyFlags,
+                                    ViewConfiguration.getLongPressTimeout());
+                            break;
                         }
                     } break;
                     default: {
@@ -278,6 +283,7 @@
                                 sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
                                 // Make sure the scheduled down/move event is sent.
                                 mSendHoverDelayed.forceSendAndRemove();
+                                mPerformLongPressDelayed.remove();
                                 // If we have transitioned to exploring state from another one
                                 // we need to send a hover enter event here.
                                 final int lastAction = mPointerTracker.getLastInjectedHoverAction();
@@ -294,20 +300,11 @@
                                     policyFlags);
                         }
 
-                        // Detect long press on the last touch explored position.
-                        if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null) {
+                        // If the exploring pointer moved enough => cancel the long press.
+                        if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null
+                                && mPerformLongPressDelayed.isPenidng()) {
 
-                            // If the down was not in the time slop => nothing else to do.
-                            final long pointerDownTime =
-                                pointerTracker.getReceivedPointerDownTime(pointerId);
-                            final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
-                            final long deltaTimeExplore = pointerDownTime - lastExploreTime;
-                            if (deltaTimeExplore > ACTIVATION_TIME_SLOP) {
-                                mLastTouchExploreEvent = null;
-                                break;
-                            }
-
-                            // If the pointer moved more than the tap slop => nothing else to do.
+                            // If the pointer moved more than the tap slop => cancel long press.
                             final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
                                     - event.getX(pointerIndex);
                             final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
@@ -315,24 +312,14 @@
                             final float moveDelta = (float) Math.hypot(deltaX, deltaY);
                             if (moveDelta > mTouchExplorationTapSlop) {
                                 mLastTouchExploreEvent = null;
+                                mPerformLongPressDelayed.remove();
                                break;
                             }
-
-                            // If down for long enough we get a long press.
-                            final long deltaTimeMove = event.getEventTime() - pointerDownTime;
-                            if (deltaTimeMove > ViewConfiguration.getLongPressTimeout()) {
-                                mCurrentState = STATE_DELEGATING;
-                                // Make sure the scheduled hover exit is delivered.
-                                mSendHoverDelayed.forceSendAndRemove();
-                                sendDownForAllActiveNotInjectedPointers(event, policyFlags);
-                                sendMotionEvent(event, policyFlags);
-                                mTouchExploreGestureInProgress = false;
-                                mLastTouchExploreEvent = null;
-                            }
                         }
                     } break;
                     case 2: {
                         mSendHoverDelayed.forceSendAndRemove();
+                        mPerformLongPressDelayed.remove();
                         // We want to no longer hover over the location so subsequent
                         // touch at the same spot will generate a hover enter.
                         sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -363,6 +350,7 @@
                     } break;
                     default: {
                         mSendHoverDelayed.forceSendAndRemove();
+                        mPerformLongPressDelayed.remove();
                         // We want to no longer hover over the location so subsequent
                         // touch at the same spot will generate a hover enter.
                         sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -391,22 +379,26 @@
                             break;
                         }
 
+                        mSendHoverDelayed.forceSendAndRemove();
+                        mPerformLongPressDelayed.remove();
+
                         // If touch exploring announce the end of the gesture.
+                        // Also do not click on the last explored location.
                         if (mTouchExploreGestureInProgress) {
-                            sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
                             mTouchExploreGestureInProgress = false;
+                            mLastTouchExploreEvent = MotionEvent.obtain(event);
+                            sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
+                            break;
                         }
 
                         // Detect whether to activate i.e. click on the last explored location.
                         if (mLastTouchExploreEvent != null) {
-
                             // If the down was not in the time slop => nothing else to do.
                             final long eventTime =
                                 pointerTracker.getLastReceivedUpPointerDownTime();
                             final long exploreTime = mLastTouchExploreEvent.getEventTime();
                             final long deltaTime = eventTime - exploreTime;
                             if (deltaTime > ACTIVATION_TIME_SLOP) {
-                                mSendHoverDelayed.forceSendAndRemove();
                                 final int lastAction = mPointerTracker.getLastInjectedHoverAction();
                                 if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
                                     sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -416,15 +408,14 @@
                                 break;
                             }
 
-                            // If the pointer moved more than the tap slop => nothing else to do.
+                            // If a tap is farther than the tap slop => nothing to do.
                             final int pointerIndex = event.findPointerIndex(pointerId);
-                            final float deltaX = pointerTracker.getLastReceivedUpPointerDownX()
+                            final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
                                     - event.getX(pointerIndex);
-                            final float deltaY = pointerTracker.getLastReceivedUpPointerDownY()
+                            final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
                                     - event.getY(pointerIndex);
                             final float deltaMove = (float) Math.hypot(deltaX, deltaY);
                             if (deltaMove > mTouchExplorationTapSlop) {
-                                mSendHoverDelayed.forceSendAndRemove();
                                 final int lastAction = mPointerTracker.getLastInjectedHoverAction();
                                 if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
                                     sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -435,7 +426,6 @@
                             }
 
                             // All preconditions are met, so click the last explored location.
-                            mSendHoverDelayed.forceSendAndRemove();
                             sendActionDownAndUp(mLastTouchExploreEvent, policyFlags);
                             mLastTouchExploreEvent = null;
                         } else {
@@ -451,6 +441,8 @@
                 }
             } break;
             case MotionEvent.ACTION_CANCEL: {
+                mSendHoverDelayed.remove();
+                mPerformLongPressDelayed.remove();
                 final int lastAction = pointerTracker.getLastInjectedHoverAction();
                 if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
                     final int pointerId = pointerTracker.getPrimaryActivePointerId();
@@ -838,8 +830,6 @@
     */
     private void sendAccessibilityEvent(int eventType) {
         AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
-        event.setPackageName(mContext.getPackageName());
-        event.setClassName(getClass().getName());
         mAccessibilityManager.sendAccessibilityEvent(event);
     }
 
@@ -939,8 +929,6 @@
         private int mInjectedPointersDown;
 
         // Keep track of the last up pointer data.
-        private float mLastReceivedUpPointerDownX;
-        private float mLastReveivedUpPointerDownY;
         private long mLastReceivedUpPointerDownTime;
         private int mLastReceivedUpPointerId;
         private boolean mLastReceivedUpPointerActive;
@@ -973,8 +961,6 @@
             mPrimaryActivePointerId = 0;
             mHasMovingActivePointer = false;
             mInjectedPointersDown = 0;
-            mLastReceivedUpPointerDownX = 0;
-            mLastReveivedUpPointerDownY = 0;
             mLastReceivedUpPointerDownTime = 0;
             mLastReceivedUpPointerId = 0;
             mLastReceivedUpPointerActive = false;
@@ -1131,20 +1117,6 @@
         }
 
         /**
-         * @return The X coordinate where the last up received pointer went down.
-         */
-        public float getLastReceivedUpPointerDownX() {
-            return mLastReceivedUpPointerDownX;
-        }
-
-        /**
-         * @return The Y coordinate where the last up received pointer went down.
-         */
-        public float getLastReceivedUpPointerDownY() {
-            return mLastReveivedUpPointerDownY;
-        }
-
-        /**
          * @return The time when the last up received pointer went down.
          */
         public long getLastReceivedUpPointerDownTime() {
@@ -1225,8 +1197,6 @@
             final int pointerFlag = (1 << pointerId);
 
             mLastReceivedUpPointerId = 0;
-            mLastReceivedUpPointerDownX = 0;
-            mLastReveivedUpPointerDownY = 0;
             mLastReceivedUpPointerDownTime = 0;
             mLastReceivedUpPointerActive = false;
 
@@ -1267,8 +1237,6 @@
             final int pointerFlag = (1 << pointerId);
 
             mLastReceivedUpPointerId = pointerId;
-            mLastReceivedUpPointerDownX = getReceivedPointerDownX(pointerId);
-            mLastReveivedUpPointerDownY = getReceivedPointerDownY(pointerId);
             mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
             mLastReceivedUpPointerActive = isActivePointer(pointerId);
 
@@ -1405,6 +1373,51 @@
     }
 
     /**
+     * Class for delayed sending of long press.
+     */
+    private final class PerformLongPressDelayed implements Runnable {
+        private MotionEvent mEvent;
+        private int mPolicyFlags;
+
+        public void post(MotionEvent prototype, int policyFlags, long delay) {
+            mEvent = MotionEvent.obtain(prototype);
+            mPolicyFlags = policyFlags;
+            mHandler.postDelayed(this, delay);
+        }
+
+        public void remove() {
+            if (isPenidng()) {
+                mHandler.removeCallbacks(this);
+                clear();
+            }
+        }
+
+        private boolean isPenidng() {
+            return (mEvent != null);
+        }
+
+        @Override
+        public void run() {
+            mCurrentState = STATE_DELEGATING;
+            // Make sure the scheduled hover exit is delivered.
+            mSendHoverDelayed.forceSendAndRemove();
+            sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+            mTouchExploreGestureInProgress = false;
+            mLastTouchExploreEvent = null;
+            clear();
+        }
+
+        private void clear() {
+            if (!isPenidng()) {
+                return;
+            }
+            mEvent.recycle();
+            mEvent = null;
+            mPolicyFlags = 0;
+        }
+    }
+
+    /**
      * Class for delayed sending of hover events.
      */
     private final class SendHoverDelayed implements Runnable {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8501163..66f88fc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -18,10 +18,10 @@
 
 import com.android.internal.R;
 import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.ProcessStats;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
 import com.android.server.ProcessMap;
-import com.android.server.ProcessStats;
 import com.android.server.SystemServer;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
@@ -45,7 +45,6 @@
 import android.app.IProcessObserver;
 import android.app.IServiceConnection;
 import android.app.IThumbnailReceiver;
-import android.app.IThumbnailRetriever;
 import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -54,6 +53,7 @@
 import android.app.backup.IBackupManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -181,22 +181,8 @@
     // The flags that are set for all calls we make to the package manager.
     static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
     
-    private static final String SYSTEM_SECURE = "ro.secure";
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
 
-    // This is the maximum number of application processes we would like
-    // to have running.  Due to the asynchronous nature of things, we can
-    // temporarily go beyond this limit.
-    static final int MAX_PROCESSES = 2;
-
-    // Set to false to leave processes running indefinitely, relying on
-    // the kernel killing them as resources are required.
-    static final boolean ENFORCE_PROCESS_LIMIT = false;
-
-    // This is the maximum number of activities that we would like to have
-    // running at a given time.
-    static final int MAX_ACTIVITIES = 20;
-
     // Maximum number of recent tasks that we can remember.
     static final int MAX_RECENT_TASKS = 20;
     
@@ -914,7 +900,8 @@
      */
     boolean mBooted = false;
 
-    int mProcessLimit = 0;
+    int mProcessLimit = MAX_HIDDEN_APPS;
+    int mProcessLimitOverride = -1;
 
     WindowManagerService mWindowManager;
 
@@ -1834,7 +1821,7 @@
                 // An application record is attached to a previous process,
                 // clean it up now.
                 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
-                handleAppDiedLocked(app, true);
+                handleAppDiedLocked(app, true, true);
             }
         }
 
@@ -2291,11 +2278,10 @@
         }
 
         synchronized (this) {
-            int index = mMainStack.indexOfTokenLocked(callingActivity);
-            if (index < 0) {
+            ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
+            if (r == null) {
                 return false;
             }
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
             if (r.app == null || r.app.thread == null) {
                 // The caller is not running...  d'oh!
                 return false;
@@ -2442,11 +2428,10 @@
     public void setRequestedOrientation(IBinder token,
             int requestedOrientation) {
         synchronized (this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index < 0) {
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
                 return;
             }
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
             final long origId = Binder.clearCallingIdentity();
             mWindowManager.setAppOrientation(r, requestedOrientation);
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
@@ -2454,7 +2439,7 @@
                     r.mayFreezeScreenLocked(r.app) ? r : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
-                if (!updateConfigurationLocked(config, r)) {
+                if (!updateConfigurationLocked(config, r, false)) {
                     mMainStack.resumeTopActivityLocked(null);
                 }
             }
@@ -2464,11 +2449,10 @@
 
     public int getRequestedOrientation(IBinder token) {
         synchronized (this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index < 0) {
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
             }
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
             return mWindowManager.getAppOrientation(r);
         }
     }
@@ -2609,11 +2593,10 @@
     public final void finishSubActivity(IBinder token, String resultWho,
             int requestCode) {
         synchronized(this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index < 0) {
+            ActivityRecord self = mMainStack.isInStackLocked(token);
+            if (self == null) {
                 return;
             }
-            ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
 
             final long origId = Binder.clearCallingIdentity();
 
@@ -2652,11 +2635,10 @@
     public void overridePendingTransition(IBinder token, String packageName,
             int enterAnim, int exitAnim) {
         synchronized(this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index < 0) {
+            ActivityRecord self = mMainStack.isInStackLocked(token);
+            if (self == null) {
                 return;
             }
-            ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
 
             final long origId = Binder.clearCallingIdentity();
             
@@ -2676,8 +2658,8 @@
      * to the process.
      */
     private final void handleAppDiedLocked(ProcessRecord app,
-            boolean restarting) {
-        cleanUpApplicationRecordLocked(app, restarting, -1);
+            boolean restarting, boolean allowRestart) {
+        cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
         if (!restarting) {
             mLruProcesses.remove(app);
         }
@@ -2735,8 +2717,7 @@
                     }
                 }
 
-                r.stack.cleanUpActivityLocked(r, true);
-                r.state = ActivityState.STOPPED;
+                r.stack.cleanUpActivityLocked(r, true, true);
             }
             atTop = false;
         }
@@ -2810,7 +2791,7 @@
                 TAG, "Dying app: " + app + ", pid: " + pid
                 + ", thread: " + thread.asBinder());
             boolean doLowMem = app.instrumentationClass == null;
-            handleAppDiedLocked(app, false);
+            handleAppDiedLocked(app, false, true);
 
             if (doLowMem) {
                 // If there are no longer any background processes running,
@@ -3214,7 +3195,7 @@
                     return;
                 }
                 killPackageProcessesLocked(packageName, pkgUid,
-                        SECONDARY_SERVER_ADJ, false, true);
+                        SECONDARY_SERVER_ADJ, false, true, true);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -3377,7 +3358,7 @@
     }
     
     private final boolean killPackageProcessesLocked(String packageName, int uid,
-            int minOomAdj, boolean callerWillRestart, boolean doit) {
+            int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit) {
         ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
 
         // Remove all processes this package may have touched: all with the
@@ -3388,6 +3369,10 @@
             final int NA = apps.size();
             for (int ia=0; ia<NA; ia++) {
                 ProcessRecord app = apps.valueAt(ia);
+                if (app.persistent) {
+                    // we don't kill persistent processes
+                    continue;
+                }
                 if (app.removed) {
                     if (doit) {
                         procs.add(app);
@@ -3408,7 +3393,7 @@
         
         int N = procs.size();
         for (int i=0; i<N; i++) {
-            removeProcessLocked(procs.get(i), callerWillRestart);
+            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
         }
         return N > 0;
     }
@@ -3438,11 +3423,12 @@
         }
         
         boolean didSomething = killPackageProcessesLocked(name, uid, -100,
-                callerWillRestart, doit);
+                callerWillRestart, false, doit);
         
         for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
             ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
-            if (r.packageName.equals(name)) {
+            if (r.packageName.equals(name)
+                    && (r.app == null || !r.app.persistent)) {
                 if (!doit) {
                     return true;
                 }
@@ -3458,7 +3444,8 @@
 
         ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
         for (ServiceRecord service : mServices.values()) {
-            if (service.packageName.equals(name)) {
+            if (service.packageName.equals(name)
+                    && (service.app == null || !service.app.persistent)) {
                 if (!doit) {
                     return true;
                 }
@@ -3490,7 +3477,8 @@
         return didSomething;
     }
 
-    private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
+    private final boolean removeProcessLocked(ProcessRecord app,
+            boolean callerWillRestart, boolean allowRestart) {
         final String name = app.processName;
         final int uid = app.info.uid;
         if (DEBUG_PROCESSES) Slog.d(
@@ -3509,7 +3497,7 @@
                 mPidsSelfLocked.remove(pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
-            handleAppDiedLocked(app, true);
+            handleAppDiedLocked(app, true, allowRestart);
             mLruProcesses.remove(app);
             Process.killProcess(pid);
             
@@ -3619,7 +3607,7 @@
         // If this application record is still attached to a previous
         // process, clean it up now.
         if (app.thread != null) {
-            handleAppDiedLocked(app, true);
+            handleAppDiedLocked(app, true, true);
         }
 
         // Tell the process all about itself.
@@ -3629,8 +3617,10 @@
 
         String processName = app.processName;
         try {
-            thread.asBinder().linkToDeath(new AppDeathRecipient(
-                    app, pid, thread), 0);
+            AppDeathRecipient adr = new AppDeathRecipient(
+                    app, pid, thread);
+            thread.asBinder().linkToDeath(adr, 0);
+            app.deathRecipient = adr;
         } catch (RemoteException e) {
             app.resetPackageList();
             startProcessLocked(app, "link fail", processName);
@@ -3645,6 +3635,7 @@
         app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.forcingToForeground = null;
         app.foregroundServices = false;
+        app.hasShownUi = false;
         app.debugging = false;
 
         mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
@@ -3706,6 +3697,7 @@
             Slog.w(TAG, "Exception thrown during bind!", e);
 
             app.resetPackageList();
+            app.unlinkDeathRecipient();
             startProcessLocked(app, "bind fail", processName);
             return false;
         }
@@ -3798,7 +3790,7 @@
         if (badApp) {
             // todo: Also need to kill application to deal with all
             // kinds of exceptions.
-            handleAppDiedLocked(app, false);
+            handleAppDiedLocked(app, false, true);
             return false;
         }
 
@@ -3920,20 +3912,9 @@
         final long origId = Binder.clearCallingIdentity();
 
         synchronized (this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index >= 0) {
-                r = (ActivityRecord)mMainStack.mHistory.get(index);
-                r.icicle = icicle;
-                r.haveState = true;
-                r.updateThumbnail(thumbnail, description);
-                r.stopped = true;
-                r.state = ActivityState.STOPPED;
-                if (!r.finishing) {
-                    if (r.configDestroy) {
-                        r.stack.destroyActivityLocked(r, true);
-                        r.stack.resumeTopActivityLocked(null);
-                    }
-                }
+            r = mMainStack.isInStackLocked(token);
+            if (r != null) {
+                r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
             }
         }
 
@@ -3966,35 +3947,30 @@
     }
 
     private ActivityRecord getCallingRecordLocked(IBinder token) {
-        int index = mMainStack.indexOfTokenLocked(token);
-        if (index >= 0) {
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
-            if (r != null) {
-                return r.resultTo;
-            }
+        ActivityRecord r = mMainStack.isInStackLocked(token);
+        if (r == null) {
+            return null;
         }
-        return null;
+        return r.resultTo;
     }
 
     public ComponentName getActivityClassForToken(IBinder token) {
         synchronized(this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index >= 0) {
-                ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
-                return r.intent.getComponent();
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
+                return null;
             }
-            return null;
+            return r.intent.getComponent();
         }
     }
 
     public String getPackageForToken(IBinder token) {
         synchronized(this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index >= 0) {
-                ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
-                return r.packageName;
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
+                return null;
             }
-            return null;
+            return r.packageName;
         }
     }
 
@@ -4057,11 +4033,10 @@
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
         ActivityRecord activity = null;
         if (type == INTENT_SENDER_ACTIVITY_RESULT) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index < 0) {
+            activity = mMainStack.isInStackLocked(token);
+            if (activity == null) {
                 return null;
             }
-            activity = (ActivityRecord)mMainStack.mHistory.get(index);
             if (activity.finishing) {
                 return null;
             }
@@ -4183,11 +4158,17 @@
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
-        mProcessLimit = max;
+        synchronized (this) {
+            mProcessLimit = max < 0 ? MAX_HIDDEN_APPS : max;
+            mProcessLimitOverride = max;
+        }
+        trimApplications();
     }
 
     public int getProcessLimit() {
-        return mProcessLimit;
+        synchronized (this) {
+            return mProcessLimitOverride;
+        }
     }
 
     void foregroundTokenDied(ForegroundToken token) {
@@ -5451,11 +5432,10 @@
 
         synchronized(this) {
             if (r == null) {
-                int index = mMainStack.indexOfTokenLocked(token);
-                if (index < 0) {
+                r = mMainStack.isInStackLocked(token);
+                if (r == null) {
                     return;
                 }
-                r = (ActivityRecord)mMainStack.mHistory.get(index);
             }
             if (thumbnail == null && r.thumbHolder != null) {
                 thumbnail = r.thumbHolder.lastThumbnail;
@@ -6169,9 +6149,8 @@
         final long origId = Binder.clearCallingIdentity();
 
         synchronized (this) {
-            int index = mMainStack.indexOfTokenLocked(token);
-            if (index >= 0) {
-                r = (ActivityRecord)mMainStack.mHistory.get(index);
+            r = mMainStack.isInStackLocked(token);
+            if (r != null) {
                 mMainStack.activitySleptLocked(r);
             }
         }
@@ -6322,22 +6301,20 @@
 
     public void setImmersive(IBinder token, boolean immersive) {
         synchronized(this) {
-            int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
-            if (index < 0) {
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
                 throw new IllegalArgumentException();
             }
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
             r.immersive = immersive;
         }
     }
 
     public boolean isImmersive(IBinder token) {
         synchronized (this) {
-            int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
-            if (index < 0) {
+            ActivityRecord r = mMainStack.isInStackLocked(token);
+            if (r == null) {
                 throw new IllegalArgumentException();
             }
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
             return r.immersive;
         }
     }
@@ -6673,7 +6650,7 @@
                 for (int i=procsToKill.size()-1; i>=0; i--) {
                     ProcessRecord proc = procsToKill.get(i);
                     Slog.i(TAG, "Removing system update proc: " + proc);
-                    removeProcessLocked(proc, true);
+                    removeProcessLocked(proc, true, false);
                 }
             }
             
@@ -6856,10 +6833,6 @@
                 }
             }
             if (!app.persistent) {
-                // Don't let services in this process be restarted and potentially
-                // annoy the user repeatedly.  Unless it is persistent, since those
-                // processes run critical code.
-                killServicesLocked(app, false);
                 // We don't want to start this process again until the user
                 // explicitly does so...  but for persistent process, we really
                 // need to keep it running.  If a persistent process is actually
@@ -6870,7 +6843,10 @@
                 app.bad = true;
                 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
                 app.removed = true;
-                removeProcessLocked(app, false);
+                // Don't let services in this process be restarted and potentially
+                // annoy the user repeatedly.  Unless it is persistent, since those
+                // processes run critical code.
+                removeProcessLocked(app, false, false);
                 mMainStack.resumeTopActivityLocked(null);
                 return false;
             }
@@ -8800,9 +8776,10 @@
             } else {
                 foreground = " ";
             }
-            pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
+            pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
                     prefix, (r.persistent ? persistentLabel : normalLabel),
-                    N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
+                    N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
+                    r.toShortString(), r.adjType));
             if (r.adjSource != null || r.adjTarget != null) {
                 pw.print(prefix);
                 pw.print("    ");
@@ -8918,25 +8895,59 @@
         pw.println("Applications Graphics Acceleration Info:");
         pw.println("Uptime: " + uptime + " Realtime: " + realtime);
         
-        String callArgs[] = {"graphics"};
         for (int i = procs.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = procs.get(i);
             if (r.thread != null) {
                 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
                 pw.flush();
                 try {
-                    TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
+                    TransferPipe tp = new TransferPipe();
+                    try {
+                        r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
+                        tp.go(fd);
+                    } finally {
+                        tp.kill();
+                    }
                 } catch (IOException e) {
-                    pw.println("Failure: " + e);
+                    pw.println("Failure while dumping the app: " + r);
                     pw.flush();
                 } catch (RemoteException e) {
-                    pw.println("Got RemoteException!");
+                    pw.println("Got a RemoteException while dumping the app " + r);
                     pw.flush();
                 }
             }
         }
     }
 
+    final static class MemItem {
+        final String label;
+        final long pss;
+
+        public MemItem(String _label, long _pss) {
+            label = _label;
+            pss = _pss;
+        }
+    }
+
+    final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
+        Collections.sort(items, new Comparator<MemItem>() {
+            @Override
+            public int compare(MemItem lhs, MemItem rhs) {
+                if (lhs.pss < rhs.pss) {
+                    return 1;
+                } else if (lhs.pss > rhs.pss) {
+                    return -1;
+                }
+                return 0;
+            }
+        });
+
+        for (int i=0; i<items.size(); i++) {
+            MemItem mi = items.get(i);
+            pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
+        }
+    }
+
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, String prefix, String[] args) {
         ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
@@ -8956,6 +8967,11 @@
             pw.println("Applications Memory Usage (kB):");
             pw.println("Uptime: " + uptime + " Realtime: " + realtime);
         }
+
+        ArrayList<MemItem> procMems = new ArrayList<MemItem>();
+        long nativePss=0, dalvikPss=0, otherPss=0;
+        long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
+
         for (int i = procs.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = procs.get(i);
             if (r.thread != null) {
@@ -8963,19 +8979,48 @@
                     pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
                     pw.flush();
                 }
+                Debug.MemoryInfo mi = null;
                 try {
-                    TransferPipe.goDump(r.thread.asBinder(), fd, args);
-                } catch (IOException e) {
-                    pw.println("Failure: " + e);
-                    pw.flush();
+                    mi = r.thread.dumpMemInfo(fd, args);
                 } catch (RemoteException e) {
                     if (!isCheckinRequest) {
                         pw.println("Got RemoteException!");
                         pw.flush();
                     }
                 }
+                if (!isCheckinRequest && mi != null) {
+                    procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
+                            mi.getTotalPss()));
+
+                    nativePss += mi.nativePss;
+                    dalvikPss += mi.dalvikPss;
+                    otherPss += mi.otherPss;
+                    for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
+                        long mem = mi.getOtherPss(j);
+                        miscPss[j] += mem;
+                        otherPss -= mem;
+                    }
+                }
             }
         }
+
+        if (!isCheckinRequest && procs.size() > 1) {
+            ArrayList<MemItem> catMems = new ArrayList<MemItem>();
+
+            catMems.add(new MemItem("Native", nativePss));
+            catMems.add(new MemItem("Dalvik", dalvikPss));
+            catMems.add(new MemItem("Unknown", otherPss));
+            for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
+                catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
+            }
+
+            pw.println();
+            pw.println("Total PSS by process:");
+            dumpMemItems(pw, "  ", procMems);
+            pw.println();
+            pw.println("Total PSS by category:");
+            dumpMemItems(pw, "  ", catMems);
+        }
     }
 
     /**
@@ -9081,7 +9126,7 @@
                     
                     // Should the service remain running?  Note that in the
                     // extreme case of so many attempts to deliver a command
-                    // that it failed, that we also will stop it here.
+                    // that it failed we also will stop it here.
                     if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                         if (sr.pendingStarts.size() == 0) {
                             sr.startRequested = false;
@@ -9150,7 +9195,7 @@
      * a process when running in single process mode.
      */
     private final void cleanUpApplicationRecordLocked(ProcessRecord app,
-            boolean restarting, int index) {
+            boolean restarting, boolean allowRestart, int index) {
         if (index >= 0) {
             mLruProcesses.remove(index);
         }
@@ -9175,12 +9220,14 @@
         app.notResponding = false;
         
         app.resetPackageList();
+        app.unlinkDeathRecipient();
         app.thread = null;
         app.forcingToForeground = null;
         app.foregroundServices = false;
         app.foregroundActivities = false;
+        app.hasShownUi = false;
 
-        killServicesLocked(app, true);
+        killServicesLocked(app, allowRestart);
 
         boolean restart = false;
 
@@ -9197,7 +9244,7 @@
                 // See if someone is waiting for this provider...  in which
                 // case we don't remove it, but just let it restart.
                 int i = 0;
-                if (!app.bad) {
+                if (!app.bad && allowRestart) {
                     for (; i<NL; i++) {
                         if (mLaunchingProviders.get(i) == cpr) {
                             restart = true;
@@ -9292,9 +9339,6 @@
             // This app is persistent, so we need to keep its record around.
             // If it is not already on the pending app list, add it there
             // and start a new process for it.
-            app.thread = null;
-            app.forcingToForeground = null;
-            app.foregroundServices = false;
             if (mPersistentStartingProcesses.indexOf(app) < 0) {
                 mPersistentStartingProcesses.add(app);
                 restart = true;
@@ -9956,8 +10000,12 @@
             while (it.hasNext()) {
                 ArrayList<ConnectionRecord> c = it.next();
                 for (int i=0; i<c.size(); i++) {
+                    ConnectionRecord cr = c.get(i);
+                    // There is still a connection to the service that is
+                    // being brought down.  Mark it as dead.
+                    cr.serviceDead = true;
                     try {
-                        c.get(i).conn.connected(r.name, null);
+                        cr.conn.connected(r.name, null);
                     } catch (Exception e) {
                         Slog.w(TAG, "Failure disconnecting service " + r.name +
                               " to connection " + c.get(i).conn.asBinder() +
@@ -10337,12 +10385,11 @@
 
             ActivityRecord activity = null;
             if (token != null) {
-                int aindex = mMainStack.indexOfTokenLocked(token);
-                if (aindex < 0) {
+                activity = mMainStack.isInStackLocked(token);
+                if (activity == null) {
                     Slog.w(TAG, "Binding with unknown activity: " + token);
                     return 0;
                 }
-                activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
             }
 
             int clientLabel = 0;
@@ -10489,26 +10536,28 @@
             b.intent.apps.remove(b.client);
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
-                + ": shouldUnbind=" + b.intent.hasBound);
-        if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
-                && b.intent.hasBound) {
-            try {
-                bumpServiceExecutingLocked(s, "unbind");
-                updateOomAdjLocked(s.app);
-                b.intent.hasBound = false;
-                // Assume the client doesn't want to know about a rebind;
-                // we will deal with that later if it asks for one.
-                b.intent.doRebind = false;
-                s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
-            } catch (Exception e) {
-                Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
-                serviceDoneExecutingLocked(s, true);
+        if (!c.serviceDead) {
+            if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
+                    + ": shouldUnbind=" + b.intent.hasBound);
+            if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
+                    && b.intent.hasBound) {
+                try {
+                    bumpServiceExecutingLocked(s, "unbind");
+                    updateOomAdjLocked(s.app);
+                    b.intent.hasBound = false;
+                    // Assume the client doesn't want to know about a rebind;
+                    // we will deal with that later if it asks for one.
+                    b.intent.doRebind = false;
+                    s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
+                } catch (Exception e) {
+                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+                    serviceDoneExecutingLocked(s, true);
+                }
             }
-        }
-
-        if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
-            bringDownServiceLocked(s, false);
+    
+            if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
+                bringDownServiceLocked(s, false);
+            }
         }
     }
 
@@ -11556,8 +11605,8 @@
             return false;
         }
         int state = r.state;
-        r.state = r.IDLE;
-        if (state == r.IDLE) {
+        r.state = BroadcastRecord.IDLE;
+        if (state == BroadcastRecord.IDLE) {
             if (explicit) {
                 Slog.w(TAG, "finishReceiver called but state is IDLE");
             }
@@ -12361,6 +12410,22 @@
         return ci;
     }
 
+    public void updatePersistentConfiguration(Configuration values) {
+        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
+                "updateConfiguration()");
+        enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
+                "updateConfiguration()");
+        if (values == null) {
+            throw new NullPointerException("Configuration must not be null");
+        }
+
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            updateConfigurationLocked(values, null, true);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
     public void updateConfiguration(Configuration values) {
         enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                 "updateConfiguration()");
@@ -12372,7 +12437,10 @@
             }
             
             final long origId = Binder.clearCallingIdentity();
-            updateConfigurationLocked(values, null);
+            if (values != null) {
+                Settings.System.clearConfiguration(values);
+            }
+            updateConfigurationLocked(values, null, false);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -12383,9 +12451,10 @@
      * configuration.  Returns true if the activity has been left running, or
      * false if <var>starting</var> is being destroyed to match the new
      * configuration.
+     * @param persistent TODO
      */
     public boolean updateConfigurationLocked(Configuration values,
-            ActivityRecord starting) {
+            ActivityRecord starting, boolean persistent) {
         int changes = 0;
         
         boolean kept = true;
@@ -12428,7 +12497,7 @@
                 // code is executed.
                 mSystemThread.applyConfigurationToResources(newConfig);
 
-                if (Settings.System.hasInterestingConfigurationChanges(changes)) {
+                if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                     Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
                     msg.obj = new Configuration(mConfiguration);
                     mHandler.sendMessage(msg);
@@ -12671,21 +12740,31 @@
             while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
                 ServiceRecord s = jt.next();
                 if (s.startRequested) {
-                    if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
-                        // This service has seen some activity within
-                        // recent memory, so we will keep its process ahead
-                        // of the background processes.
+                    if (app.hasShownUi) {
+                        // If this process has shown some UI, let it immediately
+                        // go to the LRU list because it may be pretty heavy with
+                        // UI stuff.  We'll tag it with a label just to help
+                        // debug and understand what is going on.
                         if (adj > SECONDARY_SERVER_ADJ) {
-                            adj = SECONDARY_SERVER_ADJ;
-                            app.adjType = "started-services";
-                            app.hidden = false;
+                            app.adjType = "started-bg-ui-services";
                         }
-                    }
-                    // If we have let the service slide into the background
-                    // state, still have some text describing what it is doing
-                    // even though the service no longer has an impact.
-                    if (adj > SECONDARY_SERVER_ADJ) {
-                        app.adjType = "started-bg-services";
+                    } else {
+                        if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                            // This service has seen some activity within
+                            // recent memory, so we will keep its process ahead
+                            // of the background processes.
+                            if (adj > SECONDARY_SERVER_ADJ) {
+                                adj = SECONDARY_SERVER_ADJ;
+                                app.adjType = "started-services";
+                                app.hidden = false;
+                            }
+                        }
+                        // If we have let the service slide into the background
+                        // state, still have some text describing what it is doing
+                        // even though the service no longer has an impact.
+                        if (adj > SECONDARY_SERVER_ADJ) {
+                            app.adjType = "started-bg-services";
+                        }
                     }
                     // Don't kill this process because it is doing work; it
                     // has said it is doing work.
@@ -12707,6 +12786,7 @@
                             }
                             if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
                                 ProcessRecord client = cr.binding.client;
+                                int clientAdj = adj;
                                 int myHiddenAdj = hiddenAdj;
                                 if (myHiddenAdj > client.hiddenAdj) {
                                     if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
@@ -12715,8 +12795,35 @@
                                         myHiddenAdj = VISIBLE_APP_ADJ;
                                     }
                                 }
-                                int clientAdj = computeOomAdjLocked(
+                                clientAdj = computeOomAdjLocked(
                                     client, myHiddenAdj, TOP_APP, true);
+                                String adjType = null;
+                                if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+                                    // Not doing bind OOM management, so treat
+                                    // this guy more like a started service.
+                                    if (app.hasShownUi) {
+                                        // If this process has shown some UI, let it immediately
+                                        // go to the LRU list because it may be pretty heavy with
+                                        // UI stuff.  We'll tag it with a label just to help
+                                        // debug and understand what is going on.
+                                        if (adj > clientAdj) {
+                                            adjType = "bound-bg-ui-services";
+                                        }
+                                        clientAdj = adj;
+                                    } else {
+                                        if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                                            // This service has not seen activity within
+                                            // recent memory, so allow it to drop to the
+                                            // LRU list if there is no other reason to keep
+                                            // it around.  We'll also tag it with a label just
+                                            // to help debug and undertand what is going on.
+                                            if (adj > clientAdj) {
+                                                adjType = "bound-bg-services";
+                                            }
+                                            clientAdj = adj;
+                                        }
+                                    }
+                                }
                                 if (adj > clientAdj) {
                                     adj = clientAdj >= VISIBLE_APP_ADJ
                                             ? clientAdj : VISIBLE_APP_ADJ;
@@ -12726,7 +12833,10 @@
                                     if (client.keeping) {
                                         app.keeping = true;
                                     }
-                                    app.adjType = "service";
+                                    adjType = "service";
+                                }
+                                if (adjType != null) {
+                                    app.adjType = adjType;
                                     app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                             .REASON_SERVICE_IN_USE;
                                     app.adjSource = cr.binding.client;
@@ -12941,7 +13051,7 @@
             ProcessRecord proc = mProcessesToGc.get(0);
             Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
             
-            long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
+            long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
             long now = SystemClock.uptimeMillis();
             if (when < (now+GC_TIMEOUT)) {
                 when = now + GC_TIMEOUT;
@@ -13084,16 +13194,14 @@
         }
     }
 
-    private final boolean updateOomAdjLocked(
+    private final void updateOomAdjLocked(
             ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
         app.hiddenAdj = hiddenAdj;
 
         if (app.thread == null) {
-            return true;
+            return;
         }
 
-        boolean success = true;
-
         final boolean wasKeeping = app.keeping;
 
         int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
@@ -13129,10 +13237,10 @@
             if (Process.setOomAdj(app.pid, adj)) {
                 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
                     TAG, "Set app " + app.processName +
-                    " oom adj to " + adj);
+                    " oom adj to " + adj + " because " + app.adjType);
                 app.setAdj = adj;
             } else {
-                success = false;
+                Slog.w(TAG, "Failed setting oom adj of " + app + " to " + adj);
             }
         }
         if (app.setSchedGroup != app.curSchedGroup) {
@@ -13158,8 +13266,7 @@
                     } finally {
                         Binder.restoreCallingIdentity(oldId);
                     }
-                }
-                if (false) {
+                } else {
                     if (app.thread != null) {
                         try {
                             app.thread.setSchedulingGroup(app.curSchedGroup);
@@ -13169,8 +13276,6 @@
                 }
             }
         }
-
-        return success;
     }
 
     private final ActivityRecord resumedAppLocked() {
@@ -13184,30 +13289,26 @@
         return resumedActivity;
     }
 
-    private final boolean updateOomAdjLocked(ProcessRecord app) {
+    private final void updateOomAdjLocked(ProcessRecord app) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         int curAdj = app.curAdj;
-        final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
-            && app.curAdj <= HIDDEN_APP_MAX_ADJ;
+        final boolean wasHidden = curAdj >= HIDDEN_APP_MIN_ADJ
+            && curAdj <= HIDDEN_APP_MAX_ADJ;
 
         mAdjSeq++;
 
-        final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
-        if (res) {
-            final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
-                && app.curAdj <= HIDDEN_APP_MAX_ADJ;
-            if (nowHidden != wasHidden) {
-                // Changed to/from hidden state, so apps after it in the LRU
-                // list may also be changed.
-                updateOomAdjLocked();
-            }
+        updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
+        final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
+            && app.curAdj <= HIDDEN_APP_MAX_ADJ;
+        if (nowHidden != wasHidden) {
+            // Changed to/from hidden state, so apps after it in the LRU
+            // list may also be changed.
+            updateOomAdjLocked();
         }
-        return res;
     }
 
-    final boolean updateOomAdjLocked() {
-        boolean didOomAdj = true;
+    final void updateOomAdjLocked() {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
 
@@ -13229,45 +13330,104 @@
         int step = 0;
         int numHidden = 0;
         
-        // First try updating the OOM adjustment for each of the
+        // First update the OOM adjustment for each of the
         // application processes based on their current state.
         int i = mLruProcesses.size();
         int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
+        int numBg = 0;
         while (i > 0) {
             i--;
             ProcessRecord app = mLruProcesses.get(i);
             //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
-            if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
-                if (curHiddenAdj < EMPTY_APP_ADJ
-                    && app.curAdj == curHiddenAdj) {
-                    step++;
-                    if (step >= factor) {
-                        step = 0;
-                        curHiddenAdj++;
-                    }
+            updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
+            if (curHiddenAdj < EMPTY_APP_ADJ
+                && app.curAdj == curHiddenAdj) {
+                step++;
+                if (step >= factor) {
+                    step = 0;
+                    curHiddenAdj++;
                 }
+            }
+            if (!app.killedBackground) {
                 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
-                    if (!app.killedBackground) {
-                        numHidden++;
-                        if (numHidden > MAX_HIDDEN_APPS) {
-                            Slog.i(TAG, "No longer want " + app.processName
-                                    + " (pid " + app.pid + "): hidden #" + numHidden);
-                            EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
-                                    app.processName, app.setAdj, "too many background");
-                            app.killedBackground = true;
-                            Process.killProcessQuiet(app.pid);
-                        }
+                    numHidden++;
+                    if (numHidden > mProcessLimit) {
+                        Slog.i(TAG, "No longer want " + app.processName
+                                + " (pid " + app.pid + "): hidden #" + numHidden);
+                        EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                                app.processName, app.setAdj, "too many background");
+                        app.killedBackground = true;
+                        Process.killProcessQuiet(app.pid);
+                    } else {
+                        numBg++;
                     }
+                } else if (app.curAdj >= HOME_APP_ADJ) {
+                    numBg++;
                 }
-            } else {
-                didOomAdj = false;
             }
         }
 
-        // If we return false, we will fall back on killing processes to
-        // have a fixed limit.  Do this if a limit has been requested; else
-        // only return false if one of the adjustments failed.
-        return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
+        // Now determine the memory trimming level of background processes.
+        // Unfortunately we need to start at the back of the list to do this
+        // properly.  We only do this if the number of background apps we
+        // are managing to keep around is less than half the maximum we desire;
+        // if we are keeping a good number around, we'll let them use whatever
+        // memory they want.
+        if (numHidden <= (MAX_HIDDEN_APPS/2)) {
+            final int N = mLruProcesses.size();
+            factor = numBg/3;
+            step = 0;
+            int curLevel = ComponentCallbacks.TRIM_MEMORY_COMPLETE;
+            for (i=0; i<N; i++) {
+                ProcessRecord app = mLruProcesses.get(i);
+                if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
+                    if (app.trimMemoryLevel < curLevel && app.thread != null) {
+                        try {
+                            app.thread.scheduleTrimMemory(curLevel);
+                        } catch (RemoteException e) {
+                        }
+                        if (curLevel >= ComponentCallbacks.TRIM_MEMORY_COMPLETE) {
+                            // For these apps we will also finish their activities
+                            // to help them free memory.
+                            mMainStack.destroyActivitiesLocked(app, false);
+                        }
+                    }
+                    app.trimMemoryLevel = curLevel;
+                    step++;
+                    if (step >= factor) {
+                        switch (curLevel) {
+                            case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
+                                curLevel = ComponentCallbacks.TRIM_MEMORY_MODERATE;
+                                break;
+                            case ComponentCallbacks.TRIM_MEMORY_MODERATE:
+                                curLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
+                                break;
+                        }
+                    }
+                } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) {
+                    if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_BACKGROUND
+                            && app.thread != null) {
+                        try {
+                            app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_BACKGROUND);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
+                } else {
+                    app.trimMemoryLevel = 0;
+                }
+            }
+        } else {
+            final int N = mLruProcesses.size();
+            for (i=0; i<N; i++) {
+                ProcessRecord app = mLruProcesses.get(i);
+                app.trimMemoryLevel = 0;
+            }
+        }
+
+        if (mAlwaysFinishActivities) {
+            mMainStack.destroyActivitiesLocked(null, false);
+        }
     }
 
     final void trimApplications() {
@@ -13296,7 +13456,7 @@
                             // Ignore exceptions.
                         }
                     }
-                    cleanUpApplicationRecordLocked(app, false, -1);
+                    cleanUpApplicationRecordLocked(app, false, true, -1);
                     mRemovedProcesses.remove(i);
                     
                     if (app.persistent) {
@@ -13307,165 +13467,8 @@
                 }
             }
 
-            // Now try updating the OOM adjustment for each of the
-            // application processes based on their current state.
-            // If the setOomAdj() API is not supported, then go with our
-            // back-up plan...
-            if (!updateOomAdjLocked()) {
-
-                // Count how many processes are running services.
-                int numServiceProcs = 0;
-                for (i=mLruProcesses.size()-1; i>=0; i--) {
-                    final ProcessRecord app = mLruProcesses.get(i);
-
-                    if (app.persistent || app.services.size() != 0
-                            || app.curReceiver != null) {
-                        // Don't count processes holding services against our
-                        // maximum process count.
-                        if (localLOGV) Slog.v(
-                            TAG, "Not trimming app " + app + " with services: "
-                            + app.services);
-                        numServiceProcs++;
-                    }
-                }
-
-                int curMaxProcs = mProcessLimit;
-                if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
-                if (mAlwaysFinishActivities) {
-                    curMaxProcs = 1;
-                }
-                curMaxProcs += numServiceProcs;
-
-                // Quit as many processes as we can to get down to the desired
-                // process count.  First remove any processes that no longer
-                // have activites running in them.
-                for (   i=0;
-                        i<mLruProcesses.size()
-                            && mLruProcesses.size() > curMaxProcs;
-                        i++) {
-                    final ProcessRecord app = mLruProcesses.get(i);
-                    // Quit an application only if it is not currently
-                    // running any activities.
-                    if (!app.persistent && app.activities.size() == 0
-                            && app.curReceiver == null && app.services.size() == 0) {
-                        Slog.i(
-                            TAG, "Exiting empty application process "
-                            + app.processName + " ("
-                            + (app.thread != null ? app.thread.asBinder() : null)
-                            + ")\n");
-                        if (app.pid > 0 && app.pid != MY_PID) {
-                            EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
-                                    app.processName, app.setAdj, "empty");
-                            Process.killProcessQuiet(app.pid);
-                        } else {
-                            try {
-                                app.thread.scheduleExit();
-                            } catch (Exception e) {
-                                // Ignore exceptions.
-                            }
-                        }
-                        // todo: For now we assume the application is not buggy
-                        // or evil, and will quit as a result of our request.
-                        // Eventually we need to drive this off of the death
-                        // notification, and kill the process if it takes too long.
-                        cleanUpApplicationRecordLocked(app, false, i);
-                        i--;
-                    }
-                }
-
-                // If we still have too many processes, now from the least
-                // recently used process we start finishing activities.
-                if (false) Slog.v(
-                    TAG, "*** NOW HAVE " + mLruProcesses.size() +
-                    " of " + curMaxProcs + " processes");
-                for (   i=0;
-                        i<mLruProcesses.size()
-                            && mLruProcesses.size() > curMaxProcs;
-                        i++) {
-                    final ProcessRecord app = mLruProcesses.get(i);
-                    // Quit the application only if we have a state saved for
-                    // all of its activities.
-                    boolean canQuit = !app.persistent && app.curReceiver == null
-                        && app.services.size() == 0;
-                    int NUMA = app.activities.size();
-                    int j;
-                    if (false) Slog.v(
-                        TAG, "Looking to quit " + app.processName);
-                    for (j=0; j<NUMA && canQuit; j++) {
-                        ActivityRecord r = app.activities.get(j);
-                        if (false) Slog.v(
-                            TAG, "  " + r.intent.getComponent().flattenToShortString()
-                            + ": frozen=" + r.haveState + ", visible=" + r.visible);
-                        canQuit = (r.haveState || !r.stateNotNeeded)
-                                && !r.visible && r.stopped;
-                    }
-                    if (canQuit) {
-                        // Finish all of the activities, and then the app itself.
-                        for (j=0; j<NUMA; j++) {
-                            ActivityRecord r = app.activities.get(j);
-                            if (!r.finishing) {
-                                r.stack.destroyActivityLocked(r, false);
-                            }
-                            r.resultTo = null;
-                        }
-                        Slog.i(TAG, "Exiting application process "
-                              + app.processName + " ("
-                              + (app.thread != null ? app.thread.asBinder() : null)
-                              + ")\n");
-                        if (app.pid > 0 && app.pid != MY_PID) {
-                            EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
-                                    app.processName, app.setAdj, "old background");
-                            Process.killProcessQuiet(app.pid);
-                        } else {
-                            try {
-                                app.thread.scheduleExit();
-                            } catch (Exception e) {
-                                // Ignore exceptions.
-                            }
-                        }
-                        // todo: For now we assume the application is not buggy
-                        // or evil, and will quit as a result of our request.
-                        // Eventually we need to drive this off of the death
-                        // notification, and kill the process if it takes too long.
-                        cleanUpApplicationRecordLocked(app, false, i);
-                        i--;
-                        //dump();
-                    }
-                }
-
-            }
-
-            int curMaxActivities = MAX_ACTIVITIES;
-            if (mAlwaysFinishActivities) {
-                curMaxActivities = 1;
-            }
-
-            // Finally, if there are too many activities now running, try to
-            // finish as many as we can to get back down to the limit.
-            for (   i=0;
-                    i<mMainStack.mLRUActivities.size()
-                        && mMainStack.mLRUActivities.size() > curMaxActivities;
-                    i++) {
-                final ActivityRecord r
-                    = (ActivityRecord)mMainStack.mLRUActivities.get(i);
-
-                // We can finish this one if we have its icicle saved and
-                // it is not persistent.
-                if ((r.haveState || !r.stateNotNeeded) && !r.visible
-                        && r.stopped && !r.finishing) {
-                    final int origSize = mMainStack.mLRUActivities.size();
-                    r.stack.destroyActivityLocked(r, true);
-
-                    // This will remove it from the LRU list, so keep
-                    // our index at the same value.  Note that this check to
-                    // see if the size changes is just paranoia -- if
-                    // something unexpected happens, we don't want to end up
-                    // in an infinite loop.
-                    if (origSize > mMainStack.mLRUActivities.size()) {
-                        i--;
-                    }
-                }
-            }
+            // Now update the oom adj for all processes.
+            updateOomAdjLocked();
         }
     }
 
@@ -13492,7 +13495,7 @@
     }
 
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException {
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
 
         try {
             synchronized (this) {
@@ -13537,7 +13540,7 @@
                     }
                 }
             
-                proc.thread.profilerControl(start, path, fd);
+                proc.thread.profilerControl(start, path, fd, profileType);
                 fd = null;
                 return true;
             }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b1da69f..cc58eaf 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -52,6 +52,7 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -83,6 +84,8 @@
     static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
     static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS;
     
+    static final boolean DEBUG_STATES = false;
+
     static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
     
     // How long we wait until giving up on the last activity telling us it
@@ -392,19 +395,25 @@
     }
 
     final int indexOfTokenLocked(IBinder token) {
-        int count = mHistory.size();
-
-        // convert the token to an entry in the history.
-        int index = -1;
-        for (int i=count-1; i>=0; i--) {
-            Object o = mHistory.get(i);
-            if (o == token) {
-                index = i;
-                break;
-            }
+        try {
+            ActivityRecord r = (ActivityRecord)token;
+            return mHistory.indexOf(r);
+        } catch (ClassCastException e) {
+            Slog.w(TAG, "Bad activity token: " + token, e);
+            return -1;
         }
+    }
 
-        return index;
+    final ActivityRecord isInStackLocked(IBinder token) {
+        try {
+            ActivityRecord r = (ActivityRecord)token;
+            if (mHistory.contains(r)) {
+                return r;
+            }
+        } catch (ClassCastException e) {
+            Slog.w(TAG, "Bad activity token: " + token, e);
+        }
+        return null;
     }
 
     private final boolean updateLRUListLocked(ActivityRecord r) {
@@ -509,7 +518,7 @@
             Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
                     mService.mConfiguration,
                     r.mayFreezeScreenLocked(app) ? r : null);
-            mService.updateConfigurationLocked(config, r);
+            mService.updateConfigurationLocked(config, r, false);
         }
 
         r.app = app;
@@ -550,6 +559,7 @@
             r.forceNewConfig = false;
             showAskCompatModeDialogLocked(r);
             r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
+            app.hasShownUi = true;
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     System.identityHashCode(r),
                     r.info, r.compat, r.icicle, results, newIntents, !andResume,
@@ -604,6 +614,8 @@
             // As part of the process of launching, ActivityThread also performs
             // a resume.
             r.state = ActivityState.RESUMED;
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
+                    + " (starting new instance)");
             r.stopped = false;
             mResumedActivity = r;
             r.task.touchActiveTime();
@@ -617,6 +629,8 @@
             // should look like we asked it to pause+stop (but remain visible),
             // and it has done so and reported back the current icicle and
             // other state.
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
+                    + " (starting in stopped state)");
             r.state = ActivityState.STOPPED;
             r.stopped = true;
         }
@@ -797,7 +811,8 @@
             resumeTopActivityLocked(null);
             return;
         }
-        if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
+        if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
+        else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
         mResumedActivity = null;
         mPausingActivity = prev;
         mLastPausedActivity = prev;
@@ -879,6 +894,8 @@
                 r = mHistory.get(index);
                 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
                 if (mPausingActivity == r) {
+                    if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
+                            + (timeout ? " (due to timeout)" : " (pause complete)"));
                     r.state = ActivityState.PAUSED;
                     completePauseLocked();
                 } else {
@@ -891,6 +908,22 @@
         }
     }
 
+    final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
+            CharSequence description) {
+        r.icicle = icicle;
+        r.haveState = true;
+        r.updateThumbnail(thumbnail, description);
+        r.stopped = true;
+        if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
+        r.state = ActivityState.STOPPED;
+        if (!r.finishing) {
+            if (r.configDestroy) {
+                destroyActivityLocked(r, true, false);
+                resumeTopActivityLocked(null);
+            }
+        }
+    }
+
     private final void completePauseLocked() {
         ActivityRecord prev = mPausingActivity;
         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
@@ -914,7 +947,7 @@
                     // instance right now, we need to first completely stop
                     // the current instance before starting the new one.
                     if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
-                    destroyActivityLocked(prev, true);
+                    destroyActivityLocked(prev, true, false);
                 } else {
                     mStoppingActivities.add(prev);
                     if (mStoppingActivities.size() > 3) {
@@ -1371,6 +1404,7 @@
 
             mService.updateCpuStats();
             
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
             next.state = ActivityState.RESUMED;
             mResumedActivity = next;
             next.task.touchActiveTime();
@@ -1391,7 +1425,7 @@
                     if (config != null) {
                         next.frozenBeforeDestroy = true;
                     }
-                    updated = mService.updateConfigurationLocked(config, next);
+                    updated = mService.updateConfigurationLocked(config, next, false);
                 }
             }
             if (!updated) {
@@ -1447,6 +1481,8 @@
 
             } catch (Exception e) {
                 // Whoops, need to restart this activity!
+                if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
+                        + lastState + ": " + next);
                 next.state = lastState;
                 mResumedActivity = lastResumedActivity;
                 Slog.i(TAG, "Restarting because process died: " + next);
@@ -2782,7 +2818,7 @@
                 mConfigWillChange = false;
                 if (DEBUG_CONFIGURATION) Slog.v(TAG,
                         "Updating to new configuration after starting activity.");
-                mService.updateConfigurationLocked(config, null);
+                mService.updateConfigurationLocked(config, null, false);
             }
             
             Binder.restoreCallingIdentity(origId);
@@ -2960,6 +2996,8 @@
             r.resumeKeyDispatchingLocked();
             try {
                 r.stopped = false;
+                if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
+                        + " (stop requested)");
                 r.state = ActivityState.STOPPING;
                 if (DEBUG_VISBILITY) Slog.v(
                         TAG, "Stopping visible=" + r.visible + " for " + r);
@@ -2977,9 +3015,10 @@
                 Slog.w(TAG, "Exception thrown during pause", e);
                 // Just in case, assume it to be stopped.
                 r.stopped = true;
+                if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
                 r.state = ActivityState.STOPPED;
                 if (r.configDestroy) {
-                    destroyActivityLocked(r, true);
+                    destroyActivityLocked(r, true, false);
                 }
             }
         }
@@ -3145,7 +3184,7 @@
         for (i=0; i<NF; i++) {
             ActivityRecord r = (ActivityRecord)finishes.get(i);
             synchronized (mService) {
-                destroyActivityLocked(r, true);
+                destroyActivityLocked(r, true, false);
             }
         }
 
@@ -3340,6 +3379,8 @@
                     checkReadyForSleepLocked();
                 }
             }
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
+                    + " (finish requested)");
             r.state = ActivityState.STOPPING;
             mService.updateOomAdjLocked();
             return r;
@@ -3353,6 +3394,7 @@
             mResumedActivity = null;
         }
         final ActivityState prevState = r.state;
+        if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
         r.state = ActivityState.FINISHING;
 
         if (mode == FINISH_IMMEDIATELY
@@ -3360,7 +3402,7 @@
                 || prevState == ActivityState.INITIALIZING) {
             // If this activity is already stopped, we can just finish
             // it right now.
-            return destroyActivityLocked(r, true) ? null : r;
+            return destroyActivityLocked(r, true, true) ? null : r;
         } else {
             // Need to go through the full pause cycle to get this
             // activity into the stopped state and then finish it.
@@ -3378,7 +3420,8 @@
      * processing going away, in which case there is no remaining client-side
      * state to destroy so only the cleanup here is needed.
      */
-    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices) {
+    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
+            boolean setState) {
         if (mResumedActivity == r) {
             mResumedActivity = null;
         }
@@ -3389,6 +3432,11 @@
         r.configDestroy = false;
         r.frozenBeforeDestroy = false;
 
+        if (setState) {
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
+            r.state = ActivityState.DESTROYED;
+        }
+
         // Make sure this record is no longer in the pending finishes list.
         // This could happen, for example, if we are trimming activities
         // down to the max limit while they are still waiting to finish.
@@ -3428,6 +3476,8 @@
             r.makeFinishing();
             mHistory.remove(r);
             r.takeFromHistory();
+            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
+                    + " (removed from history)");
             r.state = ActivityState.DESTROYED;
             mService.mWindowManager.removeAppToken(r);
             if (VALIDATE_TOKENS) {
@@ -3453,6 +3503,22 @@
         }
     }
     
+    final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj) {
+        for (int i=mHistory.size()-1; i>=0; i--) {
+            ActivityRecord r = mHistory.get(i);
+            if (owner != null && r.app != owner) {
+                continue;
+            }
+            // We can destroy this one if we have its icicle saved and
+            // it is not in the process of pausing/stopping/finishing.
+            if (r.app != null && r.haveState && !r.visible && r.stopped && !r.finishing
+                    && r.state != ActivityState.DESTROYING
+                    && r.state != ActivityState.DESTROYED) {
+                destroyActivityLocked(r, true, oomAdj);
+            }
+        }
+    }
+
     /**
      * Destroy the current CLIENT SIDE instance of an activity.  This may be
      * called both when actually finishing an activity, or when performing
@@ -3460,7 +3526,7 @@
      * but then create a new client-side object for this same HistoryRecord.
      */
     final boolean destroyActivityLocked(ActivityRecord r,
-            boolean removeFromApp) {
+            boolean removeFromApp, boolean oomAdj) {
         if (DEBUG_SWITCH) Slog.v(
             TAG, "Removing activity: token=" + r
               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
@@ -3470,7 +3536,7 @@
 
         boolean removedFromHistory = false;
         
-        cleanUpActivityLocked(r, false);
+        cleanUpActivityLocked(r, false, false);
 
         final boolean hadApp = r.app != null;
         
@@ -3488,7 +3554,7 @@
                 if (r.app.activities.size() == 0) {
                     // No longer have activities, so update location in
                     // LRU list.
-                    mService.updateLruProcessLocked(r.app, true, false);
+                    mService.updateLruProcessLocked(r.app, oomAdj, false);
                 }
             }
 
@@ -3513,12 +3579,23 @@
             r.app = null;
             r.nowVisible = false;
             
+            // If the activity is finishing, we need to wait on removing it
+            // from the list to give it a chance to do its cleanup.  During
+            // that time it may make calls back with its token so we need to
+            // be able to find it on the list and so we don't want to remove
+            // it from the list yet.  Otherwise, we can just immediately put
+            // it in the destroyed state since we are not removing it from the
+            // list.
             if (r.finishing && !skipDestroy) {
+                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
+                        + " (destroy requested)");
                 r.state = ActivityState.DESTROYING;
                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
                 msg.obj = r;
                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
             } else {
+                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
+                        + " (destroy skipped)");
                 r.state = ActivityState.DESTROYED;
             }
         } else {
@@ -3527,6 +3604,8 @@
                 removeActivityFromHistoryLocked(r);
                 removedFromHistory = true;
             } else {
+                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
+                        + " (no app)");
                 r.state = ActivityState.DESTROYED;
             }
         }
@@ -3919,7 +3998,7 @@
             if (r.app == null || r.app.thread == null) {
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
                         "Switch is destroying non-running " + r);
-                destroyActivityLocked(r, true);
+                destroyActivityLocked(r, true, false);
             } else if (r.state == ActivityState.PAUSING) {
                 // A little annoying: we are waiting for this activity to
                 // finish pausing.  Let's not do anything now, but just
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 22acda9..0106114 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -32,6 +32,7 @@
     final int clientLabel;          // String resource labeling this client.
     final PendingIntent clientIntent; // How to launch the client.
     String stringName;              // Caching of toString.
+    boolean serviceDead;            // Well is it?
     
     void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "binding=" + binding);
@@ -61,6 +62,9 @@
         sb.append("ConnectionRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
+        if (serviceDead) {
+            sb.append("DEAD ");
+        }
         sb.append(binding.service.shortName);
         sb.append(":@");
         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index da83e7d..5b59363 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -61,10 +61,12 @@
     int setAdj;                 // Last set OOM adjustment for this process
     int curSchedGroup;          // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
+    int trimMemoryLevel;        // Last selected memory trimming level
     boolean keeping;            // Actively running code so don't kill due to that?
     boolean setIsForeground;    // Running foreground UI when last set?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
+    boolean hasShownUi;         // Has UI been shown in this process since it was started?
     boolean bad;                // True if disabled in the bad process list
     boolean killedBackground;   // True when proc has been killed due to too many bg
     String waitingToKill;       // Process is waiting to be killed when in the bg; reason
@@ -72,6 +74,7 @@
     int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
     int lruSeq;                 // Sequence id for identifying LRU update cycles
     CompatibilityInfo compat;   // last used compatibility mode
+    IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
     ComponentName instrumentationClass;// class installed to instrument app
     ApplicationInfo instrumentationInfo; // the application being instrumented
     String instrumentationProfileFile; // where to save profiling
@@ -181,7 +184,9 @@
                 pw.print(" cur="); pw.print(curAdj);
                 pw.print(" set="); pw.println(setAdj);
         pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);
-                pw.print(" setSchedGroup="); pw.println(setSchedGroup);
+                pw.print(" setSchedGroup="); pw.print(setSchedGroup);
+                pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
+                pw.print(" hasShownUi="); pw.println(hasShownUi);
         pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
                 pw.print(" foregroundServices="); pw.print(foregroundServices);
                 pw.print(" forcingToForeground="); pw.println(forcingToForeground);
@@ -295,6 +300,13 @@
         }
     }
     
+    public void unlinkDeathRecipient() {
+        if (deathRecipient != null && thread != null) {
+            thread.asBinder().unlinkToDeath(deathRecipient, 0);
+        }
+        deathRecipient = null;
+    }
+
     public String toShortString() {
         if (shortStringName != null) {
             return shortStringName;
@@ -305,8 +317,6 @@
     }
     
     void toShortString(StringBuilder sb) {
-        sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(' ');
         sb.append(pid);
         sb.append(':');
         sb.append(processName);
@@ -320,6 +330,8 @@
         }
         StringBuilder sb = new StringBuilder(128);
         sb.append("ProcessRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
         toShortString(sb);
         sb.append('}');
         return stringName = sb.toString();
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index d7d4b03..ce45998 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -36,7 +36,6 @@
 import android.net.NetworkInfo;
 import android.net.NetworkUtils;
 import android.os.Binder;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -76,10 +75,6 @@
     private final static String TAG = "Tethering";
     private final static boolean DEBUG = true;
 
-    private boolean mBooted = false;
-    //used to remember if we got connected before boot finished
-    private boolean mDeferedUsbConnection = false;
-
     // TODO - remove both of these - should be part of interface inspection/selection stuff
     private String[] mTetherableUsbRegexs;
     private String[] mTetherableWifiRegexs;
@@ -126,10 +121,9 @@
 
     private Notification mTetheredNotification;
 
-    // whether we can tether is the && of these two - they come in as separate
-    // broadcasts so track them so we can decide what to do when either changes
-    private boolean mUsbMassStorageOff;  // track the status of USB Mass Storage
-    private boolean mUsbConnected;       // track the status of USB connection
+    private boolean mRndisEnabled;       // track the RNDIS function enabled state
+    private boolean mUsbTetherRequested; // true if USB tethering should be started
+                                         // when RNDIS is enabled
 
     public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
         mContext = context;
@@ -149,7 +143,6 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(UsbManager.ACTION_USB_STATE);
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
         mContext.registerReceiver(mStateReceiver, filter);
 
         filter = new IntentFilter();
@@ -158,9 +151,6 @@
         filter.addDataScheme("file");
         mContext.registerReceiver(mStateReceiver, filter);
 
-        mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
-                Environment.getExternalStorageState());
-
         mDhcpRange = context.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_dhcp_range);
         if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
@@ -212,7 +202,11 @@
                     sm.start();
                 }
             } else {
-                if (sm != null) {
+                if (isUsb(iface)) {
+                    // ignore usb0 down after enabling RNDIS
+                    // we will handle disconnect in interfaceRemoved instead
+                    Log.d(TAG, "ignoring interface down for " + iface);
+                } else if (sm != null) {
                     sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
                     mIfaces.remove(iface);
                 }
@@ -221,6 +215,8 @@
     }
 
     public void interfaceLinkStateChanged(String iface, boolean up) {
+        if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
+        interfaceStatusChanged(iface, up);
     }
 
     private boolean isUsb(String iface) {
@@ -243,7 +239,9 @@
         }
         return false;
     }
+
     public void interfaceAdded(String iface) {
+        if (DEBUG) Log.d(TAG, "interfaceAdded " + iface);
         boolean found = false;
         boolean usb = false;
         if (isWifi(iface)) {
@@ -275,6 +273,7 @@
     }
 
     public void interfaceRemoved(String iface) {
+        if (DEBUG) Log.d(TAG, "interfaceRemoved " + iface);
         synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (sm == null) {
@@ -288,6 +287,8 @@
         }
     }
 
+    public void limitReached(String limitName, String iface) {}
+
     public int tether(String iface) {
         Log.d(TAG, "Tethering " + iface);
         TetherInterfaceSM sm = null;
@@ -454,47 +455,28 @@
         }
     }
 
-    private void updateUsbStatus() {
-        boolean enable = mUsbConnected && mUsbMassStorageOff;
-
-        if (mBooted) {
-            enableUsbIfaces(enable);
-        }
-    }
-
     private class StateReceiver extends BroadcastReceiver {
         public void onReceive(Context content, Intent intent) {
             String action = intent.getAction();
             if (action.equals(UsbManager.ACTION_USB_STATE)) {
-                mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
-                updateUsbStatus();
-            } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
-                mUsbMassStorageOff = false;
-                updateUsbStatus();
-            }
-            else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
-                mUsbMassStorageOff = true;
-                updateUsbStatus();
+                synchronized (Tethering.this) {
+                    boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+                    mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
+                    // start tethering if we have a request pending
+                    if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+                        tetherUsb(true);
+                    }
+                    mUsbTetherRequested = false;
+                }
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
                 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
-            } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
-                mBooted = true;
-                updateUsbStatus();
             }
         }
     }
 
-    // used on cable insert/remove
-    private void enableUsbIfaces(boolean enable) {
-        // add/remove USB interfaces when USB is connected/disconnected
-        for (String intf : mTetherableUsbRegexs) {
-            if (enable) {
-                interfaceAdded(intf);
-            } else {
-                interfaceRemoved(intf);
-            }
-        }
+    private void tetherUsb(boolean enable) {
+        if (DEBUG) Log.d(TAG, "tetherUsb " + enable);
 
         String[] ifaces = new String[0];
         try {
@@ -505,83 +487,50 @@
         }
         for (String iface : ifaces) {
             if (isUsb(iface)) {
-                if (enable) {
-                    interfaceAdded(iface);
-                } else {
-                    interfaceRemoved(iface);
+                int result = (enable ? tether(iface) : untether(iface));
+                if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                    return;
                 }
             }
         }
-    }
-
-    // toggled when we enter/leave the fully tethered state
-    private boolean enableUsbRndis(boolean enabled) {
-        if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")");
-
-        UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
-        if (usbManager == null) {
-            Log.d(TAG, "could not get UsbManager");
-            return false;
-        }
-        try {
-            if (enabled) {
-                usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
-            } else {
-                usbManager.setCurrentFunction(null, false);
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error toggling usb RNDIS", e);
-            return false;
-        }
-        return true;
+        Log.e(TAG, "unable start or stop USB tethering");
     }
 
     // configured when we start tethering and unconfig'd on error or conclusion
     private boolean configureUsbIface(boolean enabled) {
         if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
 
-        if (enabled) {
-            // must enable RNDIS first to create the interface
-            enableUsbRndis(enabled);
-        }
-
+        // toggle the USB interfaces
+        String[] ifaces = new String[0];
         try {
-            // bring toggle the interfaces
-            String[] ifaces = new String[0];
-            try {
-                ifaces = mNMService.listInterfaces();
-            } catch (Exception e) {
-                Log.e(TAG, "Error listing Interfaces", e);
-                return false;
-            }
-            for (String iface : ifaces) {
-                if (isUsb(iface)) {
-                    InterfaceConfiguration ifcg = null;
-                    try {
-                        ifcg = mNMService.getInterfaceConfig(iface);
-                        if (ifcg != null) {
-                            InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
-                            ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
-                            if (enabled) {
-                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
-                            } else {
-                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
-                            }
-                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
-                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
-                            mNMService.setInterfaceConfig(iface, ifcg);
-                        }
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error configuring interface " + iface, e);
-                        return false;
-                    }
-                }
-             }
-        } finally {
-            if (!enabled) {
-                enableUsbRndis(false);
-            }
+            ifaces = mNMService.listInterfaces();
+        } catch (Exception e) {
+            Log.e(TAG, "Error listing Interfaces", e);
+            return false;
         }
+        for (String iface : ifaces) {
+            if (isUsb(iface)) {
+                InterfaceConfiguration ifcg = null;
+                try {
+                    ifcg = mNMService.getInterfaceConfig(iface);
+                    if (ifcg != null) {
+                        InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
+                        ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
+                        if (enabled) {
+                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+                        } else {
+                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
+                        }
+                        ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
+                        ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
+                        mNMService.setInterfaceConfig(iface, ifcg);
+                    }
+                } catch (Exception e) {
+                    Log.e(TAG, "Error configuring interface " + iface, e);
+                    return false;
+                }
+            }
+         }
 
         return true;
     }
@@ -598,6 +547,29 @@
         return mTetherableBluetoothRegexs;
     }
 
+    public int setUsbTethering(boolean enable) {
+        if (DEBUG) Log.d(TAG, "setUsbTethering(" + enable + ")");
+        UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
+
+        synchronized (this) {
+            if (enable) {
+                if (mRndisEnabled) {
+                    tetherUsb(true);
+                } else {
+                    mUsbTetherRequested = true;
+                    usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+                }
+            } else {
+                tetherUsb(false);
+                if (mRndisEnabled) {
+                    usbManager.setCurrentFunction(null, false);
+                }
+                mUsbTetherRequested = false;
+            }
+        }
+        return ConnectivityManager.TETHER_ERROR_NO_ERROR;
+    }
+
     public int[] getUpstreamIfaceTypes() {
         int values[] = new int[mUpstreamIfaceTypes.size()];
         Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index c185012..9cb772e 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -41,6 +41,9 @@
 import com.android.internal.net.VpnConfig;
 import com.android.server.ConnectivityService.VpnCallback;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.Charsets;
 import java.util.Arrays;
@@ -67,22 +70,14 @@
 
     /**
      * Protect a socket from routing changes by binding it to the given
-     * interface. The socket IS closed by this method.
+     * interface. The socket is NOT closed by this method.
      *
      * @param socket The socket to be bound.
      * @param name The name of the interface.
      */
     public void protect(ParcelFileDescriptor socket, String interfaze) {
-        try {
-            mContext.enforceCallingPermission(VPN, "protect");
-            jniProtect(socket.getFd(), interfaze);
-        } finally {
-            try {
-                socket.close();
-            } catch (Exception e) {
-                // ignore
-            }
-        }
+        mContext.enforceCallingPermission(VPN, "protect");
+        jniProtect(socket.getFd(), interfaze);
     }
 
     /**
@@ -192,10 +187,15 @@
         }
 
         // Configure the interface. Abort if any of these steps fails.
-        ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(
-                jniConfigure(config.mtu, config.addresses, config.routes));
+        ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
         try {
             String interfaze = jniGetName(tun.getFd());
+            if (jniSetAddresses(interfaze, config.addresses) < 1) {
+                throw new IllegalArgumentException("At least one address must be specified");
+            }
+            if (config.routes != null) {
+                jniSetRoutes(interfaze, config.routes);
+            }
             if (mInterface != null && !mInterface.equals(interfaze)) {
                 jniReset(mInterface);
             }
@@ -222,18 +222,24 @@
     }
 
     // INetworkManagementEventObserver.Stub
-    public void interfaceStatusChanged(String interfaze, boolean up) {
-    }
-
-    // INetworkManagementEventObserver.Stub
-    public void interfaceLinkStateChanged(String interfaze, boolean up) {
-    }
-
-    // INetworkManagementEventObserver.Stub
     public void interfaceAdded(String interfaze) {
     }
 
     // INetworkManagementEventObserver.Stub
+    public synchronized void interfaceStatusChanged(String interfaze, boolean up) {
+        if (!up && mLegacyVpnRunner != null) {
+            mLegacyVpnRunner.check(interfaze);
+        }
+    }
+
+    // INetworkManagementEventObserver.Stub
+    public synchronized void interfaceLinkStateChanged(String interfaze, boolean up) {
+        if (!up && mLegacyVpnRunner != null) {
+            mLegacyVpnRunner.check(interfaze);
+        }
+    }
+
+    // INetworkManagementEventObserver.Stub
     public synchronized void interfaceRemoved(String interfaze) {
         if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
             mCallback.restore();
@@ -242,6 +248,8 @@
         }
     }
 
+    public void limitReached(String limitName, String iface) {}
+
     private void showNotification(VpnConfig config, String label, Bitmap icon) {
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -279,8 +287,10 @@
         }
     }
 
-    private native int jniConfigure(int mtu, String addresses, String routes);
+    private native int jniCreate(int mtu);
     private native String jniGetName(int tun);
+    private native int jniSetAddresses(String interfaze, String addresses);
+    private native int jniSetRoutes(String interfaze, String routes);
     private native void jniReset(String interfaze);
     private native int jniCheck(String interfaze);
     private native void jniProtect(int socket, String interfaze);
@@ -323,11 +333,11 @@
      */
     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 String mOuterInterface;
         private final LegacyVpnInfo mInfo;
 
         private long mTimer = -1;
@@ -339,17 +349,27 @@
             mArguments = new String[][] {racoon, mtpd};
             mInfo = new LegacyVpnInfo();
 
+            // This is the interface which VPN is running on.
+            mOuterInterface = mConfig.interfaze;
+
             // Legacy VPN is not a real package, so we use it to carry the key.
             mInfo.key = mConfig.packagz;
             mConfig.packagz = VpnConfig.LEGACY_VPN;
         }
 
+        public void check(String interfaze) {
+            if (interfaze.equals(mOuterInterface)) {
+                Log.i(TAG, "Legacy VPN is going down with " + interfaze);
+                exit();
+            }
+        }
+
         public void exit() {
             // We assume that everything is reset after the daemons die.
+            interrupt();
             for (String daemon : mDaemons) {
                 SystemProperties.set("ctl.stop", daemon);
             }
-            interrupt();
         }
 
         public LegacyVpnInfo getInfo() {
@@ -376,11 +396,11 @@
             if (mTimer == -1) {
                 mTimer = now;
                 Thread.sleep(1);
-            } else if (now - mTimer <= 30000) {
+            } else if (now - mTimer <= 60000) {
                 Thread.sleep(yield ? 200 : 1);
             } else {
                 mInfo.state = LegacyVpnInfo.STATE_TIMEOUT;
-                throw new IllegalStateException("time is up");
+                throw new IllegalStateException("Time is up");
             }
         }
 
@@ -404,12 +424,11 @@
                     }
                 }
 
-                // 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);
+                // Clear the previous state.
+                File state = new File("/data/misc/vpn/state");
+                state.delete();
+                if (state.exists()) {
+                    throw new IllegalStateException("Cannot delete the state");
                 }
 
                 // Check if we need to restart any of the daemons.
@@ -461,29 +480,34 @@
                     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");
+                        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.shutdownOutput();
+
+                    // Wait for End-of-File.
+                    InputStream in = socket.getInputStream();
+                    while (true) {
+                        try {
+                            if (in.read() == -1) {
+                                break;
+                            }
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        checkpoint(true);
+                    }
                     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"))) {
-
+                // Wait for the daemons to create the new state.
+                while (!state.exists()) {
                     // Check if a running daemon is dead.
                     for (int i = 0; i < mDaemons.length; ++i) {
                         String daemon = mDaemons[i];
@@ -495,20 +519,45 @@
                     checkpoint(true);
                 }
 
-                // Now we are connected. Get the interface.
-                mConfig.interfaze = SystemProperties.get("vpn.via");
+                // Now we are connected. Read and parse the new state.
+                byte[] buffer = new byte[(int) state.length()];
+                if (new FileInputStream(state).read(buffer) != buffer.length) {
+                    throw new IllegalStateException("Cannot read the state");
+                }
+                String[] parameters = new String(buffer, Charsets.UTF_8).split("\n", -1);
+                if (parameters.length != 6) {
+                    throw new IllegalStateException("Cannot parse the state");
+                }
 
-                // Get the DNS servers if they are not set in config.
+                // Set the interface and the addresses in the config.
+                mConfig.interfaze = parameters[0].trim();
+                mConfig.addresses = parameters[1].trim();
+
+                // Set the routes if they are not set in the config.
+                if (mConfig.routes == null || mConfig.routes.isEmpty()) {
+                    mConfig.routes = parameters[2].trim();
+                }
+
+                // Set the DNS servers if they are not set in the config.
                 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
-                    String dnsServers = SystemProperties.get("vpn.dns").trim();
+                    String dnsServers = parameters[3].trim();
                     if (!dnsServers.isEmpty()) {
                         mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
                     }
                 }
 
-                // TODO: support search domains from ISAKMP mode config.
+                // Set the search domains if they are not set in the config.
+                if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
+                    String searchDomains = parameters[4].trim();
+                    if (!searchDomains.isEmpty()) {
+                        mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
+                    }
+                }
 
-                // The final step must be synchronized.
+                // Set the routes.
+                jniSetRoutes(mConfig.interfaze, mConfig.routes);
+
+                // Here is the last step and it must be done synchronously.
                 synchronized (Vpn.this) {
                     // Check if the thread is interrupted while we are waiting.
                     checkpoint(false);
diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java
index e3131fe..b38ea13 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -47,7 +47,9 @@
     public GeocoderProxy(Context context, String serviceName) {
         mContext = context;
         mIntent = new Intent(serviceName);
-        mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+        mContext.bindService(mIntent, mServiceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                | Context.BIND_ALLOW_OOM_MANAGEMENT);
     }
 
     /**
@@ -58,7 +60,9 @@
         synchronized (mMutex) {
             mContext.unbindService(mServiceConnection);
             mServiceConnection = new Connection();
-            mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+            mContext.bindService(mIntent, mServiceConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                    | Context.BIND_ALLOW_OOM_MANAGEMENT);
         }
     }
 
@@ -67,14 +71,12 @@
         private IGeocodeProvider mProvider;
 
         public void onServiceConnected(ComponentName className, IBinder service) {
-            Log.d(TAG, "onServiceConnected " + className);
             synchronized (this) {
                 mProvider = IGeocodeProvider.Stub.asInterface(service);
             }
         }
 
         public void onServiceDisconnected(ComponentName className) {
-            Log.d(TAG, "onServiceDisconnected " + className);
             synchronized (this) {
                 mProvider = null;
             }
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java
index 1a1a170..0bc1664 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -28,7 +28,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.WorkSource;
 import android.util.Log;
 
@@ -65,7 +64,9 @@
         mName = name;
         mIntent = new Intent(serviceName);
         mHandler = handler;
-        mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+        mContext.bindService(mIntent, mServiceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                | Context.BIND_ALLOW_OOM_MANAGEMENT);
     }
 
     /**
@@ -76,7 +77,9 @@
         synchronized (mMutex) {
             mContext.unbindService(mServiceConnection);
             mServiceConnection = new Connection();
-            mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+            mContext.bindService(mIntent, mServiceConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                    | Context.BIND_ALLOW_OOM_MANAGEMENT);
         }
     }
 
@@ -88,7 +91,6 @@
         private DummyLocationProvider mCachedAttributes;  // synchronized by mMutex
 
         public void onServiceConnected(ComponentName className, IBinder service) {
-            Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className);
             synchronized (this) {
                 mProvider = ILocationProvider.Stub.asInterface(service);
                 if (mProvider != null) {
@@ -98,7 +100,6 @@
         }
 
         public void onServiceDisconnected(ComponentName className) {
-            Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className);
             synchronized (this) {
                 mProvider = null;
             }
diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java
new file mode 100644
index 0000000..0d1c3b2
--- /dev/null
+++ b/services/java/com/android/server/net/NetworkAlertObserver.java
@@ -0,0 +1,44 @@
+/*
+ * 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.net;
+
+import android.net.INetworkManagementEventObserver;
+
+/**
+ * @hide
+ */
+public abstract class NetworkAlertObserver extends INetworkManagementEventObserver.Stub {
+    @Override
+    public void interfaceStatusChanged(String iface, boolean up) {
+        // ignored; interface changes come through ConnectivityService
+    }
+
+    @Override
+    public void interfaceRemoved(String iface) {
+        // ignored; interface changes come through ConnectivityService
+    }
+
+    @Override
+    public void interfaceLinkStateChanged(String iface, boolean up) {
+        // ignored; interface changes come through ConnectivityService
+    }
+
+    @Override
+    public void interfaceAdded(String iface) {
+        // ignored; interface changes come through ConnectivityService
+    }
+}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index d30b66b..756cd00 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -22,15 +22,14 @@
 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.Manifest.permission.READ_PHONE_STATE;
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
 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.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
-import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
-import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_WARNING;
 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -42,9 +41,15 @@
 import static android.net.NetworkPolicyManager.isUidValidForPolicy;
 import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
 import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
-import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
+import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -55,6 +60,7 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -63,6 +69,7 @@
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
@@ -130,25 +137,31 @@
     private static final boolean LOGD = true;
     private static final boolean LOGV = false;
 
-    private static final int VERSION_CURRENT = 1;
+    private static final int VERSION_INIT = 1;
+    private static final int VERSION_ADDED_SNOOZE = 2;
+    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
 
     private static final long KB_IN_BYTES = 1024;
     private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
     private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
 
-    private static final int TYPE_WARNING = 0x1;
-    private static final int TYPE_LIMIT = 0x2;
+    // @VisibleForTesting
+    public static final int TYPE_WARNING = 0x1;
+    public static final int TYPE_LIMIT = 0x2;
+    public static final int TYPE_LIMIT_SNOOZED = 0x3;
 
     private static final String TAG_POLICY_LIST = "policy-list";
     private static final String TAG_NETWORK_POLICY = "network-policy";
     private static final String TAG_UID_POLICY = "uid-policy";
 
     private static final String ATTR_VERSION = "version";
+    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
     private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
     private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
     private static final String ATTR_CYCLE_DAY = "cycleDay";
     private static final String ATTR_WARNING_BYTES = "warningBytes";
     private static final String ATTR_LIMIT_BYTES = "limitBytes";
+    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
     private static final String ATTR_UID = "uid";
     private static final String ATTR_POLICY = "policy";
 
@@ -161,7 +174,7 @@
     private final IActivityManager mActivityManager;
     private final IPowerManager mPowerManager;
     private final INetworkStatsService mNetworkStats;
-    private final INetworkManagementService mNetworkManagement;
+    private final INetworkManagementService mNetworkManager;
     private final TrustedTime mTime;
 
     private IConnectivityManager mConnManager;
@@ -170,18 +183,22 @@
     private final Object mRulesLock = new Object();
 
     private boolean mScreenOn;
-    private boolean mBackgroundData;
+    private boolean mRestrictBackground;
 
-    /** Current policy for network templates. */
-    private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
+    /** Defined network policies. */
+    private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
+    /** Currently active network rules for ifaces. */
+    private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
 
-    /** Current policy for each UID. */
+    /** Defined UID policies. */
     private SparseIntArray mUidPolicy = new SparseIntArray();
-    /** Current derived network rules for each UID. */
+    /** Currently derived rules for each UID. */
     private SparseIntArray mUidRules = new SparseIntArray();
 
     /** Set of ifaces that are metered. */
     private HashSet<String> mMeteredIfaces = Sets.newHashSet();
+    /** Set of over-limit templates that have been notified. */
+    private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
 
     /** Foreground at both UID and PID granularity. */
     private SparseBooleanArray mUidForeground = new SparseBooleanArray();
@@ -199,7 +216,7 @@
     // 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.
+    // TODO: migrate notifications to SystemUI
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             IPowerManager powerManager, INetworkStatsService networkStats,
@@ -220,7 +237,7 @@
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mPowerManager = checkNotNull(powerManager, "missing powerManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
-        mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement");
+        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
         mTime = checkNotNull(time, "missing TrustedTime");
 
         mHandlerThread = new HandlerThread(TAG);
@@ -242,11 +259,13 @@
         synchronized (mRulesLock) {
             // read policy from disk
             readPolicyLocked();
-            updateNotificationsLocked();
+
+            if (mRestrictBackground) {
+                updateRulesForRestrictBackgroundLocked();
+            }
         }
 
         updateScreenOn();
-        updateBackgroundData(true);
 
         try {
             mActivityManager.registerProcessObserver(mProcessObserver);
@@ -256,31 +275,37 @@
             Slog.e(TAG, "unable to register IProcessObserver", e);
         }
 
+        try {
+            mNetworkManager.registerObserver(mAlertObserver);
+        } catch (RemoteException e) {
+            // ouch, no alert updates means we fall back to
+            // ACTION_NETWORK_STATS_UPDATED broadcasts.
+            Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
+        }
+
         // TODO: traverse existing processes to know foreground state, or have
         // activitymanager dispatch current state when new observer attached.
 
         final IntentFilter screenFilter = new IntentFilter();
         screenFilter.addAction(Intent.ACTION_SCREEN_ON);
         screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
-        mContext.registerReceiver(mScreenReceiver, screenFilter);
+        mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
 
         // watch for network interfaces to be claimed
         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
 
-        // listen for uid removal to clean policy
-        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
-        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
+        // listen for package/uid changes to update policy
+        final IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(ACTION_UID_REMOVED);
+        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
 
         // 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() {
@@ -331,17 +356,28 @@
         }
     };
 
-    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
+    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and UID_REMOVED is protected
-            // broadcast.
+            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
+            // are protected broadcasts.
+
+            final String action = intent.getAction();
             final int uid = intent.getIntExtra(EXTRA_UID, 0);
             synchronized (mRulesLock) {
-                // remove any policy and update rules to clean up
-                mUidPolicy.delete(uid);
-                updateRulesForUidLocked(uid);
-                writePolicyLocked();
+                if (ACTION_PACKAGE_ADDED.equals(action)) {
+                    // update rules for UID, since it might be subject to
+                    // global background data policy.
+                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
+                    updateRulesForUidLocked(uid);
+
+                } else if (ACTION_UID_REMOVED.equals(action)) {
+                    // remove any policy and update rules to clean up.
+                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
+                    mUidPolicy.delete(uid);
+                    updateRulesForUidLocked(uid);
+                    writePolicyLocked();
+                }
             }
         }
     };
@@ -363,17 +399,26 @@
     };
 
     /**
-     * Receiver that watches for
-     * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
+     * Observer that watches for {@link INetworkManagementService} alerts.
      */
-    private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
+    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and verified CONNECTIVITY_INTERNAL
-            // permission above.
+        public void limitReached(String limitName, String iface) {
+            // only someone like NMS should be calling us
+            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
             synchronized (mRulesLock) {
-                updateBackgroundData(false);
+                if (mMeteredIfaces.contains(iface)) {
+                    try {
+                        // force stats update to make sure we have numbers that
+                        // caused alert to trigger.
+                        mNetworkStats.forceUpdate();
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "problem updating network stats");
+                    }
+
+                    updateNotificationsLocked();
+                }
             }
         }
     };
@@ -396,35 +441,71 @@
         // TODO: when switching to kernel notifications, compute next future
         // cycle boundary to recompute notifications.
 
-        // examine stats for each policy defined
-        for (NetworkPolicy policy : mNetworkPolicy) {
+        // examine stats for each active policy
+        for (NetworkPolicy policy : mNetworkRules.keySet()) {
             final long start = computeLastCycleBoundary(currentTime, policy);
             final long end = currentTime;
 
-            final long total;
+            final long totalBytes;
             try {
                 final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
                         policy.template, start, end);
                 final NetworkStats.Entry entry = stats.getValues(0, null);
-                total = entry.rxBytes + entry.txBytes;
+                totalBytes = entry.rxBytes + entry.txBytes;
             } catch (RemoteException e) {
                 Slog.w(TAG, "problem reading summary for template " + policy.template);
                 continue;
             }
 
-            if (policy.limitBytes != LIMIT_DISABLED && total >= policy.limitBytes) {
+            if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
                 cancelNotification(policy, TYPE_WARNING);
-                enqueueNotification(policy, TYPE_LIMIT);
+
+                if (policy.lastSnooze >= start) {
+                    cancelNotification(policy, TYPE_LIMIT);
+                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
+                } else {
+                    cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
+                    notifyOverLimitLocked(policy.template);
+                }
+
             } else {
                 cancelNotification(policy, TYPE_LIMIT);
+                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+                notifyUnderLimitLocked(policy.template);
 
-                if (policy.warningBytes != WARNING_DISABLED && total >= policy.warningBytes) {
-                    enqueueNotification(policy, TYPE_WARNING);
+                if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
+                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
                 } else {
                     cancelNotification(policy, TYPE_WARNING);
                 }
             }
         }
+
+        // clear notifications for non-active policies
+        for (NetworkPolicy policy : mNetworkPolicy.values()) {
+            if (!mNetworkRules.containsKey(policy)) {
+                cancelNotification(policy, TYPE_WARNING);
+                cancelNotification(policy, TYPE_LIMIT);
+                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+                notifyUnderLimitLocked(policy.template);
+            }
+        }
+    }
+
+    /**
+     * Notify that given {@link NetworkTemplate} is over
+     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
+     */
+    private void notifyOverLimitLocked(NetworkTemplate template) {
+        if (!mOverLimitNotified.contains(template)) {
+            mContext.startActivity(buildNetworkOverLimitIntent(template));
+            mOverLimitNotified.add(template);
+        }
+    }
+
+    private void notifyUnderLimitLocked(NetworkTemplate template) {
+        mOverLimitNotified.remove(template);
     }
 
     /**
@@ -439,7 +520,7 @@
      * Show notification for combined {@link NetworkPolicy} and specific type,
      * like {@link #TYPE_LIMIT}. Okay to call multiple times.
      */
-    private void enqueueNotification(NetworkPolicy policy, int type) {
+    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
         final String tag = buildNotificationTag(policy, type);
         final Notification.Builder builder = new Notification.Builder(mContext);
         builder.setOnlyAlertOnce(true);
@@ -448,8 +529,8 @@
         final Resources res = mContext.getResources();
         switch (type) {
             case TYPE_WARNING: {
-                final String title = res.getString(R.string.data_usage_warning_title);
-                final String body = res.getString(R.string.data_usage_warning_body,
+                final CharSequence title = res.getText(R.string.data_usage_warning_title);
+                final CharSequence body = res.getString(R.string.data_usage_warning_body,
                         Formatter.formatFileSize(mContext, policy.warningBytes));
 
                 builder.setSmallIcon(R.drawable.ic_menu_info_details);
@@ -457,25 +538,24 @@
                 builder.setContentTitle(title);
                 builder.setContentText(body);
 
-                final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING);
-                intent.addCategory(Intent.CATEGORY_DEFAULT);
-                intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
+                final Intent intent = buildViewDataUsageIntent(policy.template);
                 builder.setContentIntent(PendingIntent.getActivity(
                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
                 break;
             }
             case TYPE_LIMIT: {
-                final String title;
-                final String body = res.getString(R.string.data_usage_limit_body);
+                final CharSequence body = res.getText(R.string.data_usage_limit_body);
+
+                final CharSequence title;
                 switch (policy.template.getMatchRule()) {
                     case MATCH_MOBILE_3G_LOWER:
-                        title = res.getString(R.string.data_usage_3g_limit_title);
+                        title = res.getText(R.string.data_usage_3g_limit_title);
                         break;
                     case MATCH_MOBILE_4G:
-                        title = res.getString(R.string.data_usage_4g_limit_title);
+                        title = res.getText(R.string.data_usage_4g_limit_title);
                         break;
                     default:
-                        title = res.getString(R.string.data_usage_mobile_limit_title);
+                        title = res.getText(R.string.data_usage_mobile_limit_title);
                         break;
                 }
 
@@ -484,9 +564,35 @@
                 builder.setContentTitle(title);
                 builder.setContentText(body);
 
-                final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT);
-                intent.addCategory(Intent.CATEGORY_DEFAULT);
-                intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
+                final Intent intent = buildNetworkOverLimitIntent(policy.template);
+                builder.setContentIntent(PendingIntent.getActivity(
+                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+                break;
+            }
+            case TYPE_LIMIT_SNOOZED: {
+                final long overBytes = totalBytes - policy.limitBytes;
+                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
+                        Formatter.formatFileSize(mContext, overBytes));
+
+                final CharSequence title;
+                switch (policy.template.getMatchRule()) {
+                    case MATCH_MOBILE_3G_LOWER:
+                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
+                        break;
+                    case MATCH_MOBILE_4G:
+                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
+                        break;
+                    default:
+                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
+                        break;
+                }
+
+                builder.setSmallIcon(R.drawable.ic_menu_info_details);
+                builder.setTicker(title);
+                builder.setContentTitle(title);
+                builder.setContentText(body);
+
+                final Intent intent = buildViewDataUsageIntent(policy.template);
                 builder.setContentIntent(PendingIntent.getActivity(
                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
                 break;
@@ -531,7 +637,8 @@
             // permission above.
             synchronized (mRulesLock) {
                 ensureActiveMobilePolicyLocked();
-                updateIfacesLocked();
+                updateNetworkRulesLocked();
+                updateNotificationsLocked();
             }
         }
     };
@@ -541,7 +648,7 @@
      * {@link NetworkPolicy} that need to be enforced. When matches found, set
      * remaining quota based on usage cycle and historical stats.
      */
-    private void updateIfacesLocked() {
+    private void updateNetworkRulesLocked() {
         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
 
         final NetworkState[] states;
@@ -565,9 +672,9 @@
         }
 
         // build list of rules and ifaces to enforce them against
-        final HashMap<NetworkPolicy, String[]> rules = Maps.newHashMap();
+        mNetworkRules.clear();
         final ArrayList<String> ifaceList = Lists.newArrayList();
-        for (NetworkPolicy policy : mNetworkPolicy) {
+        for (NetworkPolicy policy : mNetworkPolicy.values()) {
 
             // collect all active ifaces that match this template
             ifaceList.clear();
@@ -580,7 +687,7 @@
 
             if (ifaceList.size() > 0) {
                 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
-                rules.put(policy, ifaces);
+                mNetworkRules.put(policy, ifaces);
             }
         }
 
@@ -596,8 +703,8 @@
 
         // apply each policy that we found ifaces for; compute remaining data
         // based on current cycle and historical stats, and push to kernel.
-        for (NetworkPolicy policy : rules.keySet()) {
-            final String[] ifaces = rules.get(policy);
+        for (NetworkPolicy policy : mNetworkRules.keySet()) {
+            final String[] ifaces = mNetworkRules.get(policy);
 
             final long start = computeLastCycleBoundary(currentTime, policy);
             final long end = currentTime;
@@ -618,11 +725,18 @@
                         + Arrays.toString(ifaces));
             }
 
-            // TODO: register for warning notification trigger through NMS
+            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
+            final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
 
-            if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
-                // remaining "quota" is based on usage in current cycle
-                final long quota = Math.max(0, policy.limitBytes - total);
+            if (hasLimit || hasWarning) {
+                final long quotaBytes;
+                if (hasLimit) {
+                    // remaining "quota" is based on usage in current cycle
+                    quotaBytes = Math.max(0, policy.limitBytes - total);
+                } else {
+                    // to track warning alert later, use a high quota
+                    quotaBytes = Long.MAX_VALUE;
+                }
 
                 if (ifaces.length > 1) {
                     // TODO: switch to shared quota once NMS supports
@@ -631,8 +745,20 @@
 
                 for (String iface : ifaces) {
                     removeInterfaceQuota(iface);
-                    setInterfaceQuota(iface, quota);
-                    newMeteredIfaces.add(iface);
+                    if (quotaBytes > 0) {
+                        setInterfaceQuota(iface, quotaBytes);
+                        newMeteredIfaces.add(iface);
+                    }
+                }
+            }
+
+            if (hasWarning) {
+                final long alertBytes = Math.max(0, policy.warningBytes - total);
+                for (String iface : ifaces) {
+                    removeInterfaceAlert(iface);
+                    if (alertBytes > 0) {
+                        setInterfaceAlert(iface, alertBytes);
+                    }
                 }
             }
         }
@@ -661,7 +787,7 @@
 
         // examine to see if any policy is defined for active mobile
         boolean mobileDefined = false;
-        for (NetworkPolicy policy : mNetworkPolicy) {
+        for (NetworkPolicy policy : mNetworkPolicy.values()) {
             if (policy.template.matches(probeIdent)) {
                 mobileDefined = true;
             }
@@ -670,17 +796,18 @@
         if (!mobileDefined) {
             Slog.i(TAG, "no policy for active mobile network; generating default policy");
 
-            // default mobile policy has combined 4GB warning, and assume usage
-            // cycle starts today today.
+            // build default mobile policy, and assume usage cycle starts today
+            final long warningBytes = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_networkPolicyDefaultWarning)
+                    * MB_IN_BYTES;
 
-            // TODO: move this policy definition to overlay or secure setting
             final Time time = new Time(Time.TIMEZONE_UTC);
             time.setToNow();
             final int cycleDay = time.monthDay;
 
-            final NetworkTemplate template = new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
-            mNetworkPolicy.add(
-                    new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
+            final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
+            mNetworkPolicy.put(template, new NetworkPolicy(
+                    template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
             writePolicyLocked();
         }
     }
@@ -699,12 +826,22 @@
             in.setInput(fis, null);
 
             int type;
-            int version = VERSION_CURRENT;
+            int version = VERSION_INIT;
             while ((type = in.next()) != END_DOCUMENT) {
                 final String tag = in.getName();
                 if (type == START_TAG) {
                     if (TAG_POLICY_LIST.equals(tag)) {
                         version = readIntAttribute(in, ATTR_VERSION);
+                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
+                            mRestrictBackground = readBooleanAttribute(
+                                    in, ATTR_RESTRICT_BACKGROUND);
+                        } else {
+                            try {
+                                mRestrictBackground = !mConnManager.getBackgroundDataSetting();
+                            } catch (RemoteException e) {
+                                mRestrictBackground = false;
+                            }
+                        }
 
                     } else if (TAG_NETWORK_POLICY.equals(tag)) {
                         final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
@@ -712,11 +849,17 @@
                         final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
                         final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
                         final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
+                        final long lastSnooze;
+                        if (version >= VERSION_ADDED_SNOOZE) {
+                            lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
+                        } else {
+                            lastSnooze = SNOOZE_NEVER;
+                        }
 
                         final NetworkTemplate template = new NetworkTemplate(
                                 networkTemplate, subscriberId);
-                        mNetworkPolicy.add(
-                                new NetworkPolicy(template, cycleDay, warningBytes, limitBytes));
+                        mNetworkPolicy.put(template, new NetworkPolicy(
+                                template, cycleDay, warningBytes, limitBytes, lastSnooze));
 
                     } else if (TAG_UID_POLICY.equals(tag)) {
                         final int uid = readIntAttribute(in, ATTR_UID);
@@ -754,10 +897,11 @@
             out.startDocument(null, true);
 
             out.startTag(null, TAG_POLICY_LIST);
-            writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT);
+            writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND);
+            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
 
             // write all known network policies
-            for (NetworkPolicy policy : mNetworkPolicy) {
+            for (NetworkPolicy policy : mNetworkPolicy.values()) {
                 final NetworkTemplate template = policy.template;
 
                 out.startTag(null, TAG_NETWORK_POLICY);
@@ -769,6 +913,7 @@
                 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
                 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
                 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
+                writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
                 out.endTag(null, TAG_NETWORK_POLICY);
             }
 
@@ -856,10 +1001,10 @@
         synchronized (mRulesLock) {
             mNetworkPolicy.clear();
             for (NetworkPolicy policy : policies) {
-                mNetworkPolicy.add(policy);
+                mNetworkPolicy.put(policy.template, policy);
             }
 
-            updateIfacesLocked();
+            updateNetworkRulesLocked();
             updateNotificationsLocked();
             writePolicyLocked();
         }
@@ -871,7 +1016,53 @@
         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
 
         synchronized (mRulesLock) {
-            return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]);
+            return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
+        }
+    }
+
+    @Override
+    public void snoozePolicy(NetworkTemplate template) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // try refreshing time source when stale
+        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
+            mTime.forceRefresh();
+        }
+
+        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
+                : System.currentTimeMillis();
+
+        synchronized (mRulesLock) {
+            // find and snooze local policy that matches
+            final NetworkPolicy policy = mNetworkPolicy.get(template);
+            if (policy == null) {
+                throw new IllegalArgumentException("unable to find policy for " + template);
+            }
+
+            policy.lastSnooze = currentTime;
+
+            updateNetworkRulesLocked();
+            updateNotificationsLocked();
+            writePolicyLocked();
+        }
+    }
+
+    @Override
+    public void setRestrictBackground(boolean restrictBackground) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        synchronized (mRulesLock) {
+            mRestrictBackground = restrictBackground;
+            updateRulesForRestrictBackgroundLocked();
+        }
+    }
+
+    @Override
+    public boolean getRestrictBackground() {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        synchronized (mRulesLock) {
+            return mRestrictBackground;
         }
     }
 
@@ -879,9 +1070,24 @@
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
 
+        final HashSet<String> argSet = new HashSet<String>();
+        for (String arg : args) {
+            argSet.add(arg);
+        }
+
         synchronized (mRulesLock) {
+            if (argSet.contains("unsnooze")) {
+                for (NetworkPolicy policy : mNetworkPolicy.values()) {
+                    policy.lastSnooze = SNOOZE_NEVER;
+                }
+                writePolicyLocked();
+                fout.println("Wiped snooze timestamps");
+                return;
+            }
+
+            fout.print("Restrict background: "); fout.println(mRestrictBackground);
             fout.println("Network policies:");
-            for (NetworkPolicy policy : mNetworkPolicy) {
+            for (NetworkPolicy policy : mNetworkPolicy.values()) {
                 fout.print("  "); fout.println(policy.toString());
             }
 
@@ -972,21 +1178,6 @@
         }
     }
 
-    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.
      */
@@ -1002,9 +1193,9 @@
     }
 
     /**
-     * Update rules that might be changed by {@link #mBackgroundData} value.
+     * Update rules that might be changed by {@link #mRestrictBackground} value.
      */
-    private void updateRulesForBackgroundDataLocked() {
+    private void updateRulesForRestrictBackgroundLocked() {
         // update rules for all installed applications
         final PackageManager pm = mContext.getPackageManager();
         final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
@@ -1038,7 +1229,7 @@
             // uid in background, and policy says to block metered data
             uidRules = RULE_REJECT_METERED;
         }
-        if (!uidForeground && !mBackgroundData) {
+        if (!uidForeground && mRestrictBackground) {
             // uid in background, and global background disabled
             uidRules = RULE_REJECT_METERED;
         }
@@ -1100,9 +1291,9 @@
         }
     };
 
-    private void setInterfaceQuota(String iface, long quota) {
+    private void setInterfaceQuota(String iface, long quotaBytes) {
         try {
-            mNetworkManagement.setInterfaceQuota(iface, quota);
+            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
         } catch (IllegalStateException e) {
             Slog.e(TAG, "problem setting interface quota", e);
         } catch (RemoteException e) {
@@ -1112,7 +1303,7 @@
 
     private void removeInterfaceQuota(String iface) {
         try {
-            mNetworkManagement.removeInterfaceQuota(iface);
+            mNetworkManager.removeInterfaceQuota(iface);
         } catch (IllegalStateException e) {
             Slog.e(TAG, "problem removing interface quota", e);
         } catch (RemoteException e) {
@@ -1120,9 +1311,29 @@
         }
     }
 
+    private void setInterfaceAlert(String iface, long alertBytes) {
+        try {
+            mNetworkManager.setInterfaceAlert(iface, alertBytes);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem setting interface alert", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem setting interface alert", e);
+        }
+    }
+
+    private void removeInterfaceAlert(String iface) {
+        try {
+            mNetworkManager.removeInterfaceAlert(iface);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem removing interface alert", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem removing interface alert", e);
+        }
+    }
+
     private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
         try {
-            mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
         } catch (IllegalStateException e) {
             Slog.e(TAG, "problem setting uid rules", e);
         } catch (RemoteException e) {
@@ -1136,6 +1347,24 @@
         return telephony.getSubscriberId();
     }
 
+    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+        return intent;
+    }
+
+    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+        return intent;
+    }
+
     private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
         final int size = source.size();
         for (int i = 0; i < size; i++) {
@@ -1160,32 +1389,43 @@
         fout.print("]");
     }
 
-    private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
-        final String value = in.getAttributeValue(null, name);
-        try {
-            return Integer.parseInt(value);
-        } catch (NumberFormatException e) {
-            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
+    public static class XmlUtils {
+        public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
+            final String value = in.getAttributeValue(null, name);
+            try {
+                return Integer.parseInt(value);
+            } catch (NumberFormatException e) {
+                throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
+            }
+        }
+
+        public static void writeIntAttribute(XmlSerializer out, String name, int value)
+                throws IOException {
+            out.attribute(null, name, Integer.toString(value));
+        }
+
+        public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
+            final String value = in.getAttributeValue(null, name);
+            try {
+                return Long.parseLong(value);
+            } catch (NumberFormatException e) {
+                throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
+            }
+        }
+
+        public static void writeLongAttribute(XmlSerializer out, String name, long value)
+                throws IOException {
+            out.attribute(null, name, Long.toString(value));
+        }
+
+        public static boolean readBooleanAttribute(XmlPullParser in, String name) {
+            final String value = in.getAttributeValue(null, name);
+            return Boolean.parseBoolean(value);
+        }
+
+        public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
+                throws IOException {
+            out.attribute(null, name, Boolean.toString(value));
         }
     }
-
-    private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
-        final String value = in.getAttributeValue(null, name);
-        try {
-            return Long.parseLong(value);
-        } catch (NumberFormatException e) {
-            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
-        }
-    }
-
-    private static void writeIntAttribute(XmlSerializer out, String name, int value)
-            throws IOException {
-        out.attribute(null, name, Integer.toString(value));
-    }
-
-    private static void writeLongAttribute(XmlSerializer out, String name, long value)
-            throws IOException {
-        out.attribute(null, name, Long.toString(value));
-    }
-
 }
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 54e94db..6cc01f4 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -60,6 +60,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.INetworkManagementService;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -73,11 +74,12 @@
 import com.google.android.collect.Maps;
 import com.google.android.collect.Sets;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -111,6 +113,8 @@
     private final TrustedTime mTime;
     private final NetworkStatsSettings mSettings;
 
+    private final PowerManager.WakeLock mWakeLock;
+
     private IConnectivityManager mConnManager;
 
     // @VisibleForTesting
@@ -190,6 +194,10 @@
         mTime = checkNotNull(time, "missing TrustedTime");
         mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
 
+        final PowerManager powerManager = (PowerManager) context.getSystemService(
+                Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
@@ -407,7 +415,12 @@
             // on background handler thread, and verified CONNECTIVITY_INTERNAL
             // permission above.
             synchronized (mStatsLock) {
-                updateIfacesLocked();
+                mWakeLock.acquire();
+                try {
+                    updateIfacesLocked();
+                } finally {
+                    mWakeLock.release();
+                }
             }
         }
     };
@@ -418,8 +431,12 @@
             // on background handler thread, and verified UPDATE_DEVICE_STATS
             // permission above.
             synchronized (mStatsLock) {
-                // TODO: acquire wakelock while performing poll
-                performPollLocked(true, false);
+                mWakeLock.acquire();
+                try {
+                    performPollLocked(true, false);
+                } finally {
+                    mWakeLock.release();
+                }
             }
         }
     };
@@ -432,7 +449,12 @@
             final int uid = intent.getIntExtra(EXTRA_UID, 0);
             synchronized (mStatsLock) {
                 // TODO: perform one last stats poll for UID
-                removeUidLocked(uid);
+                mWakeLock.acquire();
+                try {
+                    removeUidLocked(uid);
+                } finally {
+                    mWakeLock.release();
+                }
             }
         }
     };
@@ -719,10 +741,9 @@
         // clear any existing stats and read from disk
         mNetworkStats.clear();
 
-        FileInputStream fis = null;
+        DataInputStream in = null;
         try {
-            fis = mNetworkFile.openRead();
-            final DataInputStream in = new DataInputStream(fis);
+            in = new DataInputStream(new BufferedInputStream(mNetworkFile.openRead()));
 
             // verify file magic header intact
             final int magic = in.readInt();
@@ -751,7 +772,7 @@
         } catch (IOException e) {
             Slog.e(TAG, "problem reading network stats", e);
         } finally {
-            IoUtils.closeQuietly(fis);
+            IoUtils.closeQuietly(in);
         }
     }
 
@@ -768,10 +789,9 @@
         // clear any existing stats and read from disk
         mUidStats.clear();
 
-        FileInputStream fis = null;
+        DataInputStream in = null;
         try {
-            fis = mUidFile.openRead();
-            final DataInputStream in = new DataInputStream(fis);
+            in = new DataInputStream(new BufferedInputStream(mUidFile.openRead()));
 
             // verify file magic header intact
             final int magic = in.readInt();
@@ -826,7 +846,7 @@
         } catch (IOException e) {
             Slog.e(TAG, "problem reading uid stats", e);
         } finally {
-            IoUtils.closeQuietly(fis);
+            IoUtils.closeQuietly(in);
         }
     }
 
@@ -838,7 +858,7 @@
         FileOutputStream fos = null;
         try {
             fos = mNetworkFile.startWrite();
-            final DataOutputStream out = new DataOutputStream(fos);
+            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
 
             out.writeInt(FILE_MAGIC);
             out.writeInt(VERSION_NETWORK_INIT);
@@ -850,6 +870,7 @@
                 history.writeToStream(out);
             }
 
+            out.flush();
             mNetworkFile.finishWrite(fos);
         } catch (IOException e) {
             if (fos != null) {
@@ -871,7 +892,7 @@
         FileOutputStream fos = null;
         try {
             fos = mUidFile.startWrite();
-            final DataOutputStream out = new DataOutputStream(fos);
+            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
 
             out.writeInt(FILE_MAGIC);
             out.writeInt(VERSION_UID_WITH_TAG);
@@ -895,6 +916,7 @@
                 }
             }
 
+            out.flush();
             mUidFile.finishWrite(fos);
         } catch (IOException e) {
             if (fos != null) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index d6a15e6..88e0fa8 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -20,6 +20,7 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static libcore.io.OsConstants.S_ISLNK;
 
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.app.ResolverActivity;
@@ -76,6 +77,7 @@
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.FileUtils.FileStatus;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -128,6 +130,9 @@
 import java.util.zip.ZipFile;
 import java.util.zip.ZipOutputStream;
 
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
 /**
  * Keep track of all those .apks everywhere.
  * 
@@ -2860,8 +2865,17 @@
     }
 
     private File getDataPathForPackage(String packageName, int userId) {
-        return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
+        /*
+         * Until we fully support multiple users, return the directory we
+         * previously would have. The PackageManagerTests will need to be
+         * revised when this is changed back..
+         */
+        if (userId == 0) {
+            return new File(mAppDataDir, packageName);
+        } else {
+            return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
                 + File.separator + packageName);
+        }
     }
 
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
@@ -3329,16 +3343,27 @@
                 } else if (nativeLibraryDir.getCanonicalFile().getParent()
                         .equals(dataPathString)) {
                     /*
+                     * Make sure the native library dir isn't a symlink to
+                     * something. If it is, ask installd to remove it and create
+                     * a directory so we can copy to it afterwards.
+                     */
+                    boolean isSymLink;
+                    try {
+                        isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
+                    } catch (ErrnoException e) {
+                        // This shouldn't happen, but we'll fail-safe.
+                        isSymLink = true;
+                    }
+                    if (isSymLink) {
+                        mInstaller.unlinkNativeLibraryDirectory(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.
+                     * the libraries if necessary.
                      */
-                    Slog.i(TAG, "Unpacking native libraries for " + path);
-                    mInstaller.unlinkNativeLibraryDirectory(dataPathString);
-                    NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
+                    NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
                 } else {
                     Slog.i(TAG, "Linking native library dir for " + path);
                     mInstaller.linkNativeLibraryDirectory(dataPathString,
@@ -7921,7 +7946,7 @@
                                                 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
                                             returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                         } else {
-                                            NativeLibraryHelper.copyNativeBinariesLI(new File(
+                                            NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
                                                     newCodePath), new File(newNativePath));
                                         }
                                     } else {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 5ed7988..f270003 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1093,8 +1093,7 @@
             serializer.attribute(null, "uidError", "true");
         }
         if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
-            serializer.attribute(null, "enabled",
-                    pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED ? "true" : "false");
+            serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
         }
         if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
             serializer.attribute(null, "installStatus", "false");
@@ -1644,17 +1643,21 @@
             packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
             final String enabledStr = parser.getAttributeValue(null, "enabled");
             if (enabledStr != null) {
-                if (enabledStr.equalsIgnoreCase("true")) {
-                    packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
-                } else if (enabledStr.equalsIgnoreCase("false")) {
-                    packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
-                } else if (enabledStr.equalsIgnoreCase("default")) {
-                    packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
-                } else {
-                    PackageManagerService.reportSettingsProblem(Log.WARN,
-                            "Error in package manager settings: package " + name
-                                    + " has bad enabled value: " + idStr + " at "
-                                    + parser.getPositionDescription());
+                try {
+                    packageSetting.enabled = Integer.parseInt(enabledStr);
+                } catch (NumberFormatException e) {
+                    if (enabledStr.equalsIgnoreCase("true")) {
+                        packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+                    } else if (enabledStr.equalsIgnoreCase("false")) {
+                        packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
+                    } else if (enabledStr.equalsIgnoreCase("default")) {
+                        packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+                    } else {
+                        PackageManagerService.reportSettingsProblem(Log.WARN,
+                                "Error in package manager settings: package " + name
+                                        + " has bad enabled value: " + idStr + " at "
+                                        + parser.getPositionDescription());
+                    }
                 }
             } else {
                 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 3139798..11cb555 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -80,6 +81,7 @@
     private static final int MSG_ENABLE_ADB = 1;
     private static final int MSG_SET_CURRENT_FUNCTION = 2;
     private static final int MSG_SYSTEM_READY = 3;
+    private static final int MSG_BOOT_COMPLETED = 4;
 
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
@@ -87,7 +89,7 @@
     private static final int UPDATE_DELAY = 1000;
 
     private UsbHandler mHandler;
-    private boolean mSystemReady;
+    private boolean mBootCompleted;
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
@@ -141,10 +143,15 @@
                 Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
         mHandler = new UsbHandler(thread.getLooper());
+
+        if (nativeIsStartRequested()) {
+            if (DEBUG) Slog.d(TAG, "accessory attached at boot");
+            setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
+        }
     }
 
     public void systemReady() {
-        mSystemReady = true;
+        if (DEBUG) Slog.d(TAG, "systemReady");
 
         mNotificationManager = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -236,15 +243,22 @@
         private String mCurrentFunctions;
         private String mDefaultFunctions;
         private UsbAccessory mCurrentAccessory;
-        private boolean mDeferAccessoryAttached;
         private int mUsbNotificationId;
         private boolean mAdbNotificationShown;
 
+        private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+            public void onReceive(Context context, Intent intent) {
+                if (DEBUG) Slog.d(TAG, "boot completed");
+                mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
+            }
+        };
+
         private static final int NOTIFICATION_NONE = 0;
         private static final int NOTIFICATION_MTP = 1;
         private static final int NOTIFICATION_PTP = 2;
         private static final int NOTIFICATION_INSTALLER = 3;
-        private static final int NOTIFICATION_ADB = 4;
+        private static final int NOTIFICATION_ACCESSORY = 4;
+        private static final int NOTIFICATION_ADB = 5;
 
         public UsbHandler(Looper looper) {
             super(looper);
@@ -285,6 +299,9 @@
                 // Watch for USB configuration changes
                 mUEventObserver.startObserving(USB_STATE_MATCH);
                 mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+                mContext.registerReceiver(mBootCompletedReceiver,
+                        new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
             } catch (Exception e) {
                 Slog.e(TAG, "Error initializing UsbHandler", e);
             }
@@ -406,11 +423,9 @@
                     mCurrentAccessory = new UsbAccessory(strings);
                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
                     // defer accessoryAttached if system is not ready
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
-                    } else {
-                        mDeferAccessoryAttached = true;
-                    }
+                    } // else handle in mBootCompletedReceiver
                 } else {
                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
                 }
@@ -421,7 +436,7 @@
                 setEnabledFunctions(mDefaultFunctions);
 
                 if (mCurrentAccessory != null) {
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         mSettingsManager.accessoryDetached(mCurrentAccessory);
                     }
                     mCurrentAccessory = null;
@@ -463,7 +478,7 @@
                         // restore defaults when USB is disconnected
                         doSetCurrentFunctions(mDefaultFunctions);
                     }
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         updateUsbState();
                     }
                     break;
@@ -473,10 +488,7 @@
                 case MSG_SET_CURRENT_FUNCTION:
                     String function = (String)msg.obj;
                     boolean makeDefault = (msg.arg1 == 1);
-                    if (makeDefault) {
-                        if (function == null) {
-                            throw new NullPointerException();
-                        }
+                    if (function != null && makeDefault) {
                         if (mAdbEnabled) {
                             function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
                         }
@@ -500,7 +512,10 @@
                     updateUsbNotification();
                     updateAdbNotification();
                     updateUsbState();
-                    if (mCurrentAccessory != null && mDeferAccessoryAttached) {
+                    break;
+                case MSG_BOOT_COMPLETED:
+                    mBootCompleted = true;
+                    if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
                     break;
@@ -513,10 +528,10 @@
 
         private void updateUsbNotification() {
             if (mNotificationManager == null || !mUseUsbNotification) return;
+            int id = NOTIFICATION_NONE;
+            Resources r = mContext.getResources();
+            CharSequence title = null;
             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);
@@ -530,17 +545,24 @@
                     title = r.getText(
                         com.android.internal.R.string.usb_cd_installer_notification_title);
                     id = NOTIFICATION_INSTALLER;
+                } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
+                    title = r.getText(
+                        com.android.internal.R.string.usb_accessory_notification_title);
+                    id = NOTIFICATION_ACCESSORY;
                 } else {
-                    Slog.e(TAG, "No known USB function in updateUsbNotification");
-                }
-                if (id != mUsbNotificationId) {
-                    // clear notification if title needs changing
-                    if (mUsbNotificationId != NOTIFICATION_NONE) {
-                        mNotificationManager.cancel(mUsbNotificationId);
-                        mUsbNotificationId = NOTIFICATION_NONE;
+                    // There is a different notification for USB tethering so we don't need one here
+                    if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
+                        Slog.e(TAG, "No known USB function in updateUsbNotification");
                     }
                 }
-                if (mUsbNotificationId == NOTIFICATION_NONE) {
+            }
+            if (id != mUsbNotificationId) {
+                // clear notification if title needs changing
+                if (mUsbNotificationId != NOTIFICATION_NONE) {
+                    mNotificationManager.cancel(mUsbNotificationId);
+                    mUsbNotificationId = NOTIFICATION_NONE;
+                }
+                if (id != NOTIFICATION_NONE) {
                     CharSequence message = r.getText(
                             com.android.internal.R.string.usb_notification_message);
 
@@ -565,10 +587,6 @@
                     mNotificationManager.notify(id, notification);
                     mUsbNotificationId = id;
                 }
-
-            } else if (mUsbNotificationId != NOTIFICATION_NONE) {
-                mNotificationManager.cancel(mUsbNotificationId);
-                mUsbNotificationId = NOTIFICATION_NONE;
             }
         }
 
@@ -674,4 +692,5 @@
 
     private native String[] nativeGetAccessoryStrings();
     private native ParcelFileDescriptor nativeOpenAccessory();
+    private native boolean nativeIsStartRequested();
 }
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index d3d9df4..bfa2b39 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -101,7 +101,7 @@
     boolean firstWindowDrawn;
 
     // Input application handle used by the input dispatcher.
-    InputApplicationHandle mInputApplicationHandle;
+    final InputApplicationHandle mInputApplicationHandle;
 
     AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
         super(_service, _token.asBinder(),
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index d8fd7fe..36f5dcb 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -32,10 +32,12 @@
         final int top;
         final Surface surface;
 
-        BlackSurface(SurfaceSession session, int layer, int l, int t, int w, int h)
+        BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b)
                 throws Surface.OutOfResourcesException {
             left = l;
             top = t;
+            int w = r-l;
+            int h = b-t;
             surface = new Surface(session, 0, "BlackSurface",
                     -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
             if (WindowManagerService.SHOW_TRANSACTIONS ||
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 118cd55..b37d1c2 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -51,6 +51,8 @@
     float mCurrentX, mCurrentY;
     float mThumbOffsetX, mThumbOffsetY;
     InputChannel mServerChannel, mClientChannel;
+    InputApplicationHandle mDragApplicationHandle;
+    InputWindowHandle mDragWindowHandle;
     WindowState mTargetWindow;
     ArrayList<WindowState> mNotifiedWindows;
     boolean mDragInProgress;
@@ -91,6 +93,38 @@
             mService.mInputManager.registerInputChannel(mServerChannel, null);
             InputQueue.registerInputChannel(mClientChannel, mService.mDragInputHandler,
                     mService.mH.getLooper().getQueue());
+
+            mDragApplicationHandle = new InputApplicationHandle(null);
+            mDragApplicationHandle.name = "drag";
+            mDragApplicationHandle.dispatchingTimeoutNanos =
+                    WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+            mDragWindowHandle.name = "drag";
+            mDragWindowHandle.inputChannel = mServerChannel;
+            mDragWindowHandle.layer = getDragLayerLw();
+            mDragWindowHandle.layoutParamsFlags = 0;
+            mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
+            mDragWindowHandle.dispatchingTimeoutNanos =
+                    WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+            mDragWindowHandle.visible = true;
+            mDragWindowHandle.canReceiveKeys = false;
+            mDragWindowHandle.hasFocus = true;
+            mDragWindowHandle.hasWallpaper = false;
+            mDragWindowHandle.paused = false;
+            mDragWindowHandle.ownerPid = Process.myPid();
+            mDragWindowHandle.ownerUid = Process.myUid();
+            mDragWindowHandle.inputFeatures = 0;
+            mDragWindowHandle.scaleFactor = 1.0f;
+
+            // The drag window cannot receive new touches.
+            mDragWindowHandle.touchableRegion.setEmpty();
+
+            // The drag window covers the entire display
+            mDragWindowHandle.frameLeft = 0;
+            mDragWindowHandle.frameTop = 0;
+            mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
+            mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
         }
     }
 
diff --git a/services/java/com/android/server/wm/InputApplication.java b/services/java/com/android/server/wm/InputApplication.java
deleted file mode 100644
index e04fd31..0000000
--- a/services/java/com/android/server/wm/InputApplication.java
+++ /dev/null
@@ -1,37 +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 com.android.server.wm;
-
-
-/**
- * Describes input-related application properties for use by the input dispatcher.
- * @hide
- */
-public final class InputApplication {
-    // Application handle.
-    public InputApplicationHandle inputApplicationHandle;
-
-    // Application name.
-    public String name;
-
-    // Dispatching timeout.
-    public long dispatchingTimeoutNanos;
-
-    public void recycle() {
-        inputApplicationHandle = null;
-    }
-}
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java
index 64c8e7e..d78b1d9 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/wm/InputApplicationHandle.java
@@ -32,6 +32,12 @@
     // The window manager's application window token.
     public final AppWindowToken appWindowToken;
 
+    // Application name.
+    public String name;
+
+    // Dispatching timeout.
+    public long dispatchingTimeoutNanos;
+
     private native void nativeDispose();
 
     public InputApplicationHandle(AppWindowToken appWindowToken) {
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 65007f9..1d0857b 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -25,7 +25,6 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.os.Environment;
-import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.SystemProperties;
@@ -65,7 +64,8 @@
     private static native void nativeInit(Context context,
             Callbacks callbacks, MessageQueue messageQueue);
     private static native void nativeStart();
-    private static native void nativeSetDisplaySize(int displayId, int width, int height);
+    private static native void nativeSetDisplaySize(int displayId, int width, int height,
+            int externalWidth, int externalHeight);
     private static native void nativeSetDisplayOrientation(int displayId, int rotation);
     
     private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
@@ -83,10 +83,10 @@
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
-    private static native void nativeSetInputWindows(InputWindow[] windows);
+    private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles);
     private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
     private static native void nativeSetSystemUiVisibility(int visibility);
-    private static native void nativeSetFocusedApplication(InputApplication application);
+    private static native void nativeSetFocusedApplication(InputApplicationHandle application);
     private static native InputDevice nativeGetInputDevice(int deviceId);
     private static native void nativeGetInputConfiguration(Configuration configuration);
     private static native int[] nativeGetInputDeviceIds();
@@ -145,15 +145,17 @@
         updatePointerSpeedFromSettings();
     }
     
-    public void setDisplaySize(int displayId, int width, int height) {
-        if (width <= 0 || height <= 0) {
+    public void setDisplaySize(int displayId, int width, int height,
+            int externalWidth, int externalHeight) {
+        if (width <= 0 || height <= 0 || externalWidth <= 0 || externalHeight <= 0) {
             throw new IllegalArgumentException("Invalid display id or dimensions.");
         }
         
         if (DEBUG) {
-            Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
+            Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height
+                    + " external size " + externalWidth + "x" + externalHeight);
         }
-        nativeSetDisplaySize(displayId, width, height);
+        nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight);
     }
     
     public void setDisplayOrientation(int displayId, int rotation) {
@@ -372,11 +374,11 @@
         return nativeGetInputDeviceIds();
     }
     
-    public void setInputWindows(InputWindow[] windows) {
-        nativeSetInputWindows(windows);
+    public void setInputWindows(InputWindowHandle[] windowHandles) {
+        nativeSetInputWindows(windowHandles);
     }
     
-    public void setFocusedApplication(InputApplication application) {
+    public void setFocusedApplication(InputApplicationHandle application) {
         nativeSetFocusedApplication(application);
     }
     
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 6806634..12ef238 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import android.graphics.Rect;
-import android.os.Binder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
@@ -26,6 +25,7 @@
 import android.view.WindowManager;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
 final class InputMonitor {
     private final WindowManagerService mService;
@@ -42,12 +42,10 @@
     // When true, need to call updateInputWindowsLw().
     private boolean mUpdateInputWindowsNeeded = true;
 
-    // Temporary list of windows information to provide to the input dispatcher.
-    private InputWindowList mTempInputWindows = new InputWindowList();
-    
-    // Temporary input application object to provide to the input dispatcher.
-    private InputApplication mTempInputApplication = new InputApplication();
-    
+    // Array of window handles to provide to the input dispatcher.
+    private InputWindowHandle[] mInputWindowHandles;
+    private int mInputWindowHandleCount;
+
     // Set to true when the first input device configuration change notification
     // is received to indicate that the input devices are ready.
     private final Object mInputDevicesReadyMonitor = new Object();
@@ -68,8 +66,10 @@
 
         synchronized (mService.mWindowMap) {
             WindowState windowState = (WindowState) inputWindowHandle.windowState;
-            Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
-            mService.removeWindowLocked(windowState.mSession, windowState);
+            if (windowState != null) {
+                Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
+                mService.removeWindowLocked(windowState.mSession, windowState);
+            }
         }
     }
     
@@ -94,8 +94,11 @@
         
         if (appWindowToken == null && inputApplicationHandle != null) {
             appWindowToken = inputApplicationHandle.appWindowToken;
-            Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application "
-                    + appWindowToken.stringName);
+            if (appWindowToken != null) {
+                Slog.i(WindowManagerService.TAG,
+                        "Input event dispatching timed out sending to application "
+                                + appWindowToken.stringName);
+            }
         }
 
         if (appWindowToken != null && appWindowToken.appToken != null) {
@@ -114,32 +117,21 @@
         return 0; // abort dispatching
     }
 
-    private void addDragInputWindowLw(InputWindowList windowList) {
-        final InputWindow inputWindow = windowList.add();
-        inputWindow.inputChannel = mService.mDragState.mServerChannel;
-        inputWindow.name = "drag";
-        inputWindow.layoutParamsFlags = 0;
-        inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
-        inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
-        inputWindow.visible = true;
-        inputWindow.canReceiveKeys = false;
-        inputWindow.hasFocus = true;
-        inputWindow.hasWallpaper = false;
-        inputWindow.paused = false;
-        inputWindow.layer = mService.mDragState.getDragLayerLw();
-        inputWindow.ownerPid = Process.myPid();
-        inputWindow.ownerUid = Process.myUid();
-        inputWindow.inputFeatures = 0;
-        inputWindow.scaleFactor = 1.0f;
+    private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+        if (mInputWindowHandles == null) {
+            mInputWindowHandles = new InputWindowHandle[16];
+        }
+        if (mInputWindowHandleCount >= mInputWindowHandles.length) {
+            mInputWindowHandles = Arrays.copyOf(mInputWindowHandles,
+                    mInputWindowHandleCount * 2);
+        }
+        mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
+    }
 
-        // The drag window covers the entire display
-        inputWindow.frameLeft = 0;
-        inputWindow.frameTop = 0;
-        inputWindow.frameRight = mService.mDisplay.getRealWidth();
-        inputWindow.frameBottom = mService.mDisplay.getRealHeight();
-
-        // The drag window cannot receive new touches.
-        inputWindow.touchableRegion.setEmpty();
+    private void clearInputWindowHandlesLw() {
+        while (mInputWindowHandleCount != 0) {
+            mInputWindowHandles[--mInputWindowHandleCount] = null;
+        }
     }
 
     public void setUpdateInputWindowsNeededLw() {
@@ -154,7 +146,7 @@
         mUpdateInputWindowsNeeded = false;
 
         if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");
-        
+
         // Populate the input window list with information about all of the windows that
         // could potentially receive input.
         // As an optimization, we could try to prune the list of windows but this turns
@@ -168,7 +160,7 @@
             if (WindowManagerService.DEBUG_DRAG) {
                 Log.d(WindowManagerService.TAG, "Inserting drag window");
             }
-            addDragInputWindowLw(mTempInputWindows);
+            addInputWindowHandleLw(mService.mDragState.mDragWindowHandle);
         }
 
         final int N = windows.size();
@@ -194,48 +186,48 @@
             }
 
             // Add a window to our list of input windows.
-            final InputWindow inputWindow = mTempInputWindows.add();
-            inputWindow.inputWindowHandle = child.mInputWindowHandle;
-            inputWindow.inputChannel = child.mInputChannel;
-            inputWindow.name = child.toString();
-            inputWindow.layoutParamsFlags = flags;
-            inputWindow.layoutParamsType = type;
-            inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
-            inputWindow.visible = isVisible;
-            inputWindow.canReceiveKeys = child.canReceiveKeys();
-            inputWindow.hasFocus = hasFocus;
-            inputWindow.hasWallpaper = hasWallpaper;
-            inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
-            inputWindow.layer = child.mLayer;
-            inputWindow.ownerPid = child.mSession.mPid;
-            inputWindow.ownerUid = child.mSession.mUid;
-            inputWindow.inputFeatures = child.mAttrs.inputFeatures;
+            final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+            inputWindowHandle.inputChannel = child.mInputChannel;
+            inputWindowHandle.name = child.toString();
+            inputWindowHandle.layoutParamsFlags = flags;
+            inputWindowHandle.layoutParamsType = type;
+            inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+            inputWindowHandle.visible = isVisible;
+            inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
+            inputWindowHandle.hasFocus = hasFocus;
+            inputWindowHandle.hasWallpaper = hasWallpaper;
+            inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+            inputWindowHandle.layer = child.mLayer;
+            inputWindowHandle.ownerPid = child.mSession.mPid;
+            inputWindowHandle.ownerUid = child.mSession.mUid;
+            inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
 
             final Rect frame = child.mFrame;
-            inputWindow.frameLeft = frame.left;
-            inputWindow.frameTop = frame.top;
-            inputWindow.frameRight = frame.right;
-            inputWindow.frameBottom = frame.bottom;
+            inputWindowHandle.frameLeft = frame.left;
+            inputWindowHandle.frameTop = frame.top;
+            inputWindowHandle.frameRight = frame.right;
+            inputWindowHandle.frameBottom = frame.bottom;
 
             if (child.mGlobalScale != 1) {
                 // If we are scaling the window, input coordinates need
                 // to be inversely scaled to map from what is on screen
                 // to what is actually being touched in the UI.
-                inputWindow.scaleFactor = 1.0f/child.mGlobalScale;
+                inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
             } else {
-                inputWindow.scaleFactor = 1;
+                inputWindowHandle.scaleFactor = 1;
             }
 
-            child.getTouchableRegion(inputWindow.touchableRegion);
+            child.getTouchableRegion(inputWindowHandle.touchableRegion);
+
+            addInputWindowHandleLw(inputWindowHandle);
         }
 
         // Send windows to native code.
-        mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
-        
+        mService.mInputManager.setInputWindows(mInputWindowHandles);
+
         // Clear the list in preparation for the next round.
-        // Also avoids keeping InputChannel objects referenced unnecessarily.
-        mTempInputWindows.clear();
-        
+        clearInputWindowHandlesLw();
+
         if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
     }
 
@@ -329,14 +321,11 @@
         if (newApp == null) {
             mService.mInputManager.setFocusedApplication(null);
         } else {
-            mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
-            mTempInputApplication.name = newApp.toString();
-            mTempInputApplication.dispatchingTimeoutNanos =
-                    newApp.inputDispatchingTimeoutNanos;
+            final InputApplicationHandle handle = newApp.mInputApplicationHandle;
+            handle.name = newApp.toString();
+            handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos;
 
-            mService.mInputManager.setFocusedApplication(mTempInputApplication);
-
-            mTempInputApplication.recycle();
+            mService.mInputManager.setFocusedApplication(handle);
         }
     }
     
@@ -398,4 +387,4 @@
     private void updateInputDispatchModeLw() {
         mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
     }
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java
deleted file mode 100644
index 655d734..0000000
--- a/services/java/com/android/server/wm/InputWindow.java
+++ /dev/null
@@ -1,85 +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 com.android.server.wm;
-
-import android.graphics.Region;
-import android.view.InputChannel;
-
-/**
- * Describes input-related window properties for use by the input dispatcher.
- * @hide
- */
-public final class InputWindow {
-    // The window handle.
-    public InputWindowHandle inputWindowHandle;
-
-    // The input channel associated with the window.
-    public InputChannel inputChannel;
-
-    // The window name.
-    public String name;
-
-    // Window layout params attributes.  (WindowManager.LayoutParams)
-    public int layoutParamsFlags;
-    public int layoutParamsType;
-
-    // Dispatching timeout.
-    public long dispatchingTimeoutNanos;
-
-    // Window frame.
-    public int frameLeft;
-    public int frameTop;
-    public int frameRight;
-    public int frameBottom;
-
-    // Global scaling factor applied to touch events when they are dispatched
-    // to the window
-    public float scaleFactor;
-
-    // Window touchable region.
-    public final Region touchableRegion = new Region();
-
-    // Window is visible.
-    public boolean visible;
-
-    // Window can receive keys.
-    public boolean canReceiveKeys;
-
-    // Window has focus.
-    public boolean hasFocus;
-
-    // Window has wallpaper.  (window is the current wallpaper target)
-    public boolean hasWallpaper;
-
-    // Input event dispatching is paused.
-    public boolean paused;
-
-    // Window layer.
-    public int layer;
-
-    // Id of process and user that owns the window.
-    public int ownerPid;
-    public int ownerUid;
-
-    // Window input features.
-    public int inputFeatures;
-
-    public void recycle() {
-        inputWindowHandle = null;
-        inputChannel = null;
-    }
-}
diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/wm/InputWindowHandle.java
index cc508c6..abf68d9 100644
--- a/services/java/com/android/server/wm/InputWindowHandle.java
+++ b/services/java/com/android/server/wm/InputWindowHandle.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import android.graphics.Region;
+import android.view.InputChannel;
 import android.view.WindowManagerPolicy;
 
 /**
@@ -35,6 +37,57 @@
     // The window manager's window state.
     public final WindowManagerPolicy.WindowState windowState;
 
+    // The input channel associated with the window.
+    public InputChannel inputChannel;
+
+    // The window name.
+    public String name;
+
+    // Window layout params attributes.  (WindowManager.LayoutParams)
+    public int layoutParamsFlags;
+    public int layoutParamsType;
+
+    // Dispatching timeout.
+    public long dispatchingTimeoutNanos;
+
+    // Window frame.
+    public int frameLeft;
+    public int frameTop;
+    public int frameRight;
+    public int frameBottom;
+
+    // Global scaling factor applied to touch events when they are dispatched
+    // to the window
+    public float scaleFactor;
+
+    // Window touchable region.
+    public final Region touchableRegion = new Region();
+
+    // Window is visible.
+    public boolean visible;
+
+    // Window can receive keys.
+    public boolean canReceiveKeys;
+
+    // Window has focus.
+    public boolean hasFocus;
+
+    // Window has wallpaper.  (window is the current wallpaper target)
+    public boolean hasWallpaper;
+
+    // Input event dispatching is paused.
+    public boolean paused;
+
+    // Window layer.
+    public int layer;
+
+    // Id of process and user that owns the window.
+    public int ownerPid;
+    public int ownerUid;
+
+    // Window input features.
+    public int inputFeatures;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
diff --git a/services/java/com/android/server/wm/InputWindowList.java b/services/java/com/android/server/wm/InputWindowList.java
deleted file mode 100644
index 6077337..0000000
--- a/services/java/com/android/server/wm/InputWindowList.java
+++ /dev/null
@@ -1,89 +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 com.android.server.wm;
-
-
-/**
- * A specialized list of window information objects backed by an array.
- * 
- * This class is part of an InputManager optimization to avoid allocating objects and arrays
- * unnecessarily.  Internally, it keeps an array full of demand-allocated objects that it
- * recycles each time the list is cleared.  The used portion of the array is padded with a null.
- * 
- * The contents of the list are intended to be Z-ordered from top to bottom.
- * 
- * @hide
- */
-public final class InputWindowList {
-    private InputWindow[] mArray;
-    private int mCount;
-    
-    /**
-     * Creates an empty list.
-     */
-    public InputWindowList() {
-        mArray = new InputWindow[8];
-    }
-    
-    /**
-     * Clears the list.
-     */
-    public void clear() {
-        if (mCount == 0) {
-            return;
-        }
-        
-        int count = mCount;
-        mCount = 0;
-        mArray[count] = mArray[0];
-        while (count > 0) {
-            count -= 1;
-            mArray[count].recycle();
-        }
-        mArray[0] = null;
-    }
-    
-    /**
-     * Adds an uninitialized input window object to the list and returns it.
-     */
-    public InputWindow add() {
-        if (mCount + 1 == mArray.length) {
-            InputWindow[] oldArray = mArray;
-            mArray = new InputWindow[oldArray.length * 2];
-            System.arraycopy(oldArray, 0, mArray, 0, mCount);
-        }
-        
-        // Grab object from tail (after used section) if available.
-        InputWindow item = mArray[mCount + 1];
-        if (item == null) {
-            item = new InputWindow();
-        }
-        
-        mArray[mCount] = item;
-        mCount += 1;
-        mArray[mCount] = null;
-        return item;
-    }
-    
-    /**
-     * Gets the input window objects as a null-terminated array.
-     * @return The input window array.
-     */
-    public InputWindow[] toNullTerminatedArray() {
-        return mArray;
-    }
-}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 8470918..16af151 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -25,9 +25,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-import android.util.DisplayMetrics;
 import android.util.Slog;
-import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.animation.Animation;
@@ -41,7 +39,6 @@
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
     final Context mContext;
-    final Display mDisplay;
     Surface mSurface;
     BlackFrame mBlackFrame;
     int mWidth, mHeight;
@@ -58,18 +55,14 @@
     final Transformation mEnterTransformation = new Transformation();
     boolean mStarted;
 
-    final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
     final Matrix mSnapshotInitialMatrix = new Matrix();
     final Matrix mSnapshotFinalMatrix = new Matrix();
     final Matrix mTmpMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
 
-    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
-            boolean inTransaction) {
+    public ScreenRotationAnimation(Context context, SurfaceSession session,
+            boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
         mContext = context;
-        mDisplay = display;
-
-        display.getRealMetrics(mDisplayMetrics);
 
         Bitmap screenshot = Surface.screenshot(0, 0);
 
@@ -83,9 +76,9 @@
         mWidth = screenshot.getWidth();
         mHeight = screenshot.getHeight();
 
-        mOriginalRotation = display.getRotation();
-        mOriginalWidth = mDisplayMetrics.widthPixels;
-        mOriginalHeight = mDisplayMetrics.heightPixels;
+        mOriginalRotation = originalRotation;
+        mOriginalWidth = originalWidth;
+        mOriginalHeight = originalHeight;
 
         if (!inTransaction) {
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
@@ -106,7 +99,7 @@
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
                             "  FREEZE " + mSurface + ": CREATE");
 
-            setRotation(display.getRotation());
+            setRotation(originalRotation);
 
             if (mSurface != null) {
                 Rect dirty = new Rect(0, 0, mWidth, mHeight);
@@ -212,7 +205,7 @@
      * Returns true if animating.
      */
     public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
-            float animationScale) {
+            float animationScale, int finalWidth, int finalHeight) {
         if (mSurface == null) {
             // Can't do animation.
             return false;
@@ -248,16 +241,12 @@
                 break;
         }
 
-        mDisplay.getRealMetrics(mDisplayMetrics);
-
         // Initialize the animations.  This is a hack, redefining what "parent"
         // means to allow supplying the last and next size.  In this definition
         // "%p" is the original (let's call it "previous") size, and "%" is the
         // screen's current/new size.
-        mEnterAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
-                mOriginalWidth, mOriginalHeight);
-        mExitAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
-                mOriginalWidth, mOriginalHeight);
+        mEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+        mExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
         mStarted = false;
 
         mExitAnimation.restrictDuration(maxAnimationDuration);
@@ -270,10 +259,8 @@
         Surface.openTransaction();
 
         try {
-            final int w = mDisplayMetrics.widthPixels;
-            final int h = mDisplayMetrics.heightPixels;
-            Rect outer = new Rect(-w, -h, w*2, h*2);
-            Rect inner = new Rect(0, 0, w, h);
+            Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2);
+            Rect inner = new Rect(0, 0, finalWidth, finalHeight);
             mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
         } catch (Surface.OutOfResourcesException e) {
             Slog.w(TAG, "Unable to allocate black surface", e);
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 71b5952..768d2db 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -38,9 +38,6 @@
     final int mThickness = 20;
 
     public StrictModeFlash(Display display, SurfaceSession session) {
-        final DisplayMetrics dm = new DisplayMetrics();
-        display.getRealMetrics(dm);
-
         try {
             mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
         } catch (Surface.OutOfResourcesException e) {
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 375abe5..5497eb4 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -50,10 +50,7 @@
     int mLastDH;
     boolean mDrawNeeded;
 
-    Watermark(Display display, SurfaceSession session, String[] tokens) {
-        final DisplayMetrics dm = new DisplayMetrics();
-        display.getRealMetrics(dm);
-
+    Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) {
         if (false) {
             Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
             for (int i=0; i<tokens.length; i++) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index be21ac0..f8059f5 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -465,6 +465,7 @@
     Display mDisplay;
 
     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
     final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
     final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
 
@@ -5642,15 +5643,14 @@
         }
         config.orientation = orientation;
 
-        DisplayMetrics dm = mDisplayMetrics;
-        mDisplay.getRealMetrics(dm);
+        // Update real display metrics.
+        mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight);
 
-        // Override display width and height with what we are computing,
-        // to be sure they remain consistent.
-        dm.widthPixels = dm.noncompatWidthPixels = mAppDisplayWidth
-                = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
-        dm.heightPixels = dm.noncompatHeightPixels = mAppDisplayHeight
-                = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+        // Update application display metrics.
+        final DisplayMetrics dm = mDisplayMetrics;
+        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
+        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+        mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);
 
         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
                 mCompatDisplayMetrics);
@@ -6086,8 +6086,8 @@
             }
             WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
             mDisplay = wm.getDefaultDisplay();
-            mInitialDisplayWidth = mDisplay.getRealWidth();
-            mInitialDisplayHeight = mDisplay.getRealHeight();
+            mInitialDisplayWidth = mDisplay.getRawWidth();
+            mInitialDisplayHeight = mDisplay.getRawHeight();
             int rot = mDisplay.getRotation();
             if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
                 // If the screen is currently rotated, we need to swap the
@@ -6098,7 +6098,9 @@
             }
             mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
             mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
-            mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight());
+            mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
+                    mDisplay.getRawWidth(), mDisplay.getRawHeight(),
+                    mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
             mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight);
         }
 
@@ -6602,6 +6604,13 @@
         }
     }
 
+    public void getRealDisplaySize(Point size) {
+        synchronized(mWindowMap) {
+            size.x = mCurDisplayWidth;
+            size.y = mCurDisplayHeight;
+        }
+    }
+
     public int getMaximumSizeDimension() {
         synchronized(mWindowMap) {
             // Do this based on the raw screen size, until we are smarter.
@@ -8687,7 +8696,8 @@
             }
             if (mScreenRotationAnimation == null) {
                 mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                        mDisplay, mFxSession, inTransaction);
+                        mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+                        mDisplay.getRotation());
             }
             if (!mScreenRotationAnimation.hasScreenshot()) {
                 Surface.freezeDisplay(0);
@@ -8717,7 +8727,7 @@
         if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
                 && mScreenRotationAnimation.hasScreenshot()) {
             if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                    mTransitionAnimationScale)) {
+                    mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
                 requestAnimationLocked(0);
             } else {
                 mScreenRotationAnimation = null;
@@ -8797,7 +8807,7 @@
             if (line != null) {
                 String[] toks = line.split("%");
                 if (toks != null && toks.length > 0) {
-                    mWatermark = new Watermark(mDisplay, mFxSession, toks);
+                    mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
                 }
             }
         } catch (FileNotFoundException e) {
@@ -9063,8 +9073,6 @@
                         pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
                         pw.print(" app=");
                         pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
-                        pw.print(" real="); pw.print(mDisplay.getRealWidth());
-                        pw.print("x"); pw.print(mDisplay.getRealHeight());
                         pw.print(" raw="); pw.print(mDisplay.getRawWidth());
                         pw.print("x"); pw.println(mDisplay.getRawHeight());
             } else {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index b370ec9..cacb3e7 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -272,7 +272,7 @@
     float mSurfaceAlpha;
     
     // Input channel and input window handle used by the input dispatcher.
-    InputWindowHandle mInputWindowHandle;
+    final InputWindowHandle mInputWindowHandle;
     InputChannel mInputChannel;
     
     // Used to improve performance of toString()
@@ -306,6 +306,7 @@
             mIsFloatingLayer = false;
             mBaseLayer = 0;
             mSubLayer = 0;
+            mInputWindowHandle = null;
             return;
         }
         mDeathRecipient = deathRecipient;
@@ -496,8 +497,8 @@
         }
 
         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
-            mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getRealWidth(),
-                    mService.mDisplay.getRealHeight(), false);
+            mService.updateWallpaperOffsetLocked(this,
+                    mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
         }
 
         if (WindowManagerService.localLOGV) {
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index e1c7305..6fa5dfa 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,10 +4,8 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
-    com_android_server_InputApplication.cpp \
     com_android_server_InputApplicationHandle.cpp \
     com_android_server_InputManager.cpp \
-    com_android_server_InputWindow.cpp \
     com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index c9a702a..e80dd04 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -32,17 +32,13 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
-
-#ifdef HAVE_ANDROID_OS
 #include <linux/ioctl.h>
 #include <linux/android_alarm.h>
-#endif
 
 namespace android {
 
 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
 {
-#ifdef HAVE_ANDROID_OS
     struct timezone tz;
 
     tz.tz_minuteswest = minswest;
@@ -57,30 +53,20 @@
     }
 
     return 0;
-#else
-    return -ENOSYS;
-#endif
 }
 
 static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
 {
-#ifdef HAVE_ANDROID_OS
     return open("/dev/alarm", O_RDWR);
-#else
-	return -1;
-#endif
 }
 
 static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
 {
-#ifdef HAVE_ANDROID_OS
 	close(fd);
-#endif
 }
 
 static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
 {
-#ifdef HAVE_ANDROID_OS
     struct timespec ts;
     ts.tv_sec = seconds;
     ts.tv_nsec = nanoseconds;
@@ -90,12 +76,10 @@
 	{
         LOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
     }
-#endif
 }
 
 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
 {
-#ifdef HAVE_ANDROID_OS
 	int result = 0;
 
 	do
@@ -110,7 +94,6 @@
     }
 
     return result;
-#endif
 }
 
 static JNINativeMethod sMethods[] = {
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index 98d0d92..b9f2c1f 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -32,10 +32,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <dirent.h>
-
-#ifdef HAVE_ANDROID_OS
 #include <linux/ioctl.h>
-#endif
 
 namespace android {
 
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
deleted file mode 100644
index 1f80242..0000000
--- a/services/jni/com_android_server_InputApplication.cpp
+++ /dev/null
@@ -1,93 +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.
- */
-
-#define LOG_TAG "InputApplication"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "com_android_server_InputApplication.h"
-#include "com_android_server_InputApplicationHandle.h"
-
-namespace android {
-
-static struct {
-    jfieldID inputApplicationHandle;
-    jfieldID name;
-    jfieldID dispatchingTimeoutNanos;
-} gInputApplicationClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputApplication_toNative(
-        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
-    jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
-            gInputApplicationClassInfo.inputApplicationHandle);
-    if (inputApplicationHandleObj) {
-        outInputApplication->inputApplicationHandle =
-                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
-        env->DeleteLocalRef(inputApplicationHandleObj);
-    } else {
-        outInputApplication->inputApplicationHandle = NULL;
-    }
-
-    jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
-            gInputApplicationClassInfo.name));
-    if (nameObj) {
-        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        outInputApplication->name.setTo(nameStr);
-        env->ReleaseStringUTFChars(nameObj, nameStr);
-        env->DeleteLocalRef(nameObj);
-    } else {
-        LOGE("InputApplication.name should not be null.");
-        outInputApplication->name.setTo("unknown");
-    }
-
-    outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
-            gInputApplicationClassInfo.dispatchingTimeoutNanos);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputApplication(JNIEnv* env) {
-    jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputApplication");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
-            clazz,
-            "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.name, clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            clazz,
-            "dispatchingTimeoutNanos", "J");
-    return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
deleted file mode 100644
index 85fb891..0000000
--- a/services/jni/com_android_server_InputApplication.h
+++ /dev/null
@@ -1,32 +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.
- */
-
-#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
-#define _ANDROID_SERVER_INPUT_APPLICATION_H
-
-#include <input/InputApplication.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputApplication_toNative(
-        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
index 9516964..7de67d9 100644
--- a/services/jni/com_android_server_InputApplicationHandle.cpp
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -27,6 +27,8 @@
 
 static struct {
     jfieldID ptr;
+    jfieldID name;
+    jfieldID dispatchingTimeoutNanos;
 } gInputApplicationHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -47,6 +49,31 @@
     return env->NewLocalRef(mObjWeak);
 }
 
+bool NativeInputApplicationHandle::update() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject obj = env->NewLocalRef(mObjWeak);
+    if (!obj) {
+        return false;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(obj,
+            gInputApplicationHandleClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        name.setTo("<null>");
+    }
+
+    dispatchingTimeout = env->GetLongField(obj,
+            gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
+
+    env->DeleteLocalRef(obj);
+    return true;
+}
+
 
 // --- Global functions ---
 
@@ -113,6 +140,13 @@
     GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
             "ptr", "I");
 
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos,
+            clazz,
+            "dispatchingTimeoutNanos", "J");
+
     return 0;
 }
 
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
index 9d18721..04cd9d6 100644
--- a/services/jni/com_android_server_InputApplicationHandle.h
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -31,6 +31,8 @@
 
     jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
 
+    virtual bool update();
+
 private:
     jweak mObjWeak;
 };
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 14a4109..3414eea 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -46,9 +46,7 @@
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
-#include "com_android_server_InputApplication.h"
 #include "com_android_server_InputApplicationHandle.h"
-#include "com_android_server_InputWindow.h"
 #include "com_android_server_InputWindowHandle.h"
 
 namespace android {
@@ -168,22 +166,23 @@
 
     void dump(String8& dump);
 
-    void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
+    void setDisplaySize(int32_t displayId, int32_t width, int32_t height,
+            int32_t externalWidth, int32_t externalHeight);
     void setDisplayOrientation(int32_t displayId, int32_t orientation);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
-    void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
-    void setFocusedApplication(JNIEnv* env, jobject applicationObj);
+    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+    void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
     void setInputDispatchMode(bool enabled, bool frozen);
     void setSystemUiVisibility(int32_t visibility);
     void setPointerSpeed(int32_t speed);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
-    virtual bool getDisplayInfo(int32_t displayId,
+    virtual bool getDisplayInfo(int32_t displayId, bool external,
             int32_t* width, int32_t* height, int32_t* orientation);
     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
@@ -223,7 +222,8 @@
     Mutex mLock;
     struct Locked {
         // Display size information.
-        int32_t displayWidth, displayHeight; // -1 when initialized
+        int32_t displayWidth, displayHeight; // -1 when not initialized
+        int32_t displayExternalWidth, displayExternalHeight; // -1 when not initialized
         int32_t displayOrientation;
 
         // System UI visibility.
@@ -271,6 +271,8 @@
         AutoMutex _l(mLock);
         mLocked.displayWidth = -1;
         mLocked.displayHeight = -1;
+        mLocked.displayExternalWidth = -1;
+        mLocked.displayExternalHeight = -1;
         mLocked.displayOrientation = ROTATION_0;
 
         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
@@ -307,22 +309,24 @@
     return false;
 }
 
-void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
+void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height,
+        int32_t externalWidth, int32_t externalHeight) {
     if (displayId == 0) {
         { // acquire lock
             AutoMutex _l(mLock);
 
-            if (mLocked.displayWidth == width && mLocked.displayHeight == height) {
-                return;
+            if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+                mLocked.displayWidth = width;
+                mLocked.displayHeight = height;
+
+                sp<PointerController> controller = mLocked.pointerController.promote();
+                if (controller != NULL) {
+                    controller->setDisplaySize(width, height);
+                }
             }
 
-            mLocked.displayWidth = width;
-            mLocked.displayHeight = height;
-
-            sp<PointerController> controller = mLocked.pointerController.promote();
-            if (controller != NULL) {
-                controller->setDisplaySize(width, height);
-            }
+            mLocked.displayExternalWidth = externalWidth;
+            mLocked.displayExternalHeight = externalHeight;
         } // release lock
     }
 }
@@ -354,7 +358,7 @@
     return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
 }
 
-bool NativeInputManager::getDisplayInfo(int32_t displayId,
+bool NativeInputManager::getDisplayInfo(int32_t displayId, bool external,
         int32_t* width, int32_t* height, int32_t* orientation) {
     bool result = false;
     if (displayId == 0) {
@@ -362,10 +366,10 @@
 
         if (mLocked.displayWidth > 0 && mLocked.displayHeight > 0) {
             if (width) {
-                *width = mLocked.displayWidth;
+                *width = external ? mLocked.displayExternalWidth : mLocked.displayWidth;
             }
             if (height) {
-                *height = mLocked.displayHeight;
+                *height = external ? mLocked.displayExternalHeight : mLocked.displayHeight;
             }
             if (orientation) {
                 *orientation = mLocked.displayOrientation;
@@ -582,31 +586,38 @@
     return isScreenOn();
 }
 
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
-    Vector<InputWindow> windows;
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+    Vector<sp<InputWindowHandle> > windowHandles;
 
-    bool newPointerGesturesEnabled = true;
-    jsize length = env->GetArrayLength(windowObjArray);
-    for (jsize i = 0; i < length; i++) {
-        jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
-        if (! windowObj) {
-            break; // found null element indicating end of used portion of the array
-        }
-
-        windows.push();
-        InputWindow& window = windows.editTop();
-        android_server_InputWindow_toNative(env, windowObj, &window);
-        if (window.inputChannel == NULL) {
-            windows.pop();
-        } else if (window.hasFocus) {
-            if (window.inputFeatures & InputWindow::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES) {
-                newPointerGesturesEnabled = false;
+    if (windowHandleObjArray) {
+        jsize length = env->GetArrayLength(windowHandleObjArray);
+        for (jsize i = 0; i < length; i++) {
+            jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
+            if (! windowHandleObj) {
+                break; // found null element indicating end of used portion of the array
             }
+
+            sp<InputWindowHandle> windowHandle =
+                    android_server_InputWindowHandle_getHandle(env, windowHandleObj);
+            if (windowHandle != NULL) {
+                windowHandles.push(windowHandle);
+            }
+            env->DeleteLocalRef(windowHandleObj);
         }
-        env->DeleteLocalRef(windowObj);
     }
 
-    mInputManager->getDispatcher()->setInputWindows(windows);
+    mInputManager->getDispatcher()->setInputWindows(windowHandles);
+
+    // Do this after the dispatcher has updated the window handle state.
+    bool newPointerGesturesEnabled = true;
+    size_t numWindows = windowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
+        if (windowHandle->hasFocus && (windowHandle->inputFeatures
+                & InputWindowHandle::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
+            newPointerGesturesEnabled = false;
+        }
+    }
 
     uint32_t changes = 0;
     { // acquire lock
@@ -623,16 +634,10 @@
     }
 }
 
-void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
-    if (applicationObj) {
-        InputApplication application;
-        android_server_InputApplication_toNative(env, applicationObj, &application);
-        if (application.inputApplicationHandle != NULL) {
-            mInputManager->getDispatcher()->setFocusedApplication(&application);
-            return;
-        }
-    }
-    mInputManager->getDispatcher()->setFocusedApplication(NULL);
+void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) {
+    sp<InputApplicationHandle> applicationHandle =
+            android_server_InputApplicationHandle_getHandle(env, applicationHandleObj);
+    mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
 }
 
 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -953,7 +958,7 @@
 }
 
 static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
-        jint displayId, jint width, jint height) {
+        jint displayId, jint width, jint height, jint externalWidth, jint externalHeight) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
@@ -962,7 +967,7 @@
     // to be passed in like this, not sure which is better but leaving it like this
     // keeps the window manager in direct control of when display transitions propagate down
     // to the input dispatcher
-    gNativeInputManager->setDisplaySize(displayId, width, height);
+    gNativeInputManager->setDisplaySize(displayId, width, height, externalWidth, externalHeight);
 }
 
 static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
@@ -1137,21 +1142,21 @@
 }
 
 static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
-        jobjectArray windowObjArray) {
+        jobjectArray windowHandleObjArray) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
 
-    gNativeInputManager->setInputWindows(env, windowObjArray);
+    gNativeInputManager->setInputWindows(env, windowHandleObjArray);
 }
 
 static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
-        jobject applicationObj) {
+        jobject applicationHandleObj) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
 
-    gNativeInputManager->setFocusedApplication(env, applicationObj);
+    gNativeInputManager->setFocusedApplication(env, applicationHandleObj);
 }
 
 static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
@@ -1292,7 +1297,7 @@
             (void*) android_server_InputManager_nativeInit },
     { "nativeStart", "()V",
             (void*) android_server_InputManager_nativeStart },
-    { "nativeSetDisplaySize", "(III)V",
+    { "nativeSetDisplaySize", "(IIIII)V",
             (void*) android_server_InputManager_nativeSetDisplaySize },
     { "nativeSetDisplayOrientation", "(II)V",
             (void*) android_server_InputManager_nativeSetDisplayOrientation },
@@ -1313,9 +1318,9 @@
             (void*) android_server_InputManager_nativeSetInputFilterEnabled },
     { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIIII)I",
             (void*) android_server_InputManager_nativeInjectInputEvent },
-    { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindow;)V",
+    { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindowHandle;)V",
             (void*) android_server_InputManager_nativeSetInputWindows },
-    { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplication;)V",
+    { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplicationHandle;)V",
             (void*) android_server_InputManager_nativeSetFocusedApplication },
     { "nativeSetInputDispatchMode", "(ZZ)V",
             (void*) android_server_InputManager_nativeSetInputDispatchMode },
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
deleted file mode 100644
index 0426f63..0000000
--- a/services/jni/com_android_server_InputWindow.cpp
+++ /dev/null
@@ -1,218 +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.
- */
-
-#define LOG_TAG "InputWindow"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <android_view_InputChannel.h>
-#include <android/graphics/Region.h>
-#include "com_android_server_InputWindow.h"
-#include "com_android_server_InputWindowHandle.h"
-
-namespace android {
-
-static struct {
-    jfieldID inputWindowHandle;
-    jfieldID inputChannel;
-    jfieldID name;
-    jfieldID layoutParamsFlags;
-    jfieldID layoutParamsType;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID frameLeft;
-    jfieldID frameTop;
-    jfieldID frameRight;
-    jfieldID frameBottom;
-    jfieldID scaleFactor;
-    jfieldID touchableRegion;
-    jfieldID visible;
-    jfieldID canReceiveKeys;
-    jfieldID hasFocus;
-    jfieldID hasWallpaper;
-    jfieldID paused;
-    jfieldID layer;
-    jfieldID ownerPid;
-    jfieldID ownerUid;
-    jfieldID inputFeatures;
-} gInputWindowClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
-    jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.inputWindowHandle);
-    if (inputWindowHandleObj) {
-        outInputWindow->inputWindowHandle =
-                android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
-        env->DeleteLocalRef(inputWindowHandleObj);
-    } else {
-        outInputWindow->inputWindowHandle = NULL;
-    }
-
-    jobject inputChannelObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.inputChannel);
-    if (inputChannelObj) {
-        outInputWindow->inputChannel =
-                android_view_InputChannel_getInputChannel(env, inputChannelObj);
-        env->DeleteLocalRef(inputChannelObj);
-    } else {
-        outInputWindow->inputChannel = NULL;
-    }
-
-    jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.name));
-    if (nameObj) {
-        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        outInputWindow->name.setTo(nameStr);
-        env->ReleaseStringUTFChars(nameObj, nameStr);
-        env->DeleteLocalRef(nameObj);
-    } else {
-        LOGE("InputWindow.name should not be null.");
-        outInputWindow->name.setTo("unknown");
-    }
-
-    outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layoutParamsFlags);
-    outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layoutParamsType);
-    outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
-            gInputWindowClassInfo.dispatchingTimeoutNanos);
-    outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameLeft);
-    outInputWindow->frameTop = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameTop);
-    outInputWindow->frameRight = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameRight);
-    outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameBottom);
-    outInputWindow->scaleFactor = env->GetFloatField(inputWindowObj,
-            gInputWindowClassInfo.scaleFactor);
-
-    jobject regionObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.touchableRegion);
-    if (regionObj) {
-        SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
-        outInputWindow->touchableRegion.set(*region);
-        env->DeleteLocalRef(regionObj);
-    } else {
-        outInputWindow->touchableRegion.setEmpty();
-    }
-
-    outInputWindow->visible = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.visible);
-    outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.canReceiveKeys);
-    outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.hasFocus);
-    outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.hasWallpaper);
-    outInputWindow->paused = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.paused);
-    outInputWindow->layer = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layer);
-    outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.ownerPid);
-    outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.ownerUid);
-    outInputWindow->inputFeatures = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.inputFeatures);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputWindow(JNIEnv* env) {
-    jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputWindow");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, clazz,
-            "inputWindowHandle", "Lcom/android/server/wm/InputWindowHandle;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, clazz,
-            "inputChannel", "Landroid/view/InputChannel;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.name, clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, clazz,
-            "layoutParamsFlags", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, clazz,
-            "layoutParamsType", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, clazz,
-            "frameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, clazz,
-            "frameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, clazz,
-            "frameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, clazz,
-            "frameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.scaleFactor, clazz,
-            "scaleFactor", "F");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, clazz,
-            "touchableRegion", "Landroid/graphics/Region;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visible, clazz,
-            "visible", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, clazz,
-            "canReceiveKeys", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, clazz,
-            "hasFocus", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, clazz,
-            "hasWallpaper", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.paused, clazz,
-            "paused", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layer, clazz,
-            "layer", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, clazz,
-            "ownerPid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz,
-            "ownerUid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputFeatures, clazz,
-            "inputFeatures", "I");
-    return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
index aaf679c..09be881 100644
--- a/services/jni/com_android_server_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -21,6 +21,9 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/threads.h>
 
+#include <android_view_InputChannel.h>
+#include <android/graphics/Region.h>
+
 #include "com_android_server_InputWindowHandle.h"
 #include "com_android_server_InputApplicationHandle.h"
 
@@ -29,6 +32,26 @@
 static struct {
     jfieldID ptr;
     jfieldID inputApplicationHandle;
+    jfieldID inputChannel;
+    jfieldID name;
+    jfieldID layoutParamsFlags;
+    jfieldID layoutParamsType;
+    jfieldID dispatchingTimeoutNanos;
+    jfieldID frameLeft;
+    jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID scaleFactor;
+    jfieldID touchableRegion;
+    jfieldID visible;
+    jfieldID canReceiveKeys;
+    jfieldID hasFocus;
+    jfieldID hasWallpaper;
+    jfieldID paused;
+    jfieldID layer;
+    jfieldID ownerPid;
+    jfieldID ownerUid;
+    jfieldID inputFeatures;
 } gInputWindowHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -51,6 +74,83 @@
     return env->NewLocalRef(mObjWeak);
 }
 
+bool NativeInputWindowHandle::update() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject obj = env->NewLocalRef(mObjWeak);
+    if (!obj) {
+        return false;
+    }
+
+    jobject inputChannelObj = env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.inputChannel);
+    if (inputChannelObj) {
+        inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        env->DeleteLocalRef(inputChannelObj);
+    } else {
+        inputChannel = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        name.setTo("<null>");
+    }
+
+    layoutParamsFlags = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layoutParamsFlags);
+    layoutParamsType = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layoutParamsType);
+    dispatchingTimeout = env->GetLongField(obj,
+            gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
+    frameLeft = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameLeft);
+    frameTop = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameTop);
+    frameRight = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameRight);
+    frameBottom = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameBottom);
+    scaleFactor = env->GetFloatField(obj,
+            gInputWindowHandleClassInfo.scaleFactor);
+
+    jobject regionObj = env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.touchableRegion);
+    if (regionObj) {
+        SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+        touchableRegion.set(*region);
+        env->DeleteLocalRef(regionObj);
+    } else {
+        touchableRegion.setEmpty();
+    }
+
+    visible = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.visible);
+    canReceiveKeys = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.canReceiveKeys);
+    hasFocus = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.hasFocus);
+    hasWallpaper = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.hasWallpaper);
+    paused = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.paused);
+    layer = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layer);
+    ownerPid = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.ownerPid);
+    ownerUid = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.ownerUid);
+    inputFeatures = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.inputFeatures);
+
+    env->DeleteLocalRef(obj);
+    return true;
+}
+
 
 // --- Global functions ---
 
@@ -127,6 +227,65 @@
             clazz,
             "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
 
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
+            "inputChannel", "Landroid/view/InputChannel;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz,
+            "layoutParamsFlags", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz,
+            "layoutParamsType", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz,
+            "dispatchingTimeoutNanos", "J");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz,
+            "frameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz,
+            "frameTop", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz,
+            "scaleFactor", "F");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
+            "touchableRegion", "Landroid/graphics/Region;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
+            "visible", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz,
+            "canReceiveKeys", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz,
+            "hasFocus", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
+            "hasWallpaper", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
+            "paused", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
+            "layer", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
+            "ownerPid", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz,
+            "ownerUid", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
+            "inputFeatures", "I");
     return 0;
 }
 
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
index 43f2a6b..913c3b1 100644
--- a/services/jni/com_android_server_InputWindowHandle.h
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -32,6 +32,8 @@
 
     jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
 
+    virtual bool update();
+
 private:
     jweak mObjWeak;
 };
diff --git a/services/jni/com_android_server_UsbDeviceManager.cpp b/services/jni/com_android_server_UsbDeviceManager.cpp
index 6954171..40f0dbd 100644
--- a/services/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/jni/com_android_server_UsbDeviceManager.cpp
@@ -99,11 +99,26 @@
         gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
 }
 
+static jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz)
+{
+    int fd = open(DRIVER_NAME, O_RDWR);
+    if (fd < 0) {
+        LOGE("could not open %s", DRIVER_NAME);
+        return false;
+    }
+    int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED);
+    close(fd);
+    return (result == 1);
+}
+
+
 static JNINativeMethod method_table[] = {
     { "nativeGetAccessoryStrings",  "()[Ljava/lang/String;",
                                     (void*)android_server_UsbDeviceManager_getAccessoryStrings },
     { "nativeOpenAccessory",        "()Landroid/os/ParcelFileDescriptor;",
                                     (void*)android_server_UsbDeviceManager_openAccessory },
+    { "nativeIsStartRequested",     "()Z",
+                                    (void*)android_server_UsbDeviceManager_isStartRequested },
 };
 
 int register_android_server_UsbDeviceManager(JNIEnv *env)
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index 5f920f1..d28a6b4 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -18,7 +18,6 @@
 
 #define LOG_TAG "VpnJni"
 #include <cutils/log.h>
-#include <cutils/properties.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -54,7 +53,7 @@
 #define SYSTEM_ERROR -1
 #define BAD_ARGUMENT -2
 
-static int create_interface(char *name, int *index, int mtu)
+static int create_interface(int mtu)
 {
     int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);
 
@@ -82,14 +81,6 @@
         goto error;
     }
 
-    // Get interface index.
-    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
-        LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno));
-        goto error;
-    }
-
-    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
-    *index = ifr4.ifr_ifindex;
     return tun;
 
 error:
@@ -97,12 +88,40 @@
     return SYSTEM_ERROR;
 }
 
-static int set_addresses(const char *name, int index, const char *addresses)
+static int get_interface_name(char *name, int tun)
 {
     ifreq ifr4;
+    if (ioctl(tun, TUNGETIFF, &ifr4)) {
+        LOGE("Cannot get interface name: %s", strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
+    return 0;
+}
+
+static int get_interface_index(const char *name)
+{
+    ifreq ifr4;
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
+        LOGE("Cannot get index of %s: %s", name, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return ifr4.ifr_ifindex;
+}
+
+static int set_addresses(const char *name, const char *addresses)
+{
+    int index = get_interface_index(name);
+    if (index < 0) {
+        return index;
+    }
+
+    ifreq ifr4;
     memset(&ifr4, 0, sizeof(ifr4));
     strncpy(ifr4.ifr_name, name, IFNAMSIZ);
     ifr4.ifr_addr.sa_family = AF_INET;
+    ifr4.ifr_netmask.sa_family = AF_INET;
 
     in6_ifreq ifr6;
     memset(&ifr6, 0, sizeof(ifr6));
@@ -146,7 +165,7 @@
             }
 
             in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
-            *as_in_addr(&ifr4.ifr_addr) = htonl(mask);
+            *as_in_addr(&ifr4.ifr_netmask) = htonl(mask);
             if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
@@ -168,8 +187,13 @@
     return count;
 }
 
-static int set_routes(const char *name, int index, const char *routes)
+static int set_routes(const char *name, const char *routes)
 {
+    int index = get_interface_index(name);
+    if (index < 0) {
+        return index;
+    }
+
     rtentry rt4;
     memset(&rt4, 0, sizeof(rt4));
     rt4.rt_dev = (char *)name;
@@ -253,17 +277,6 @@
     return count;
 }
 
-static int get_interface_name(char *name, int tun)
-{
-    ifreq ifr4;
-    if (ioctl(tun, TUNGETIFF, &ifr4)) {
-        LOGE("Cannot get interface name: %s", strerror(errno));
-        return SYSTEM_ERROR;
-    }
-    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
-    return 0;
-}
-
 static int reset_interface(const char *name)
 {
     ifreq ifr4;
@@ -309,53 +322,14 @@
     }
 }
 
-static jint configure(JNIEnv *env, jobject thiz,
-        jint mtu, jstring jAddresses, jstring jRoutes)
+static jint create(JNIEnv *env, jobject thiz, jint mtu)
 {
-    char name[IFNAMSIZ];
-    int index;
-    int tun = create_interface(name, &index, mtu);
+    int tun = create_interface(mtu);
     if (tun < 0) {
         throwException(env, tun, "Cannot create interface");
         return -1;
     }
-
-    const char *addresses = NULL;
-    const char *routes = NULL;
-    int count;
-
-    // At least one address must be set.
-    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
-    if (!addresses) {
-        jniThrowNullPointerException(env, "address");
-        goto error;
-    }
-    count = set_addresses(name, index, addresses);
-    env->ReleaseStringUTFChars(jAddresses, addresses);
-    if (count <= 0) {
-        throwException(env, count, "Cannot set address");
-        goto error;
-    }
-    LOGD("Configured %d address(es) on %s", count, name);
-
-    // On the contrary, routes are optional.
-    routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
-    if (routes) {
-        count = set_routes(name, index, routes);
-        env->ReleaseStringUTFChars(jRoutes, routes);
-        if (count < 0) {
-            throwException(env, count, "Cannot set route");
-            goto error;
-        }
-        LOGD("Configured %d route(s) on %s", count, name);
-    }
-
     return tun;
-
-error:
-    close(tun);
-    LOGD("%s is destroyed", name);
-    return -1;
 }
 
 static jstring getName(JNIEnv *env, jobject thiz, jint tun)
@@ -368,6 +342,72 @@
     return env->NewStringUTF(name);
 }
 
+static jint setAddresses(JNIEnv *env, jobject thiz, jstring jName,
+        jstring jAddresses)
+{
+    const char *name = NULL;
+    const char *addresses = NULL;
+    int count = -1;
+
+    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        goto error;
+    }
+    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
+    if (!addresses) {
+        jniThrowNullPointerException(env, "addresses");
+        goto error;
+    }
+    count = set_addresses(name, addresses);
+    if (count < 0) {
+        throwException(env, count, "Cannot set address");
+        count = -1;
+    }
+
+error:
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (addresses) {
+        env->ReleaseStringUTFChars(jAddresses, addresses);
+    }
+    return count;
+}
+
+static jint setRoutes(JNIEnv *env, jobject thiz, jstring jName,
+        jstring jRoutes)
+{
+    const char *name = NULL;
+    const char *routes = NULL;
+    int count = -1;
+
+    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        goto error;
+    }
+    routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
+    if (!routes) {
+        jniThrowNullPointerException(env, "routes");
+        goto error;
+    }
+    count = set_routes(name, routes);
+    if (count < 0) {
+        throwException(env, count, "Cannot set route");
+        count = -1;
+    }
+
+error:
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (routes) {
+        env->ReleaseStringUTFChars(jRoutes, routes);
+    }
+    return count;
+}
+
 static void reset(JNIEnv *env, jobject thiz, jstring jName)
 {
     const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
@@ -409,8 +449,10 @@
 //------------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"jniConfigure", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)configure},
+    {"jniCreate", "(I)I", (void *)create},
     {"jniGetName", "(I)Ljava/lang/String;", (void *)getName},
+    {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
+    {"jniSetRoutes", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setRoutes},
     {"jniReset", "(Ljava/lang/String;)V", (void *)reset},
     {"jniCheck", "(Ljava/lang/String;)I", (void *)check},
     {"jniProtect", "(ILjava/lang/String;)V", (void *)protect},
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 9dff48b..4178039 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -22,9 +22,7 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
-int register_android_server_InputApplication(JNIEnv* env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
-int register_android_server_InputWindow(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
@@ -51,9 +49,7 @@
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_PowerManagerService(env);
-    register_android_server_InputApplication(env);
     register_android_server_InputApplicationHandle(env);
-    register_android_server_InputWindow(env);
     register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
diff --git a/services/powermanager/Android.mk b/services/powermanager/Android.mk
new file mode 100644
index 0000000..d98b2daf
--- /dev/null
+++ b/services/powermanager/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	IPowerManager.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	libbinder
+
+LOCAL_MODULE:= libpowermanager
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
new file mode 100644
index 0000000..a0f19d4
--- /dev/null
+++ b/services/powermanager/IPowerManager.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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_TAG "IPowerManager"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <powermanager/IPowerManager.h>
+
+namespace android {
+
+// must be kept in sync with IPowerManager.aidl
+enum {
+    ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
+    RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 4,
+};
+
+class BpPowerManager : public BpInterface<IPowerManager>
+{
+public:
+    BpPowerManager(const sp<IBinder>& impl)
+        : BpInterface<IPowerManager>(impl)
+    {
+    }
+
+    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+
+        data.writeInt32(flags);
+        data.writeStrongBinder(lock);
+        data.writeString16(tag);
+        // no WorkSource passed
+        data.writeInt32(0);
+        return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply);
+    }
+
+    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeStrongBinder(lock);
+        data.writeInt32(flags);
+        return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 4ec0c8c..518a1bb7 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -28,23 +28,25 @@
       mEnabled(false), mGyroTime(0)
 {
     sensor_t const* list;
-    size_t count = mSensorDevice.getSensorList(&list);
-    for (size_t i=0 ; i<count ; i++) {
-        if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
-            mAcc = Sensor(list + i);
+    ssize_t count = mSensorDevice.getSensorList(&list);
+    if (count > 0) {
+        for (size_t i=0 ; i<size_t(count) ; i++) {
+            if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
+                mAcc = Sensor(list + i);
+            }
+            if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
+                mMag = Sensor(list + i);
+            }
+            if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
+                mGyro = Sensor(list + i);
+                // 200 Hz for gyro events is a good compromise between precision
+                // and power/cpu usage.
+                mGyroRate = 200;
+                mTargetDelayNs = 1000000000LL/mGyroRate;
+            }
         }
-        if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
-            mMag = Sensor(list + i);
-        }
-        if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
-            mGyro = Sensor(list + i);
-            // 200 Hz for gyro events is a good compromise between precision
-            // and power/cpu usage.
-            mGyroRate = 200;
-            mTargetDelayNs = 1000000000LL/mGyroRate;
-        }
+        mFusion.init();
     }
-    mFusion.init();
 }
 
 void SensorFusion::process(const sensors_event_t& event) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 64d214b..5b74fb8 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -70,73 +70,76 @@
     SensorDevice& dev(SensorDevice::getInstance());
 
     if (dev.initCheck() == NO_ERROR) {
-        ssize_t orientationIndex = -1;
-        bool hasGyro = false;
-        uint32_t virtualSensorsNeeds =
-                (1<<SENSOR_TYPE_GRAVITY) |
-                (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
-                (1<<SENSOR_TYPE_ROTATION_VECTOR);
         sensor_t const* list;
-        int count = dev.getSensorList(&list);
-        mLastEventSeen.setCapacity(count);
-        for (int i=0 ; i<count ; i++) {
-            registerSensor( new HardwareSensor(list[i]) );
-            switch (list[i].type) {
-                case SENSOR_TYPE_ORIENTATION:
-                    orientationIndex = i;
-                    break;
-                case SENSOR_TYPE_GYROSCOPE:
-                    hasGyro = true;
-                    break;
-                case SENSOR_TYPE_GRAVITY:
-                case SENSOR_TYPE_LINEAR_ACCELERATION:
-                case SENSOR_TYPE_ROTATION_VECTOR:
-                    virtualSensorsNeeds &= ~(1<<list[i].type);
-                    break;
+        ssize_t count = dev.getSensorList(&list);
+        if (count > 0) {
+            ssize_t orientationIndex = -1;
+            bool hasGyro = false;
+            uint32_t virtualSensorsNeeds =
+                    (1<<SENSOR_TYPE_GRAVITY) |
+                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
+                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
+
+            mLastEventSeen.setCapacity(count);
+            for (ssize_t i=0 ; i<count ; i++) {
+                registerSensor( new HardwareSensor(list[i]) );
+                switch (list[i].type) {
+                    case SENSOR_TYPE_ORIENTATION:
+                        orientationIndex = i;
+                        break;
+                    case SENSOR_TYPE_GYROSCOPE:
+                        hasGyro = true;
+                        break;
+                    case SENSOR_TYPE_GRAVITY:
+                    case SENSOR_TYPE_LINEAR_ACCELERATION:
+                    case SENSOR_TYPE_ROTATION_VECTOR:
+                        virtualSensorsNeeds &= ~(1<<list[i].type);
+                        break;
+                }
             }
-        }
 
-        // it's safe to instantiate the SensorFusion object here
-        // (it wants to be instantiated after h/w sensors have been
-        // registered)
-        const SensorFusion& fusion(SensorFusion::getInstance());
+            // it's safe to instantiate the SensorFusion object here
+            // (it wants to be instantiated after h/w sensors have been
+            // registered)
+            const SensorFusion& fusion(SensorFusion::getInstance());
 
-        if (hasGyro) {
-            // Always instantiate Android's virtual sensors. Since they are
-            // instantiated behind sensors from the HAL, they won't
-            // interfere with applications, unless they looks specifically
-            // for them (by name).
+            if (hasGyro) {
+                // Always instantiate Android's virtual sensors. Since they are
+                // instantiated behind sensors from the HAL, they won't
+                // interfere with applications, unless they looks specifically
+                // for them (by name).
 
-            registerVirtualSensor( new RotationVectorSensor() );
-            registerVirtualSensor( new GravitySensor(list, count) );
-            registerVirtualSensor( new LinearAccelerationSensor(list, count) );
+                registerVirtualSensor( new RotationVectorSensor() );
+                registerVirtualSensor( new GravitySensor(list, count) );
+                registerVirtualSensor( new LinearAccelerationSensor(list, count) );
 
-            // these are optional
-            registerVirtualSensor( new OrientationSensor() );
-            registerVirtualSensor( new CorrectedGyroSensor(list, count) );
+                // these are optional
+                registerVirtualSensor( new OrientationSensor() );
+                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
 
-            // virtual debugging sensors...
-            char value[PROPERTY_VALUE_MAX];
-            property_get("debug.sensors", value, "0");
-            if (atoi(value)) {
-                registerVirtualSensor( new GyroDriftSensor() );
+                // virtual debugging sensors...
+                char value[PROPERTY_VALUE_MAX];
+                property_get("debug.sensors", value, "0");
+                if (atoi(value)) {
+                    registerVirtualSensor( new GyroDriftSensor() );
+                }
             }
-        }
 
-        // build the sensor list returned to users
-        mUserSensorList = mSensorList;
-        if (hasGyro &&
-                (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
-            // if we have the fancy sensor fusion, and it's not provided by the
-            // HAL, use our own (fused) orientation sensor by removing the
-            // HAL supplied one form the user list.
-            if (orientationIndex >= 0) {
-                mUserSensorList.removeItemsAt(orientationIndex);
+            // build the sensor list returned to users
+            mUserSensorList = mSensorList;
+            if (hasGyro &&
+                    (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
+                // if we have the fancy sensor fusion, and it's not provided by the
+                // HAL, use our own (fused) orientation sensor by removing the
+                // HAL supplied one form the user list.
+                if (orientationIndex >= 0) {
+                    mUserSensorList.removeItemsAt(orientationIndex);
+                }
             }
-        }
 
-        run("SensorService", PRIORITY_URGENT_DISPLAY);
-        mInitCheck = NO_ERROR;
+            run("SensorService", PRIORITY_URGENT_DISPLAY);
+            mInitCheck = NO_ERROR;
+        }
     }
 }
 
@@ -583,12 +586,12 @@
     if (size == -EAGAIN) {
         // the destination doesn't accept events anymore, it's probably
         // full. For now, we just drop the events on the floor.
-        LOGW("dropping %d events on the floor", count);
+        //LOGW("dropping %d events on the floor", count);
         return size;
     }
 
-    LOGE_IF(size<0, "dropping %d events on the floor (%s)",
-            count, strerror(-size));
+    //LOGE_IF(size<0, "dropping %d events on the floor (%s)",
+    //        count, strerror(-size));
 
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f3b6c4d..7d6a14d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -44,10 +44,6 @@
 
 namespace android {
 
-template <typename T> inline T min(T a, T b) {
-    return a<b ? a : b;
-}
-
 // ---------------------------------------------------------------------------
 
 Layer::Layer(SurfaceFlinger* flinger,
@@ -56,14 +52,14 @@
         mTextureName(-1U),
         mQueuedFrames(0),
         mCurrentTransform(0),
+        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
         mCurrentOpacity(true),
         mFormat(PIXEL_FORMAT_NONE),
         mGLExtensions(GLExtensions::getInstance()),
         mOpaqueLayer(true),
         mNeedsDithering(false),
         mSecure(false),
-        mProtectedByApp(false),
-        mFixedSize(false)
+        mProtectedByApp(false)
 {
     mCurrentCrop.makeInvalid();
     glGenTextures(1, &mTextureName);
@@ -356,12 +352,13 @@
     if (sizeChanged) {
         // the size changed, we need to ask our client to request a new buffer
         LOGD_IF(DEBUG_RESIZE,
+                "doTransaction: "
                 "resize (layer=%p), requested (%dx%d), drawing (%d,%d), "
-                "fixedSize=%d",
+                "scalingMode=%d",
                 this,
                 int(temp.requested_w), int(temp.requested_h),
                 int(front.requested_w), int(front.requested_h),
-                isFixedSize());
+                mCurrentScalingMode);
 
         if (!isFixedSize()) {
             // we're being resized and there is a freeze display request,
@@ -400,14 +397,7 @@
 }
 
 bool Layer::isFixedSize() const {
-    Mutex::Autolock _l(mLock);
-    return mFixedSize;
-}
-
-void Layer::setFixedSize(bool fixedSize)
-{
-    Mutex::Autolock _l(mLock);
-    mFixedSize = fixedSize;
+    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
 }
 
 bool Layer::isCropped() const {
@@ -437,9 +427,14 @@
 
         const Rect crop(mSurfaceTexture->getCurrentCrop());
         const uint32_t transform(mSurfaceTexture->getCurrentTransform());
-        if ((crop != mCurrentCrop) || (transform != mCurrentTransform)) {
+        const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
+        if ((crop != mCurrentCrop) ||
+            (transform != mCurrentTransform) ||
+            (scalingMode != mCurrentScalingMode))
+        {
             mCurrentCrop = crop;
             mCurrentTransform = transform;
+            mCurrentScalingMode = scalingMode;
             mFlinger->invalidateHwcGeometry();
         }
 
@@ -459,13 +454,22 @@
         // FIXME: mPostedDirtyRegion = dirty & bounds
         mPostedDirtyRegion.set(front.w, front.h);
 
-        sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
-        if ((newFrontBuffer->getWidth()  == front.requested_w &&
-            newFrontBuffer->getHeight() == front.requested_h) ||
-            isFixedSize())
+
+        if ((front.w != front.requested_w) ||
+            (front.h != front.requested_h))
         {
-            if ((front.w != front.requested_w) ||
-                (front.h != front.requested_h))
+            // check that we received a buffer of the right size
+            // (Take the buffer's orientation into account)
+            sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
+            uint32_t bufWidth  = newFrontBuffer->getWidth();
+            uint32_t bufHeight = newFrontBuffer->getHeight();
+            if (mCurrentTransform & Transform::ROT_90) {
+                swap(bufWidth, bufHeight);
+            }
+
+            if (isFixedSize() ||
+                    (bufWidth == front.requested_w &&
+                    bufHeight == front.requested_h))
             {
                 // Here we pretend the transaction happened by updating the
                 // current and drawing states. Drawing state is only accessed
@@ -485,10 +489,18 @@
 
                 // recompute visible region
                 recomputeVisibleRegions = true;
+
+                // we now have the correct size, unfreeze the screen
+                mFreezeLock.clear();
             }
 
-            // we now have the correct size, unfreeze the screen
-            mFreezeLock.clear();
+            LOGD_IF(DEBUG_RESIZE,
+                    "lockPageFlip : "
+                    "       (layer=%p), buffer (%ux%u, tr=%02x), "
+                    "requested (%dx%d)",
+                    this,
+                    bufWidth, bufHeight, mCurrentTransform,
+                    front.requested_w, front.requested_h);
         }
     }
 }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e3fc13d..ddfc666 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -59,7 +59,6 @@
     status_t setBuffers(uint32_t w, uint32_t h, 
             PixelFormat format, uint32_t flags=0);
 
-    // Set this Layer's buffers size
     bool isFixedSize() const;
 
     // LayerBase interface
@@ -88,7 +87,6 @@
     void onFrameQueued();
     virtual sp<ISurface> createSurface();
     uint32_t getEffectiveUsage(uint32_t usage) const;
-    void setFixedSize(bool fixedSize);
     bool isCropped() const;
     static bool getOpacityForFormat(uint32_t format);
 
@@ -106,6 +104,7 @@
     GLfloat mTextureMatrix[16];
     Rect mCurrentCrop;
     uint32_t mCurrentTransform;
+    uint32_t mCurrentScalingMode;
     bool mCurrentOpacity;
 
     // constants
@@ -124,7 +123,6 @@
 
     // binder thread, transaction thread
     mutable Mutex mLock;
-    bool mFixedSize;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b0881a4..4a27701 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1318,9 +1318,6 @@
         if (surfaceHandle != 0) {
             params->token = token;
             params->identity = layer->getIdentity();
-            params->width = w;
-            params->height = h;
-            params->format = format;
             if (normalLayer != 0) {
                 Mutex::Autolock _l(mStateLock);
                 mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
@@ -1551,8 +1548,18 @@
          * Dump SurfaceFlinger global state
          */
 
-        snprintf(buffer, SIZE, "SurfaceFlinger global state\n");
+        snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
         result.append(buffer);
+
+        const GLExtensions& extensions(GLExtensions::getInstance());
+        snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
+                extensions.getVendor(),
+                extensions.getRenderer(),
+                extensions.getVersion());
+        result.append(buffer);
+        snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
+        result.append(buffer);
+
         mWormholeRegion.dump(result, "WormholeRegion");
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         snprintf(buffer, SIZE,
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 60fa965..91e010f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -52,6 +52,24 @@
     return res;
 }
 
+status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp,
+        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+
+    status_t res = SurfaceTexture::queueBuffer(buf, timestamp,
+            outWidth, outHeight, outTransform);
+
+    sp<Layer> layer(mLayer.promote());
+    if (layer != NULL) {
+        uint32_t orientation = layer->getOrientation();
+        if (orientation & Transform::ROT_INVALID) {
+            orientation = 0;
+        }
+        *outTransform = orientation;
+    }
+
+    return res;
+}
+
 status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
 
@@ -64,9 +82,6 @@
         //LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
         //        __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
         res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
-        if (res == NO_ERROR) {
-            layer->setFixedSize(w && h);
-        }
     }
     return res;
 }
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index 7faff54..29a9cbe 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -45,6 +45,9 @@
     virtual status_t setBufferCount(int bufferCount);
 
 protected:
+    virtual status_t queueBuffer(int buf, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+
     virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
             uint32_t format, uint32_t usage);
 };
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 4cedcbf..05b7527 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -20,6 +20,7 @@
 #include <utils/String8.h>
 #include <ui/Region.h>
 
+#include "clz.h"
 #include "Transform.h"
 
 // ---------------------------------------------------------------------------
@@ -28,42 +29,6 @@
 
 // ---------------------------------------------------------------------------
 
-template <typename T>
-static inline T min(T a, T b) {
-    return a<b ? a : b;
-}
-template <typename T>
-static inline T min(T a, T b, T c) {
-    return min(a, min(b, c));
-}
-template <typename T>
-static inline T min(T a, T b, T c, T d) {
-    return min(a, b, min(c, d));
-}
-
-template <typename T>
-static inline T max(T a, T b) {
-    return a>b ? a : b;
-}
-template <typename T>
-static inline T max(T a, T b, T c) {
-    return max(a, max(b, c));
-}
-template <typename T>
-static inline T max(T a, T b, T c, T d) {
-    return max(a, b, max(c, d));
-}
-
-template <typename T>
-static inline
-void swap(T& a, T& b) {
-    T t(a);
-    a = b;
-    b = t;
-}
-
-// ---------------------------------------------------------------------------
-
 Transform::Transform() {
     reset();
 }
@@ -343,7 +308,7 @@
 
 bool Transform::preserveRects() const
 {
-    return (type() & ROT_INVALID) ? false : true;
+    return (getOrientation() & ROT_INVALID) ? false : true;
 }
 
 void Transform::dump(const char* name) const
diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index ca445553..a4c5262 100644
--- a/services/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
@@ -24,6 +24,41 @@
     return __builtin_clz(x);
 }
 
+template <typename T>
+static inline T min(T a, T b) {
+    return a<b ? a : b;
+}
+template <typename T>
+static inline T min(T a, T b, T c) {
+    return min(a, min(b, c));
+}
+template <typename T>
+static inline T min(T a, T b, T c, T d) {
+    return min(a, b, min(c, d));
+}
+
+template <typename T>
+static inline T max(T a, T b) {
+    return a>b ? a : b;
+}
+template <typename T>
+static inline T max(T a, T b, T c) {
+    return max(a, max(b, c));
+}
+template <typename T>
+static inline T max(T a, T b, T c, T d) {
+    return max(a, b, max(c, d));
+}
+
+template <typename T>
+static inline
+void swap(T& a, T& b) {
+    T t(a);
+    a = b;
+    b = t;
+}
+
+
 }; // namespace android
 
 #endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index ee5f3f5..1620405 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -29,6 +29,7 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 302a2d6..46bcc4a 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -29,12 +29,13 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.view.accessibility.IAccessibilityManagerClient;
 
 /**
  * This test exercises the
- * {@link com.android.server.AccessibilityManagerService} by mocking the
+ * {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the
  * {@link android.view.accessibility.AccessibilityManager} which talks to to the
  * service. The service itself is interacting with the platform. Note: Testing
  * the service in full isolation would require significant amount of work for
@@ -97,7 +98,9 @@
         MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
 
         // invoke the method under test
-        boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+        final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+        boolean enabledAccessibilityDisabled =
+            (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
         // check expected result
         assertFalse("The client must be disabled since accessibility is disabled.",
@@ -107,7 +110,10 @@
         ensureAccessibilityEnabled(mContext, true);
 
         // invoke the method under test
-        boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+        final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+        boolean enabledAccessibilityEnabled =
+            (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+
 
         // check expected result
         assertTrue("The client must be enabled since accessibility is enabled.",
@@ -123,7 +129,9 @@
         MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
 
         // invoke the method under test
-        boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+        final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+        boolean enabledAccessibilityEnabled =
+            (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
         // check expected result
         assertTrue("The client must be enabled since accessibility is enabled.",
@@ -133,7 +141,9 @@
         ensureAccessibilityEnabled(mContext, false);
 
         // invoke the method under test
-        boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+        final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+        boolean enabledAccessibilityDisabled =
+            (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
         // check expected result
         assertFalse("The client must be disabled since accessibility is disabled.",
@@ -537,10 +547,13 @@
      * This class is a mock {@link IAccessibilityManagerClient}.
      */
     public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub {
-        boolean mIsEnabled;
+        int mState;
 
-        public void setEnabled(boolean enabled) {
-            mIsEnabled = enabled;
+        public void setState(int state) {
+            mState = state;
+        }
+
+        public void setTouchExplorationEnabled(boolean enabled) {
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index 1463d30..e083815 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -70,7 +70,8 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
         expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn(
                 expectedServices);
         replay(mockServiceInterface);
@@ -91,7 +92,8 @@
     public void testInterrupt() throws Exception {
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
         mockServiceInterface.interrupt();
         replay(mockServiceInterface);
 
@@ -107,7 +109,8 @@
     public void testIsEnabled() throws Exception {
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
         replay(mockServiceInterface);
 
         // invoke the method under test
@@ -118,7 +121,7 @@
         assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled);
 
         // disable accessibility
-        manager.getClient().setEnabled(false);
+        manager.getClient().setState(0);
 
         // wait for the asynchronous IBinder call to complete
         Thread.sleep(TIMEOUT_BINDER_CALL);
@@ -141,7 +144,8 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
         expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
                 .andReturn(true);
         expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
@@ -176,7 +180,7 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(false);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0);
         replay(mockServiceInterface);
 
         // invoke the method under test (accessibility disabled)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 33fd355..aab09ca 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -20,6 +20,7 @@
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -27,7 +28,10 @@
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkTemplate.MATCH_WIFI;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
 import static org.easymock.EasyMock.anyInt;
 import static org.easymock.EasyMock.aryEq;
 import static org.easymock.EasyMock.capture;
@@ -40,12 +44,14 @@
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
+import android.app.Notification;
 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.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkStatsService;
 import android.net.LinkProperties;
@@ -88,7 +94,7 @@
     private static final long TEST_START = 1194220800000L;
     private static final String TEST_IFACE = "test0";
 
-    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
+    private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi();
 
     private BroadcastInterceptingContext mServiceContext;
     private File mPolicyDir;
@@ -96,7 +102,7 @@
     private IActivityManager mActivityManager;
     private IPowerManager mPowerManager;
     private INetworkStatsService mStatsService;
-    private INetworkManagementService mNetworkManagement;
+    private INetworkManagementService mNetworkManager;
     private INetworkPolicyListener mPolicyListener;
     private TrustedTime mTime;
     private IConnectivityManager mConnManager;
@@ -104,6 +110,7 @@
 
     private NetworkPolicyManagerService mService;
     private IProcessObserver mProcessObserver;
+    private INetworkManagementEventObserver mNetworkObserver;
 
     private Binder mStubBinder = new Binder();
 
@@ -142,6 +149,11 @@
                     }
                 };
             }
+
+            @Override
+            public void startActivity(Intent intent) {
+                // ignored
+            }
         };
 
         mPolicyDir = getContext().getFilesDir();
@@ -152,7 +164,7 @@
         mActivityManager = createMock(IActivityManager.class);
         mPowerManager = createMock(IPowerManager.class);
         mStatsService = createMock(INetworkStatsService.class);
-        mNetworkManagement = createMock(INetworkManagementService.class);
+        mNetworkManager = createMock(INetworkManagementService.class);
         mPolicyListener = createMock(INetworkPolicyListener.class);
         mTime = createMock(TrustedTime.class);
         mConnManager = createMock(IConnectivityManager.class);
@@ -160,7 +172,7 @@
 
         mService = new NetworkPolicyManagerService(
                 mServiceContext, mActivityManager, mPowerManager, mStatsService,
-                mNetworkManagement, mTime, mPolicyDir);
+                mNetworkManager, mTime, mPolicyDir);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
 
@@ -170,11 +182,17 @@
         mService.registerListener(mPolicyListener);
         verifyAndReset();
 
-        // catch the registered IProcessObserver during systemReady()
+        // catch IProcessObserver during systemReady()
         final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
         mActivityManager.registerProcessObserver(capture(processObserver));
         expectLastCall().atLeastOnce();
 
+        // catch INetworkManagementEventObserver during systemReady()
+        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+                INetworkManagementEventObserver>();
+        mNetworkManager.registerObserver(capture(networkObserver));
+        expectLastCall().atLeastOnce();
+
         // expect to answer screen status during systemReady()
         expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
         expectTime(System.currentTimeMillis());
@@ -187,6 +205,7 @@
         verifyAndReset();
 
         mProcessObserver = processObserver.getValue();
+        mNetworkObserver = networkObserver.getValue();
 
     }
 
@@ -383,7 +402,8 @@
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
         final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
 
-        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 5, 1024L, 1024L);
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
         assertEquals(expectedCycle, actualCycle);
     }
@@ -393,7 +413,8 @@
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
         final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
 
-        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 20, 1024L, 1024L);
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
         assertEquals(expectedCycle, actualCycle);
     }
@@ -403,7 +424,8 @@
         final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
         final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
 
-        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
         assertEquals(expectedCycle, actualCycle);
     }
@@ -413,7 +435,8 @@
         final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
         final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
 
-        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
         assertEquals(expectedCycle, actualCycle);
     }
@@ -433,6 +456,7 @@
         state = new NetworkState[] { buildWifi() };
         expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
         expectTime(TIME_MAR_10 + elapsedRealtime);
+        expectClearNotifications();
         future = expectMeteredIfacesChanged();
 
         replay();
@@ -454,12 +478,14 @@
         // TODO: consider making strongly ordered mock
         expectRemoveInterfaceQuota(TEST_IFACE);
         expectSetInterfaceQuota(TEST_IFACE, 1536L);
+        expectRemoveInterfaceAlert(TEST_IFACE);
+        expectSetInterfaceAlert(TEST_IFACE, 512L);
 
         expectClearNotifications();
         future = expectMeteredIfacesChanged(TEST_IFACE);
 
         replay();
-        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
+        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
         future.get();
         verifyAndReset();
     }
@@ -486,6 +512,131 @@
         verifyAndReset();
     }
 
+    public void testOverWarningLimitNotification() throws Exception {
+        long elapsedRealtime = 0;
+        long currentTime = 0;
+        NetworkState[] state = null;
+        NetworkStats stats = null;
+        Future<Void> future;
+        Capture<String> tag;
+
+        final long TIME_FEB_15 = 1171497600000L;
+        final long TIME_MAR_10 = 1173484800000L;
+        final int CYCLE_DAY = 15;
+
+        // assign wifi policy
+        elapsedRealtime = 0;
+        currentTime = TIME_MAR_10 + elapsedRealtime;
+        state = new NetworkState[] {};
+
+        {
+            expectTime(currentTime);
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+
+            expectClearNotifications();
+            future = expectMeteredIfacesChanged();
+
+            replay();
+            setNetworkPolicies(
+                    new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
+            future.get();
+            verifyAndReset();
+        }
+
+        // bring up wifi network
+        elapsedRealtime += MINUTE_IN_MILLIS;
+        currentTime = TIME_MAR_10 + elapsedRealtime;
+        stats = new NetworkStats(elapsedRealtime, 1)
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L);
+        state = new NetworkState[] { buildWifi() };
+
+        {
+            expectTime(currentTime);
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+                    .andReturn(stats).atLeastOnce();
+
+            expectRemoveInterfaceQuota(TEST_IFACE);
+            expectSetInterfaceQuota(TEST_IFACE, 2048L);
+            expectRemoveInterfaceAlert(TEST_IFACE);
+            expectSetInterfaceAlert(TEST_IFACE, 1024L);
+
+            expectClearNotifications();
+            future = expectMeteredIfacesChanged(TEST_IFACE);
+
+            replay();
+            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+            future.get();
+            verifyAndReset();
+        }
+
+        // go over warning, which should kick notification
+        elapsedRealtime += MINUTE_IN_MILLIS;
+        currentTime = TIME_MAR_10 + elapsedRealtime;
+        stats = new NetworkStats(elapsedRealtime, 1)
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L);
+
+        {
+            expectTime(currentTime);
+            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+                    .andReturn(stats).atLeastOnce();
+
+            expectForceUpdate();
+            expectClearNotifications();
+            tag = expectEnqueueNotification();
+
+            replay();
+            mNetworkObserver.limitReached(null, TEST_IFACE);
+            assertNotificationType(TYPE_WARNING, tag.getValue());
+            verifyAndReset();
+        }
+
+        // go over limit, which should kick notification and dialog
+        elapsedRealtime += MINUTE_IN_MILLIS;
+        currentTime = TIME_MAR_10 + elapsedRealtime;
+        stats = new NetworkStats(elapsedRealtime, 1)
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L);
+
+        {
+            expectTime(currentTime);
+            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+                    .andReturn(stats).atLeastOnce();
+
+            expectForceUpdate();
+            expectClearNotifications();
+            tag = expectEnqueueNotification();
+
+            replay();
+            mNetworkObserver.limitReached(null, TEST_IFACE);
+            assertNotificationType(TYPE_LIMIT, tag.getValue());
+            verifyAndReset();
+        }
+
+        // now snooze policy, which should remove quota
+        elapsedRealtime += MINUTE_IN_MILLIS;
+        currentTime = TIME_MAR_10 + elapsedRealtime;
+
+        {
+            expectTime(currentTime);
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+                    .andReturn(stats).atLeastOnce();
+
+            expectRemoveInterfaceQuota(TEST_IFACE);
+            expectRemoveInterfaceAlert(TEST_IFACE);
+
+            expectClearNotifications();
+            tag = expectEnqueueNotification();
+            future = expectMeteredIfacesChanged();
+
+            replay();
+            mService.snoozePolicy(sTemplateWifi);
+            future.get();
+            assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
+            verifyAndReset();
+        }
+    }
+
     private static long parseTime(String time) {
         final Time result = new Time();
         result.parse3339(time);
@@ -512,24 +663,46 @@
         expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
     }
 
+    private void expectForceUpdate() throws Exception {
+        mStatsService.forceUpdate();
+        expectLastCall().atLeastOnce();
+    }
+
     private void expectClearNotifications() throws Exception {
         mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
         expectLastCall().anyTimes();
     }
 
-    private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
-        mNetworkManagement.setInterfaceQuota(iface, quota);
+    private Capture<String> expectEnqueueNotification() throws Exception {
+        final Capture<String> tag = new Capture<String>();
+        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
+                isA(Notification.class), isA(int[].class));
+        return tag;
+    }
+
+    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
         expectLastCall().atLeastOnce();
     }
 
     private void expectRemoveInterfaceQuota(String iface) throws Exception {
-        mNetworkManagement.removeInterfaceQuota(iface);
+        mNetworkManager.removeInterfaceQuota(iface);
+        expectLastCall().atLeastOnce();
+    }
+
+    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
+        mNetworkManager.setInterfaceAlert(iface, alertBytes);
+        expectLastCall().atLeastOnce();
+    }
+
+    private void expectRemoveInterfaceAlert(String iface) throws Exception {
+        mNetworkManager.removeInterfaceAlert(iface);
         expectLastCall().atLeastOnce();
     }
 
     private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
             throws Exception {
-        mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+        mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
         expectLastCall().atLeastOnce();
     }
 
@@ -564,15 +737,20 @@
         }
     }
 
+    private static void assertNotificationType(int expected, String actualTag) {
+        assertEquals(
+                Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
+    }
+
     private void replay() {
         EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManagement, mTime, mConnManager, mNotifManager);
+                mNetworkManager, mTime, mConnManager, mNotifManager);
     }
 
     private void verifyAndReset() {
         EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManagement, mTime, mConnManager, mNotifManager);
+                mNetworkManager, mTime, mConnManager, mNotifManager);
         EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManagement, mTime, mConnManager, mNotifManager);
+                mNetworkManager, 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 ac74063..bd80af9 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -25,8 +25,8 @@
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
-import static android.net.NetworkTemplate.MATCH_WIFI;
+import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateWifi;
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
@@ -81,9 +81,9 @@
     private static final String IMSI_1 = "310004";
     private static final String IMSI_2 = "310260";
 
-    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
-    private static NetworkTemplate sTemplateImsi1 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_1);
-    private static NetworkTemplate sTemplateImsi2 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_2);
+    private static NetworkTemplate sTemplateWifi = buildTemplateWifi();
+    private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
+    private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
 
     private static final int UID_RED = 1001;
     private static final int UID_BLUE = 1002;
@@ -290,7 +290,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify service recorded history
-        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
+        history = mService.getHistoryForNetwork(sTemplateWifi);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
         assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
         assertEquals(2, history.size());
@@ -307,7 +307,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify identical stats, but spread across 4 buckets now
-        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
+        history = mService.getHistoryForNetwork(sTemplateWifi);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
         assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
         assertEquals(4, history.size());
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 66120a1..f7e0c66 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -61,7 +61,7 @@
     /** @hide */
     public TelephonyManager(Context context) {
         if (sContext == null) {
-            sContext = context;
+            sContext = context.getApplicationContext();
 
             sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                     "telephony.registry"));
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 8427d14..f0d2fba 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -857,22 +857,28 @@
      */
     public static int getLteOnCdmaModeStatic() {
         int retVal;
-        String productType;
+        int curVal;
+        String productType = "";
 
-        Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
-        if (matcher.find()) {
-            productType = matcher.group(1);
-            if (sLteOnCdmaProductType.equals(productType)) {
-                retVal = Phone.LTE_ON_CDMA_TRUE;
+        curVal = SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,
+                    Phone.LTE_ON_CDMA_UNKNOWN);
+        retVal = curVal;
+        if (retVal == Phone.LTE_ON_CDMA_UNKNOWN) {
+            Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
+            if (matcher.find()) {
+                productType = matcher.group(1);
+                if (sLteOnCdmaProductType.equals(productType)) {
+                    retVal = Phone.LTE_ON_CDMA_TRUE;
+                } else {
+                    retVal = Phone.LTE_ON_CDMA_FALSE;
+                }
             } else {
                 retVal = Phone.LTE_ON_CDMA_FALSE;
             }
-        } else {
-            retVal = Phone.LTE_ON_CDMA_FALSE;
-            productType = "";
         }
 
-        Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " product_type='" + productType +
+        Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " curVal=" + curVal +
+                " product_type='" + productType +
                 "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'");
         return retVal;
     }
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index fba3184..6d8956f 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -52,7 +52,7 @@
     /**
      * Class returned by onSetupConnectionCompleted.
      */
-    protected enum SetupResult {
+    public enum SetupResult {
         SUCCESS,
         ERR_BadCommand,
         ERR_UnacceptableParameter,
@@ -142,13 +142,15 @@
                         } catch (IllegalArgumentException e) {
                             throw new UnknownHostException("Non-numeric ip addr=" + addr);
                         }
-                        if (addrPrefixLen == 0) {
-                            // Assume point to point
-                            addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+                        if (! ia.isAnyLocalAddress()) {
+                            if (addrPrefixLen == 0) {
+                                // Assume point to point
+                                addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+                            }
+                            if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
+                            la = new LinkAddress(ia, addrPrefixLen);
+                            linkProperties.addLinkAddress(la);
                         }
-                        if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
-                        la = new LinkAddress(ia, addrPrefixLen);
-                        linkProperties.addLinkAddress(la);
                     }
                 } else {
                     throw new UnknownHostException("no address for ifname=" + ifname);
@@ -163,21 +165,24 @@
                         } catch (IllegalArgumentException e) {
                             throw new UnknownHostException("Non-numeric dns addr=" + addr);
                         }
-                        linkProperties.addDns(ia);
+                        if (! ia.isAnyLocalAddress()) {
+                            linkProperties.addDns(ia);
+                        }
                     }
                 } else if (okToUseSystemPropertyDns){
                     String dnsServers[] = new String[2];
                     dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
                     dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
                     for (String dnsAddr : dnsServers) {
-                            InetAddress ia;
-                            try {
-                                ia = NetworkUtils.numericToInetAddress(dnsAddr);
-                            } catch (IllegalArgumentException e) {
-                                throw new UnknownHostException("Non-numeric dns addr="
-                                            + dnsAddr);
-                            }
+                        InetAddress ia;
+                        try {
+                            ia = NetworkUtils.numericToInetAddress(dnsAddr);
+                        } catch (IllegalArgumentException e) {
+                            throw new UnknownHostException("Non-numeric dns addr=" + dnsAddr);
+                        }
+                        if (! ia.isAnyLocalAddress()) {
                             linkProperties.addDns(ia);
+                        }
                     }
                 } else {
                     throw new UnknownHostException("Empty dns response and no system default dns");
@@ -199,7 +204,9 @@
                     } catch (IllegalArgumentException e) {
                         throw new UnknownHostException("Non-numeric gateway addr=" + addr);
                     }
-                    linkProperties.addRoute(new RouteInfo(ia));
+                    if (! ia.isAnyLocalAddress()) {
+                        linkProperties.addRoute(new RouteInfo(ia));
+                    }
                 }
 
                 result = SetupResult.SUCCESS;
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 5c84fdc..636646e 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -17,30 +17,24 @@
 package com.android.internal.telephony;
 
 
+import com.android.internal.telephony.DataCallState.SetupResult;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 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;
-import android.net.NetworkUtils;
 import android.net.ProxyProperties;
 import android.os.AsyncResult;
-import android.os.Bundle;
 import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
 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;
 
 /**
  * {@hide}
@@ -453,6 +447,7 @@
         lastFailCause = FailCause.NONE;
         mRetryOverride = -1;
         mRefCount = 0;
+        cid = -1;
 
         mLinkProperties = new LinkProperties();
         mApn = null;
@@ -497,8 +492,7 @@
         } else {
             if (DBG) log("onSetupConnectionCompleted received DataCallState: " + response);
             cid = response.cid;
-            // set link properties based on data call response
-            result = setLinkProperties(response, mLinkProperties);
+            result = updateLinkProperty(response).setupResult;
         }
 
         return result;
@@ -527,48 +521,41 @@
         return response.setLinkProperties(lp, okToUseSystemPropertyDns);
     }
 
-    private DataConnectionAc.LinkPropertyChangeAction updateLinkProperty(
-                                                      DataCallState newState) {
-        DataConnectionAc.LinkPropertyChangeAction changed =
-                        DataConnectionAc.LinkPropertyChangeAction.NONE;
+    public static class UpdateLinkPropertyResult {
+        public DataCallState.SetupResult setupResult = DataCallState.SetupResult.SUCCESS;
+        public LinkProperties oldLp;
+        public LinkProperties newLp;
+        public UpdateLinkPropertyResult(LinkProperties curLp) {
+            oldLp = curLp;
+            newLp = curLp;
+        }
+    }
 
-        if (newState == null) return changed;
+    private UpdateLinkPropertyResult updateLinkProperty(DataCallState newState) {
+        UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
 
-        DataCallState.SetupResult result;
-        LinkProperties newLp = new LinkProperties();
+        if (newState == null) return result;
+
+        DataCallState.SetupResult setupResult;
+        result.newLp = new LinkProperties();
 
         // set link properties based on data call response
-        result = setLinkProperties(newState, newLp);
-        if (result != DataCallState.SetupResult.SUCCESS) {
-            if (DBG) log("UpdateLinkProperty failed : " + result);
-            return changed;
+        result.setupResult = setLinkProperties(newState, result.newLp);
+        if (result.setupResult != DataCallState.SetupResult.SUCCESS) {
+            if (DBG) log("updateLinkProperty failed : " + result.setupResult);
+            return result;
         }
         // copy HTTP proxy as it is not part DataCallState.
-        newLp.setHttpProxy(mLinkProperties.getHttpProxy());
+        result.newLp.setHttpProxy(mLinkProperties.getHttpProxy());
 
-        if (DBG) log("old LP=" + mLinkProperties);
-        if (DBG) log("new LP=" + newLp);
-
-        // Check consistency of link address. Currently we expect
-        // only one "global" address is assigned per each IP type.
-        Collection<LinkAddress> oLinks = mLinkProperties.getLinkAddresses();
-        Collection<LinkAddress> nLinks = newLp.getLinkAddresses();
-        for (LinkAddress oldLink : oLinks) {
-            for (LinkAddress newLink : nLinks) {
-                if ((NetworkUtils.addressTypeMatches(oldLink.getAddress(),
-                                        newLink.getAddress())) &&
-                    (oldLink.equals(newLink) == false)) {
-                    return DataConnectionAc.LinkPropertyChangeAction.RESET;
-                }
-            }
+        if (DBG && (! result.oldLp.equals(result.newLp))) {
+            if (DBG) log("updateLinkProperty old != new");
+            if (VDBG) log("updateLinkProperty old LP=" + result.oldLp);
+            if (VDBG) log("updateLinkProperty new LP=" + result.newLp);
         }
+        mLinkProperties = result.newLp;
 
-        if (mLinkProperties == null || !mLinkProperties.equals(newLp)) {
-            mLinkProperties = newLp;
-            changed = DataConnectionAc.LinkPropertyChangeAction.CHANGED;
-        }
-
-        return changed;
+        return result;
     }
 
     /**
@@ -643,14 +630,15 @@
                 }
                 case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
                     DataCallState newState = (DataCallState) msg.obj;
-                    DataConnectionAc.LinkPropertyChangeAction action = updateLinkProperty(newState);
+                    UpdateLinkPropertyResult result =
+                                             updateLinkProperty(newState);
                     if (VDBG) {
-                        log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE action="
-                            + action + " newState=" + newState);
+                        log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE result="
+                            + result + " newState=" + newState);
                     }
                     mAc.replyToMessage(msg,
                                    DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
-                                   action.ordinal());
+                                   result);
                     break;
                 }
                 case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
@@ -688,7 +676,7 @@
                 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));
+                                       new ArrayList<ApnContext>(mApnList));
                     break;
                 }
                 case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
index 309dbed6..a9f2cd1 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionAc.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony;
 
+import com.android.internal.telephony.DataConnection.UpdateLinkPropertyResult;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
@@ -310,18 +311,18 @@
         if (DBG) log("reqUpdateLinkPropertiesDataCallState");
     }
 
-    public LinkPropertyChangeAction rspUpdateLinkPropertiesDataCallState(Message response) {
-        LinkPropertyChangeAction retVal = LinkPropertyChangeAction.fromInt(response.arg1);
-        if (DBG) log("rspUpdateLinkPropertiesState=" + retVal);
+    public UpdateLinkPropertyResult rspUpdateLinkPropertiesDataCallState(Message response) {
+        UpdateLinkPropertyResult retVal = (UpdateLinkPropertyResult)response.obj;
+        if (DBG) log("rspUpdateLinkPropertiesState: retVal=" + retVal);
         return retVal;
     }
 
     /**
      * Update link properties in the data connection
      *
-     * @return true if link property has been updated. false otherwise.
+     * @return the removed and added addresses.
      */
-    public LinkPropertyChangeAction updateLinkPropertiesDataCallStateSync(DataCallState newState) {
+    public UpdateLinkPropertyResult updateLinkPropertiesDataCallStateSync(DataCallState newState) {
         Message response =
             sendMessageSynchronously(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
         if ((response != null) &&
@@ -329,7 +330,7 @@
             return rspUpdateLinkPropertiesDataCallState(response);
         } else {
             log("getLinkProperties error response=" + response);
-            return LinkPropertyChangeAction.NONE;
+            return new UpdateLinkPropertyResult(new LinkProperties());
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 4f8b525..3bd78e04 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -36,6 +36,7 @@
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
+import android.telephony.ServiceState;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
 import android.util.Log;
@@ -1031,6 +1032,27 @@
     protected void onSetDependencyMet(String apnType, boolean met) {
     }
 
+    protected String getReryConfig(boolean forDefault) {
+        int rt = mPhone.getServiceState().getRadioTechnology();
+
+        if ((rt == ServiceState.RADIO_TECHNOLOGY_IS95A) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_IS95B) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_1xRTT) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_0) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_A) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_B) ||
+            (rt == ServiceState.RADIO_TECHNOLOGY_EHRPD)) {
+            // CDMA variant
+            return SystemProperties.get("ro.cdma.data_retry_config");
+        } else {
+            // Use GSM varient for all others.
+            if (forDefault) {
+                return SystemProperties.get("ro.gsm.data_retry_config");
+            } else {
+                return SystemProperties.get("ro.gsm.2nd_data_retry_config");
+            }
+        }
+    }
 
     protected void resetAllRetryCounts() {
         for (DataConnection dc : mDataConnections.values()) {
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 48c5318..4b02e8e 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -1430,6 +1430,11 @@
     String getMeid();
 
     /**
+     * Retrieves IMEI for phones. Returns null if IMEI is not set.
+     */
+    String getImei();
+
+    /**
      * Retrieves the PhoneSubInfo of the Phone
      */
     public PhoneSubInfo getPhoneSubInfo();
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 40a70a8..a0961ca 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -806,10 +806,10 @@
         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
     }
 
-    public void notifyDataConnection() {
+    public void notifyDataConnection(String reason) {
         String types[] = getActiveApnTypes();
         for (String apnType : types) {
-            mNotifier.notifyDataConnection(this, null, apnType, getDataConnectionState(apnType));
+            mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index c2212db..b5bfc76f 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -685,6 +685,10 @@
         return mActivePhone.getMeid();
     }
 
+    public String getImei() {
+        return mActivePhone.getImei();
+    }
+
     public PhoneSubInfo getPhoneSubInfo(){
         return mActivePhone.getPhoneSubInfo();
     }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 93fc9ce..facee5f 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -31,6 +31,8 @@
     // From the top of ril.cpp
     int RIL_ERRNO_INVALID_RESPONSE = -1;
 
+    int MAX_INT = 0x7FFFFFFF;
+
     // from RIL_Errno
     int SUCCESS = 0;
     int RADIO_NOT_AVAILABLE = 1;              /* If radio did not start or is resetting */
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 60cf9b7..abb4523 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -79,6 +79,15 @@
      */
     static final String PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE = "telephony.lteOnCdmaProductType";
 
+    /**
+     * The contents of this property is the one of {@link Phone#LTE_ON_CDMA_TRUE} or
+     * {@link Phone#LTE_ON_CDMA_FALSE}. If absent the value will assumed to be false
+     * and the {@see #PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE} will be used to determine its
+     * final value which could also be {@link Phone#LTE_ON_CDMA_FALSE}.
+     * {@see BaseCommands#getLteOnCdmaMode()}
+     */
+    static final String PROPERTY_LTE_ON_CDMA_DEVICE = "telephony.lteOnCdmaDevice";
+
     static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
 
     //****** SIM Card
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index a31b704..ac66b48 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -136,6 +136,16 @@
     }
 
     @Override
+    public String getImei() {
+        return mImei;
+    }
+
+    @Override
+    public String getDeviceSvn() {
+        return mImeiSv;
+    }
+
+    @Override
     protected void log(String s) {
         if (DBG)
             Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 8a60b5a..286515e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -122,6 +122,8 @@
     //keep track of if phone is in emergency callback mode
     private boolean mIsPhoneInEcmState;
     private Registrant mEcmExitRespRegistrant;
+    protected String mImei;
+    protected String mImeiSv;
     private String mEsn;
     private String mMeid;
     // string to define how the carrier specifies its own ota sp number
@@ -489,6 +491,11 @@
         return mSST.getImsi();
     }
 
+    public String getImei() {
+        Log.e(LOG_TAG, "IMEI is not available in CDMA");
+        return null;
+    }
+
     public boolean canConference() {
         Log.e(LOG_TAG, "canConference: not possible in CDMA");
         return false;
@@ -987,6 +994,8 @@
                     break;
                 }
                 String[] respId = (String[])ar.result;
+                mImei = respId[0];
+                mImeiSv = respId[1];
                 mEsn  =  respId[2];
                 mMeid =  respId[3];
             }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 0d551aa..4d86903 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -134,8 +134,6 @@
                 }
             }
 
-            // Not sure if this is needed in CDMALTE phone.
-            // mDataRoaming = regCodeIsRoaming(regState);
             mLteSS.setRadioTechnology(type);
             mLteSS.setState(regCodeToServiceState(regState));
         } else {
@@ -219,6 +217,26 @@
                 " mNewDataConnectionState = " + mNewDataConnectionState);
         }
 
+        // TODO: Add proper support for LTE Only, we should be looking at
+        //       the preferred network mode, to know when newSS state should
+        //       be coming from mLteSs state. This was needed to pass a VZW
+        //       LTE Only test.
+        //
+        // If CDMA service is OOS, double check if the device is running with LTE only
+        // mode. If that is the case, derive the service state from LTE side.
+        // To set in LTE only mode, sqlite3 /data/data/com.android.providers.settings/
+        // databases/settings.db "update secure set value='11' where name='preferred_network_mode'"
+        if (newSS.getState() == ServiceState.STATE_OUT_OF_SERVICE) {
+            int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
+                                  .getContentResolver(),
+                                  android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+                                  RILConstants.PREFERRED_NETWORK_MODE);
+            if (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY) {
+                if (DBG) log("pollState: LTE Only mode");
+                newSS.setState(mLteSS.getState());
+            }
+        }
+
         if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
 
         boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -249,10 +267,11 @@
         boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
 
         boolean has4gHandoff =
-                ((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) &&
-                 (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) ||
-                ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) &&
-                 (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE));
+                mNewDataConnectionState == ServiceState.STATE_IN_SERVICE &&
+                (((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) &&
+                  (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) ||
+                 ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) &&
+                  (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE)));
 
         boolean hasMultiApnSupport =
                 (((newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE) ||
@@ -345,13 +364,14 @@
             }
 
             if (cm.getSimState().isSIMReady()) {
-                // SIM is found on the device. If ERI roaming is OFF, use operator name
-                // from CSIM record.
+                // SIM is found on the device. If ERI roaming is OFF and SID/NID matches
+                // one configfured in SIM, use operator name from CSIM record.
                 boolean showSpn =
                     ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
                 int iconIndex = ss.getCdmaEriIconIndex();
 
-                if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)) {
+                if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) &&
+                    isInHomeSidNid(ss.getSystemId(), ss.getNetworkId())) {
                     ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
                 }
             }
@@ -392,7 +412,7 @@
             phone.notifyServiceStateChanged(ss);
         }
 
-        if (hasCdmaDataConnectionAttached) {
+        if (hasCdmaDataConnectionAttached || has4gHandoff) {
             mAttachedRegistrants.notifyRegistrants();
         }
 
@@ -401,7 +421,7 @@
         }
 
         if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)) {
-            phone.notifyDataConnection();
+            phone.notifyDataConnection(null);
         }
 
         if (hasRoamingOn) {
@@ -469,6 +489,34 @@
     }
 
     /**
+     * Check whether the specified SID and NID pair appears in the HOME SID/NID list
+     * read from NV or SIM.
+     *
+     * @return true if provided sid/nid pair belongs to operator's home network.
+     */
+    private boolean isInHomeSidNid(int sid, int nid) {
+        // if SID/NID is not available, assume this is home network.
+        if (isSidsAllZeros()) return true;
+
+        // length of SID/NID shold be same
+        if (mHomeSystemId.length != mHomeNetworkId.length) return true;
+
+        if (sid == 0) return true;
+
+        for (int i = 0; i < mHomeSystemId.length; i++) {
+            // Use SID only if NID is a reserved value.
+            // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
+            if ((mHomeSystemId[i] == sid) &&
+                ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
+                 (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
+                return true;
+            }
+        }
+        // SID/NID are not in the list. So device is not in home network
+        return false;
+    }
+
+    /**
      * Returns OTASP_NOT_NEEDED as its not needed for LTE
      */
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 24a468a..2cf4b88 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -130,8 +130,8 @@
     protected String mCurPlmn = null;
 
     protected String mMdn;
-    private int mHomeSystemId[] = null;
-    private int mHomeNetworkId[] = null;
+    protected int mHomeSystemId[] = null;
+    protected int mHomeNetworkId[] = null;
     protected String mMin;
     protected String mPrlVersion;
     protected boolean mIsMinInfoReady = false;
@@ -999,7 +999,7 @@
         }
 
         if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
-            phone.notifyDataConnection();
+            phone.notifyDataConnection(null);
         }
 
         if (hasRoamingOn) {
@@ -1481,7 +1481,7 @@
         }
     }
 
-    private boolean isSidsAllZeros() {
+    protected boolean isSidsAllZeros() {
         if (mHomeSystemId != null) {
             for (int i=0; i < mHomeSystemId.length; i++) {
                 if (mHomeSystemId[i] != 0) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index d357eac..1db9860 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -855,6 +855,10 @@
         return mImeiSv;
     }
 
+    public String getImei() {
+        return mImei;
+    }
+
     public String getEsn() {
         Log.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method");
         return "0";
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index df5898b..be129d5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -26,6 +26,9 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.ConnectivityManager;
+import android.net.LinkAddress;
+import android.net.LinkProperties.CompareResult;
+import android.net.NetworkUtils;
 import android.net.ProxyProperties;
 import android.net.TrafficStats;
 import android.net.Uri;
@@ -53,6 +56,7 @@
 import com.android.internal.telephony.ApnSetting;
 import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.UpdateLinkPropertyResult;
 import com.android.internal.telephony.DataConnectionAc;
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
@@ -605,9 +609,20 @@
         for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
             if (dcac.getReconnectIntentSync() != null) {
                 cancelReconnectAlarm(dcac);
-                if (dcac.dataConnection != null) {
-                    dcac.dataConnection.resetRetryCount();
+            }
+            // update retry config for existing calls to match up
+            // ones for the new RAT.
+            if (dcac.dataConnection != null) {
+                Collection<ApnContext> apns = dcac.getApnListSync();
+
+                boolean hasDefault = false;
+                for (ApnContext apnContext : apns) {
+                    if (apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
+                        hasDefault = true;
+                        break;
+                    }
                 }
+                configureRetry(dcac.dataConnection, hasDefault);
             }
         }
 
@@ -969,7 +984,7 @@
 
             // configure retry count if no other Apn is using the same connection.
             if (refCount == 0) {
-                configureRetry(dc, apnContext.getApnType());
+                configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT));
             }
             apnContext.setDataConnectionAc(dcac);
             apnContext.setDataConnection(dc);
@@ -1037,7 +1052,7 @@
 
     /**
      * @param dcacs Collection of DataConnectionAc reported from RIL.
-     * @return List of ApnContext whihc is connected, but does not present in
+     * @return List of ApnContext which is connected, but is not present in
      *         data connection list reported from RIL.
      */
     private List<ApnContext> findApnContextToClean(Collection<DataConnectionAc> dcacs) {
@@ -1091,32 +1106,30 @@
         if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
 
         // Create a hash map to store the dataCallState of each DataConnectionAc
-        // TODO: Depends on how frequent the DATA_CALL_LIST got updated,
-        //       may cache response to reduce comparison.
-        HashMap<DataCallState, DataConnectionAc> response;
-        response = new HashMap<DataCallState, DataConnectionAc>();
+        HashMap<DataCallState, DataConnectionAc> dataCallStateToDcac;
+        dataCallStateToDcac = new HashMap<DataCallState, DataConnectionAc>();
         for (DataCallState dataCallState : dataCallStates) {
             DataConnectionAc dcac = findDataConnectionAcByCid(dataCallState.cid);
 
-            if (dcac != null) response.put(dataCallState, dcac);
+            if (dcac != null) dataCallStateToDcac.put(dataCallState, dcac);
         }
 
-        // step1: Find a list of "connected" APN which does not have reference to
-        //        calls listed in the Data Call List.
-        List<ApnContext> apnsToClear = findApnContextToClean(response.values());
+        // A list of apns to cleanup, those that aren't in the list we know we have to cleanup
+        List<ApnContext> apnsToCleanup = findApnContextToClean(dataCallStateToDcac.values());
 
-        // step2: Check status of each calls in Data Call List.
-        //        Collect list of ApnContext associated with the data call if the link
-        //        has to be cleared.
+        // Find which connections have changed state and send a notification or cleanup
         for (DataCallState newState : dataCallStates) {
-            DataConnectionAc dcac = response.get(newState);
+            DataConnectionAc dcac = dataCallStateToDcac.get(newState);
 
-            // no associated DataConnection found. Ignore.
-            if (dcac == null) continue;
+            if (dcac == null) {
+                loge("onDataStateChanged(ar): No associated DataConnection ignore");
+                continue;
+            }
 
+            // The list of apn's associated with this DataConnection
             Collection<ApnContext> apns = dcac.getApnListSync();
 
-            // filter out ApnContext with "Connected/Connecting" state.
+            // Find which ApnContexts of this DC are in the "Connected/Connecting" state.
             ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
             for (ApnContext apnContext : apns) {
                 if (apnContext.getState() == State.CONNECTED ||
@@ -1125,67 +1138,86 @@
                     connectedApns.add(apnContext);
                 }
             }
-
-            // No "Connected" ApnContext associated with this CID. Ignore.
-            if (connectedApns.isEmpty()) {
-                continue;
-            }
-
-            if (DBG) log("onDataStateChanged(ar): Found ConnId=" + newState.cid
-                            + " newState=" + newState.toString());
-            if (newState.active != 0) {
-                boolean resetConnection;
-                switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
-                case NONE:
-                    if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
-                    resetConnection = false;
-                    break;
-                case CHANGED:
-                    for (ApnContext apnContext : connectedApns) {
-                        if (DBG) log("onDataStateChanged(ar): Found and changed, notify (" +
-                                     apnContext.toString() + ")");
-                        mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
-                                                    apnContext.getApnType());
+            if (connectedApns.size() == 0) {
+                if (DBG) log("onDataStateChanged(ar): no connected apns");
+            } else {
+                // Determine if the connection/apnContext should be cleaned up
+                // or just a notification should be sent out.
+                if (DBG) log("onDataStateChanged(ar): Found ConnId=" + newState.cid
+                        + " newState=" + newState.toString());
+                if (newState.active == 0) {
+                    if (DBG) {
+                        log("onDataStateChanged(ar): inactive, cleanup apns=" + connectedApns);
                     }
-                    // Temporary hack, at this time a transition from CDMA -> Global
-                    // fails so we'll hope for the best and not reset the connection.
-                    // @see bug/4455071
-                    if (SystemProperties.getBoolean("telephony.ignore-state-changes",
-                                                    true)) {
-                        log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
-                        resetConnection = false;
+                    apnsToCleanup.addAll(connectedApns);
+                } else {
+                    // Its active so update the DataConnections link properties
+                    UpdateLinkPropertyResult result =
+                        dcac.updateLinkPropertiesDataCallStateSync(newState);
+                    if (result.oldLp.equals(result.newLp)) {
+                        if (DBG) log("onDataStateChanged(ar): no change");
                     } else {
-                        // Things changed so reset connection, when hack is removed
-                        // this is the normal path.
-                        log("onDataStateChanged(ar): changed so resetting connection");
-                        resetConnection = true;
+                        if (result.oldLp.isIdenticalInterfaceName(result.newLp)) {
+                            if (! result.oldLp.isIdenticalDnses(result.newLp) ||
+                                    ! result.oldLp.isIdenticalRoutes(result.newLp) ||
+                                    ! result.oldLp.isIdenticalHttpProxy(result.newLp) ||
+                                    ! result.oldLp.isIdenticalAddresses(result.newLp)) {
+                                // If the same address type was removed and added we need to cleanup
+                                CompareResult<LinkAddress> car =
+                                    result.oldLp.compareAddresses(result.newLp);
+                                boolean needToClean = false;
+                                for (LinkAddress added : car.added) {
+                                    for (LinkAddress removed : car.removed) {
+                                        if (NetworkUtils.addressTypeMatches(removed.getAddress(),
+                                                added.getAddress())) {
+                                            needToClean = true;
+                                            break;
+                                        }
+                                    }
+                                }
+                                if (needToClean) {
+                                    if (DBG) {
+                                        log("onDataStateChanged(ar): addr change, cleanup apns=" +
+                                                connectedApns);
+                                    }
+                                    apnsToCleanup.addAll(connectedApns);
+                                } else {
+                                    if (DBG) log("onDataStateChanged(ar): simple change");
+                                    for (ApnContext apnContext : connectedApns) {
+                                         mPhone.notifyDataConnection(
+                                                 Phone.REASON_LINK_PROPERTIES_CHANGED,
+                                                 apnContext.getApnType());
+                                    }
+                                }
+                            } else {
+                                if (DBG) {
+                                    log("onDataStateChanged(ar): no changes");
+                                }
+                            }
+                        } else {
+                            if (DBG) {
+                                log("onDataStateChanged(ar): interface change, cleanup apns="
+                                        + connectedApns);
+                            }
+                            apnsToCleanup.addAll(connectedApns);
+                        }
                     }
-                    break;
-                case RESET:
-                default:
-                    if (DBG) log("onDataStateChanged(ar): an error, reset connection");
-                    resetConnection = true;
-                    break;
                 }
-                if (resetConnection == false) continue;
             }
-
-            if (DBG) log("onDataStateChanged(ar): reset connection.");
-
-            apnsToClear.addAll(connectedApns);
         }
 
-        // step3: Clear apn connection if applicable.
-        if (!apnsToClear.isEmpty()) {
+        if (apnsToCleanup.size() != 0) {
             // Add an event log when the network drops PDP
             int cid = getCellLocationId();
             EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
                                 TelephonyManager.getDefault().getNetworkType());
         }
 
-        for (ApnContext apnContext : apnsToClear) {
+        // Cleanup those dropped connections
+        for (ApnContext apnContext : apnsToCleanup) {
             cleanUpConnection(true, apnContext);
         }
+
         if (DBG) log("onDataStateChanged(ar): X");
     }
 
@@ -1813,7 +1845,11 @@
                         retryOverride =
                             ((DataConnection.CallSetupException)ar.exception).getRetryOverride();
                     }
-                    startDelayedRetry(cause, apnContext, retryOverride);
+                    if (retryOverride == RILConstants.MAX_INT) {
+                        if (DBG) log("No retry is suggested.");
+                    } else {
+                        startDelayedRetry(cause, apnContext, retryOverride);
+                    }
                 }
             } else {
                 if (DBG) log("onDataSetupComplete: Try next APN");
@@ -2001,20 +2037,18 @@
         return conn;
     }
 
-    private void configureRetry(DataConnection dc, String apnType) {
-        if ((dc == null) || (apnType == null)) return;
+    private void configureRetry(DataConnection dc, boolean forDefault) {
+        if (dc == null) return;
 
-        if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
-            if (!dc.configureRetry(SystemProperties.get("ro.gsm.data_retry_config"))) {
+        if (!dc.configureRetry(getReryConfig(forDefault))) {
+            if (forDefault) {
                 if (!dc.configureRetry(DEFAULT_DATA_RETRY_CONFIG)) {
                     // Should never happen, log an error and default to a simple linear sequence.
                     loge("configureRetry: Could not configure using " +
                             "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
                     dc.configureRetry(20, 2000, 1000);
                 }
-            }
-        } else {
-            if (!dc.configureRetry(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
+            } else {
                 if (!dc.configureRetry(SECONDARY_DATA_RETRY_CONFIG)) {
                     // Should never happen, log an error and default to a simple sequence.
                     loge("configureRetry: Could note configure using " +
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 93f4b4e..d3645fa 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -915,7 +915,7 @@
         }
 
         if (hasRadioTechnologyChanged) {
-            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL);
+            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED);
         }
 
         if (hasRoamingOn) {
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 9dfc015..5c4b446 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -264,6 +264,10 @@
         return null;
     }
 
+    public String getImei() {
+        return null;
+    }
+
     public String getEsn() {
         Log.e(LOG_TAG, "[SipPhone] getEsn() is a CDMA method");
         return "0";
diff --git a/tests/BiDiTests/Android b/tests/BiDiTests/Android
deleted file mode 100644
index e69de29..0000000
--- a/tests/BiDiTests/Android
+++ /dev/null
diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android-private.mk
similarity index 100%
rename from tests/BiDiTests/Android.mk
rename to tests/BiDiTests/Android-private.mk
diff --git a/tests/BiDiTests/new-attributes.txt b/tests/BiDiTests/new-attributes.txt
new file mode 100644
index 0000000..57854cc
--- /dev/null
+++ b/tests/BiDiTests/new-attributes.txt
@@ -0,0 +1,9 @@
+  <public type="attr" name="layoutDirection" />
+
+  <public type="attr" name="layout_marginStart"/>
+  <public type="attr" name="layout_marginEnd"/>
+
+  <public type="attr" name="paddingStart"/>
+  <public type="attr" name="paddingEnd"/>
+
+  <public type="attr" name="textDirection"/>
diff --git a/tests/BiDiTests/res/drawable/alphabet_a.png b/tests/BiDiTests/res/drawable/alphabet_a.png
new file mode 100644
index 0000000..2a80ec1
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_a.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_b.png b/tests/BiDiTests/res/drawable/alphabet_b.png
new file mode 100644
index 0000000..ac887ad
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_b.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_c.png b/tests/BiDiTests/res/drawable/alphabet_c.png
new file mode 100644
index 0000000..f8cc5c6
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_c.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_d.png b/tests/BiDiTests/res/drawable/alphabet_d.png
new file mode 100644
index 0000000..764dfe5
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_d.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_e.png b/tests/BiDiTests/res/drawable/alphabet_e.png
new file mode 100644
index 0000000..dbd00e1
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_e.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_f.png b/tests/BiDiTests/res/drawable/alphabet_f.png
new file mode 100644
index 0000000..f6a1bbe
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_f.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_g.png b/tests/BiDiTests/res/drawable/alphabet_g.png
new file mode 100644
index 0000000..e9d360c
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_g.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_h.png b/tests/BiDiTests/res/drawable/alphabet_h.png
new file mode 100644
index 0000000..cbc4eb1
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_h.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_i.png b/tests/BiDiTests/res/drawable/alphabet_i.png
new file mode 100644
index 0000000..bae2103
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_i.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/alphabet_j.png b/tests/BiDiTests/res/drawable/alphabet_j.png
new file mode 100644
index 0000000..264c6a7
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/alphabet_j.png
Binary files differ
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index d438b2c..ed91c49 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -40,7 +40,7 @@
                       android:textSize="32dip"
                       android:text="@string/textview_text"
                     />
-    
+
             <EditText android:id="@+id/edittext"
                       android:layout_height="wrap_content"
                       android:layout_width="match_parent"
@@ -49,6 +49,40 @@
 
         </LinearLayout>
 
+        <Button android:id="@+id/button_alert_dialog"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/button_alert_dialog_text"
+                android:textSize="32dip"
+                />
     </LinearLayout>
 
-</FrameLayout>
\ No newline at end of file
+    <LinearLayout
+        android:layout_width="600dip"
+        android:layout_height="128dip"
+        android:layout_gravity="center_vertical"
+        android:orientation="horizontal"
+        style="@android:style/Widget.Holo.Spinner"
+        >
+        <LinearLayout
+            android:layout_width="0dip"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical"
+            android:orientation="vertical"
+            >
+            <TextView
+                android:id="@+id/spinner_line_1"
+                android:layout_width="match_parent"
+                android:layout_height="0dip"
+                android:layout_weight="1"
+                android:textSize="16dip"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:gravity="left|center_vertical"
+                android:text="@string/button_text"
+                />
+        </LinearLayout>
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/canvas2.xml b/tests/BiDiTests/res/layout/canvas2.xml
new file mode 100644
index 0000000..b3e038f
--- /dev/null
+++ b/tests/BiDiTests/res/layout/canvas2.xml
@@ -0,0 +1,66 @@
+<?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/canvas2"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+
+    <LinearLayout
+        xmlns:local="http://schemas.android.com/apk/res/com.android.bidi"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+
+        <TextView
+            android:text="@string/ltr"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content" />
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/ltr"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+        <TextView
+            android:text="@string/rtl"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"/>
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/rtl"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+        <TextView
+            android:text="@string/composing"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"/>
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/composing"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/tests/BiDiTests/res/layout/gallery_ltr.xml
similarity index 60%
copy from core/res/res/layout/text_edit_suggestions_bottom_window.xml
copy to tests/BiDiTests/res/layout/gallery_ltr.xml
index 588bfbd..d0e4168 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/tests/BiDiTests/res/layout/gallery_ltr.xml
@@ -4,9 +4,9 @@
      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.
@@ -14,10 +14,17 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/gallery_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
 
-</LinearLayout>
+    <Gallery
+        android:id="@+id/galleryview"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:spacing="10dip"
+        />
+
+</FrameLayout>
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/tests/BiDiTests/res/layout/gallery_rtl.xml
similarity index 60%
copy from core/res/res/layout/text_edit_suggestions_bottom_window.xml
copy to tests/BiDiTests/res/layout/gallery_rtl.xml
index 588bfbd..c5c2f5c 100644
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ b/tests/BiDiTests/res/layout/gallery_rtl.xml
@@ -4,9 +4,9 @@
      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.
@@ -14,10 +14,17 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/gallery_rtl"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="rtl">
 
-</LinearLayout>
+    <Gallery
+        android:id="@+id/galleryview"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:spacing="10dip"
+        />
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_direction_ltr.xml b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
index f7b7b8e..2c790ec 100644
--- a/tests/BiDiTests/res/layout/textview_direction_ltr.xml
+++ b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
@@ -18,95 +18,232 @@
         android:id="@+id/textview_direction_ltr"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
-        android:layoutDirection="ltr">
+        android:layoutDirection="ltr"
+        android:textDirection="ltr">
 
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:textDirection="ltr">
-
-        <LinearLayout android:orientation="vertical"
+        <TableLayout 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>
+            <TableRow>
+                <TextView android:text="(unspecified)"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-        <LinearLayout android:orientation="vertical"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content">
+            <TableRow>
+                <TextView android:text="inherit"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-            <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>
+            <TableRow>
+                <TextView android:text="firstStrong"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-    </LinearLayout>
+            <TableRow>
+                <TextView android:text="anyRtl"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-</FrameLayout>
\ No newline at end of file
+            <TableRow>
+                <TextView android:text="ltr"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="rtl"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+        </TableLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_direction_rtl.xml b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
index 81c5411..1df100d 100644
--- a/tests/BiDiTests/res/layout/textview_direction_rtl.xml
+++ b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
@@ -18,95 +18,232 @@
         android:id="@+id/textview_direction_rtl"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
-        android:layoutDirection="rtl">
+        android:layoutDirection="rtl"
+        android:textDirection="rtl">
 
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:textDirection="rtl">
-
-        <LinearLayout android:orientation="vertical"
+        <TableLayout 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>
+            <TableRow>
+                <TextView android:text="(unspecified)"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-        <LinearLayout android:orientation="vertical"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content">
+            <TableRow>
+                <TextView android:text="inherit"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-            <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>
+            <TableRow>
+                <TextView android:text="firstStrong"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="firstStrong"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-    </LinearLayout>
+            <TableRow>
+                <TextView android:text="anyRtl"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="anyRtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
 
-</FrameLayout>
\ No newline at end of file
+            <TableRow>
+                <TextView android:text="ltr"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="ltr"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="rtl"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_hebrew_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_latin_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="wrap_content"
+                          android:textSize="24dip"
+                          android:text="@string/textview_multiline_text"
+                          android:textDirection="rtl"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+        </TableLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/values/attrs.xml b/tests/BiDiTests/res/values/attrs.xml
new file mode 100644
index 0000000..7f8a1d8
--- /dev/null
+++ b/tests/BiDiTests/res/values/attrs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="DrawTextTestView">
+        <attr name="size" format="dimension" />
+        <attr name="color" format="color" />
+        <attr name="text" format="string" />
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index c0bbe94..1f6be7f 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -23,6 +23,7 @@
     <string name="button_left_text">Left</string>
     <string name="button_before_text">Start</string>
     <string name="button_requestlayout_text">Request Layout</string>
+    <string name="button_alert_dialog_text">AlertDialog</string>
     <string name="textview_text">This is a text for a TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
     <string name="normal_text">Normal String</string>
@@ -40,6 +41,9 @@
     <string name="menu_delete">Delete</string>
     <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
     <string name="textview_latin_text">ab&#x05DD;&#x05DE;?!</string>
-    <string name="textview_multiline_text">&#x05DD;&#x05DE;?!\nab?!</string>
+    <string name="textview_multiline_text">&#x05DD;&#x05DE;?!\nab?!\n?!</string>
+    <string name="ltr">Left to right text"</string>
+    <string name="rtl">"والحق أن تترك ونص"</string>
+    <string name="composing">"\u0644\u0627"</string>
 </resources>
 
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index 7002c41..b45b98f 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -102,6 +102,7 @@
         addItem(result, "Basic", BiDiTestBasic.class, R.id.basic);
 
         addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
+        addItem(result, "Canvas2", BiDiTestCanvas2.class, R.id.canvas2);
 
         addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
         addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
@@ -136,6 +137,8 @@
 
         addItem(result, "TextView Drawables LTR", BiDiTestTextViewDrawablesLtr.class, R.id.textview_drawables_ltr);
         addItem(result, "TextView Drawables RTL", BiDiTestTextViewDrawablesRtl.class, R.id.textview_drawables_rtl);
+        addItem(result, "Gallery LTR", BiDiTestGalleryLtr.class, R.id.gallery_ltr);
+        addItem(result, "Gallery RTL", BiDiTestGalleryRtl.class, R.id.gallery_rtl);
 
         return result;
     }
@@ -146,4 +149,4 @@
         inflater.inflate(R.menu.main_menu, menu);
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java
index 9b3918d..f0b7438 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java
@@ -16,17 +16,42 @@
 
 package com.android.bidi;
 
+import android.app.AlertDialog;
 import android.app.Fragment;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 
 public class BiDiTestBasic extends Fragment {
-    
+
+    private View currentView;
+    private Button alertDialogButton;
+    private String[] items = {"This is a very very very very very very very very very very very long Item1", "Item2"};
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.basic, container, false);
+        currentView = inflater.inflate(R.layout.basic, container, false);
+        return currentView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        alertDialogButton = (Button) currentView.findViewById(R.id.button_alert_dialog);
+        alertDialogButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                showDialog();
+            }
+        });
+    }
+
+    private void showDialog() {
+        AlertDialog.Builder builder = new AlertDialog.Builder(currentView.getContext());
+        builder.setSingleChoiceItems(items, 0, null);
+        builder.show();
     }
 }
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java
new file mode 100644
index 0000000..b801f0e
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+import android.widget.SeekBar;
+
+import static com.android.bidi.BiDiTestConstants.FONT_MAX_SIZE;
+import static com.android.bidi.BiDiTestConstants.FONT_MIN_SIZE;
+
+public class BiDiTestCanvas2 extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.canvas2, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryImages.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryImages.java
new file mode 100644
index 0000000..adc17e1
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryImages.java
@@ -0,0 +1,68 @@
+/*
+ * 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.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+
+public class BiDiTestGalleryImages extends BaseAdapter {
+    int mGalleryItemBackground;
+    private Context mContext;
+
+    private Integer[] mImageIds = {
+            R.drawable.alphabet_a,
+            R.drawable.alphabet_b,
+            R.drawable.alphabet_c,
+            R.drawable.alphabet_d,
+            R.drawable.alphabet_e,
+            R.drawable.alphabet_f,
+            R.drawable.alphabet_g,
+            R.drawable.alphabet_h,
+            R.drawable.alphabet_i,
+            R.drawable.alphabet_j,
+    };
+
+    public BiDiTestGalleryImages(Context c) {
+        mContext = c;
+    }
+
+    @Override
+    public int getCount() {
+        return mImageIds.length;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return position;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ImageView i = new ImageView(mContext);
+        i.setImageResource(mImageIds[position]);
+        i.setScaleType(ScaleType.CENTER_INSIDE);
+        return i;
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryLtr.java
new file mode 100644
index 0000000..fa86b1a
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryLtr.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Gallery;
+
+public class BiDiTestGalleryLtr extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        View v = inflater.inflate(R.layout.gallery_ltr, container, false);
+        Gallery g = (Gallery) v.findViewById(R.id.galleryview);
+        g.setAdapter(new BiDiTestGalleryImages(this.getActivity().getBaseContext()));
+        return v;
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryRtl.java
new file mode 100644
index 0000000..4cef658
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGalleryRtl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Gallery;
+
+public class BiDiTestGalleryRtl extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        View v = inflater.inflate(R.layout.gallery_rtl, container, false);
+        Gallery g = (Gallery) v.findViewById(R.id.galleryview);
+        g.setAdapter(new BiDiTestGalleryImages(this.getActivity().getBaseContext()));
+        return v;
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
index 4f17e52..0126dea 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
@@ -21,7 +21,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.Typeface;
+import android.text.TextPaint;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -37,7 +37,6 @@
 
     private static final float DEFAULT_ITALIC_SKEW_X = -0.25f;
 
-    private Paint paint = new Paint();
     private Rect rect = new Rect();
 
     private String NORMAL_TEXT;
@@ -51,8 +50,7 @@
     private String CHINESE_TEXT;
     private String MIXED_TEXT_1;
     private String HEBREW_TEXT;
-
-    private Typeface typeface;
+    private String RTL_TEXT;
 
     private int currentTextSize;
 
@@ -83,9 +81,7 @@
         CHINESE_TEXT = context.getString(R.string.chinese_text);
         MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
         HEBREW_TEXT = context.getString(R.string.hebrew_text);
-
-        typeface = paint.getTypeface();
-        paint.setAntiAlias(true);
+        RTL_TEXT = context.getString(R.string.rtl);
     }
 
     public void setCurrentTextSize(int size) {
@@ -95,54 +91,56 @@
 
     @Override
     public void onDraw(Canvas canvas) {
-        drawInsideRect(canvas, Color.BLACK);
+        drawInsideRect(canvas, new Paint(), Color.BLACK);
 
         int deltaX = 0;
 
         deltaX  = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, true, false,  Paint.DIRECTION_LTR, currentTextSize);
+                true, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, false, true,  Paint.DIRECTION_LTR, currentTextSize);
+                false, true,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, true, true,  Paint.DIRECTION_LTR, currentTextSize);
+                true, true,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Arabic ligature
         deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_RTL, currentTextSize);
+                false, false,  Paint.DIRECTION_RTL, currentTextSize);
 
         // Test Chinese
         deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Mixed (English and Arabic)
         deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Hebrew
-        deltaX = testString(canvas, HEBREW_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_RTL, currentTextSize);
+        deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
+                false, false,  Paint.DIRECTION_RTL, currentTextSize);
     }
 
-    private int testString(Canvas canvas, String text, int x, int y, Paint paint, Typeface typeface,
+    private int testString(Canvas canvas, String text, int x, int y,
             boolean isItalic, boolean isBold, int dir, int textSize) {
-        paint.setTypeface(typeface);
+
+        TextPaint paint = new TextPaint();
+        paint.setAntiAlias(true);
 
         // Set paint properties
         boolean oldFakeBold = paint.isFakeBoldText();
@@ -153,9 +151,9 @@
             paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
         }
 
-        Log.v(TAG, "START -- drawTextWithCanvasDrawText");
-        drawTextWithCanvasDrawText(text, canvas, x, y, textSize, Color.WHITE, dir);
-        Log.v(TAG, "END   -- drawTextWithCanvasDrawText");
+        paint.setTextSize(textSize);
+        paint.setColor(Color.WHITE);
+        canvas.drawText(text, x, y, paint);
 
         int length = text.length();
         float[] advances = new float[length];
@@ -167,17 +165,6 @@
         logAdvances(text, textWidthHB, textWidthICU, advances);
         drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
 
-        paint.setColor(Color.WHITE);
-//        char[] glyphs = new char[2*length];
-//        int count = getGlyphs(text, glyphs, dir);
-//
-//        logGlypths(glyphs, count);
-//        drawTextWithDrawGlyph(canvas, glyphs, count, x, y + currentTextSize);
-
-        Log.v(TAG, "START -- drawTextWithGlyphs");
-        drawTextWithGlyphs(canvas, text, x, y + currentTextSize, dir);
-        Log.v(TAG, "END   -- drawTextWithGlyphs");
-
         // Restore old paint properties
         paint.setFakeBoldText(oldFakeBold);
         paint.setTextSkewX(oldTextSkewX);
@@ -190,27 +177,7 @@
         paint.setBidiFlags(dir);
     }
 
-    private void drawTextWithDrawGlyph(Canvas canvas, char[] glyphs, int count, int x, int y) {
-        canvas.drawGlyphs(glyphs, 0, count, x, y, paint);
-    }
-
-    private void drawTextWithGlyphs(Canvas canvas, String text, int x, int y, int dir) {
-        setPaintDir(paint, dir);
-        canvas.drawTextWithGlyphs(text, x, y, paint);
-    }
-
-    private void logGlypths(char[] glyphs, int count) {
-        Log.v(TAG, "GlyphIds - count=" + count);
-        for (int n = 0; n < count; n++) {
-            Log.v(TAG, "GlyphIds - Id[" + n + "]="+ (int)glyphs[n]);
-        }
-    }
-
-    private int getGlyphs(String text, char[] glyphs, int dir) {
-        return paint.getTextGlypths(text, 0, text.length(), 0, text.length(), dir, glyphs);
-    }
-
-    private void drawInsideRect(Canvas canvas, int color) {
+    private void drawInsideRect(Canvas canvas, Paint paint, int color) {
         paint.setColor(color);
         int width = getWidth();
         int height = getHeight();
@@ -218,16 +185,9 @@
         canvas.drawRect(rect, paint);
     }
 
-    private void drawTextWithCanvasDrawText(String text, Canvas canvas,
-            float x, float y, float textSize, int color, int dir) {
-        setPaintDir(paint, dir);
-        paint.setColor(color);
-        paint.setTextSize(textSize);
-        canvas.drawText(text, x, y, paint);
-    }
-
     private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
             float textWidthICU, int textSize, int color, int colorICU) {
+        Paint paint = new Paint();
         paint.setColor(color);
         canvas.drawLine(x, y - textSize, x, y + 8, paint);
         canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java
new file mode 100644
index 0000000..dfdb807
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java
@@ -0,0 +1,66 @@
+/*
+ * 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.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint.Align;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class BiDiTestViewDrawText extends View {
+    private float mSize;
+    private int mColor;
+    private String mText;
+
+    public BiDiTestViewDrawText(Context context) {
+        this(context, null);
+    }
+
+    public BiDiTestViewDrawText(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public BiDiTestViewDrawText(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.DrawTextTestView, defStyle, 0);
+        mSize = a.getDimension(R.styleable.DrawTextTestView_size, 40.0f);
+        mColor = a.getColor(R.styleable.DrawTextTestView_color, Color.YELLOW);
+        final CharSequence text = a.getText(R.styleable.DrawTextTestView_text);
+        mText = (text != null) ? text.toString() : "(empty)";
+        a.recycle();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        final int width = getWidth();
+        final int height = getHeight();
+
+        final TextPaint paint = new TextPaint();
+        paint.setTextSize(mSize);
+        paint.setColor(mColor);
+        paint.setTextAlign(Align.CENTER);
+
+        canvas.drawText(mText, width / 2, height * 2 / 3, paint);
+    }
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index f8c32dd..41e44cb 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -159,7 +159,7 @@
         // Expose window.gc function to JavaScript. JSC build exposes
         // this function by default, but V8 requires the flag to turn it on.
         // WebView::setJsFlags is noop in JSC build.
-        mWebView.setJsFlags("--expose_gc");
+        mWebView.setJsFlags("--expose_gc --crankshaft=false");
 
         mHandler = new AsyncHandler();
 
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index 3c2db54..2eca384 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -27,8 +27,8 @@
         >
 
     <TextView
-            android:text="Email account"
-            android:textSize="48dip"
+            android:text="Email setup"
+            android:textSize="32dip"
 
             android:layout_columnSpan="4"
             android:layout_gravity="center_horizontal"
@@ -36,7 +36,7 @@
 
     <TextView
             android:text="You can configure email in just a few steps:"
-            android:textSize="20dip"
+            android:textSize="16dip"
 
             android:layout_columnSpan="4"
             android:layout_gravity="left"
@@ -49,7 +49,7 @@
             />
 
     <EditText
-            android:layout_width="100dip"
+            android:layout_width="64dip"
             />
 
     <TextView
@@ -60,14 +60,14 @@
             />
 
     <EditText
-            android:layout_width="50dip"
+            android:layout_width="32dip"
             />
 
     <Space
             android:layout_row="4"
             android:layout_column="2"
-            android:layout_rowFlexibility="canStretch"
-            android:layout_columnFlexibility="canStretch"
+            android:layout_margin="0dip"
+            android:layout_gravity="fill"
             />
 
     <Button
@@ -75,7 +75,6 @@
 
             android:layout_row="5"
             android:layout_column="3"
-            android:layout_gravity="fill_horizontal"
             />
 
     <Button
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index b9bf526..e1871ac 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -38,30 +38,31 @@
         vg.setUseDefaultMargins(true);
         vg.setAlignmentMode(ALIGN_BOUNDS);
 
-        Group row1 = new Group(1, CENTER);
-        Group row2 = new Group(2, CENTER);
-        Group row3 = new Group(3, BASELINE);
-        Group row4 = new Group(4, BASELINE);
-        Group row5 = new Group(5, FILL);
-        Group row6 = new Group(6, CENTER);
-        Group row7 = new Group(7, CENTER);
+        Spec row1 = spec(0);
+        Spec row2 = spec(1);
+        Spec row3 = spec(2, BASELINE);
+        Spec row4 = spec(3, BASELINE);
+        Spec row5 = spec(4, FILL);
+        Spec row6 = spec(5);
+        Spec row7 = spec(6);
 
-        Group col1a = new Group(1, 4, CENTER);
-        Group col1b = new Group(1, 4, LEFT);
-        Group col1c = new Group(1, RIGHT);
-        Group col2 = new Group(2, LEFT);
-        Group col3 = new Group(3, FILL);
-        Group col4 = new Group(4, FILL);
+        Spec col1a = spec(0, 4, CENTER);
+        Spec col1b = spec(0, 4, LEFT);
+        Spec col1c = spec(0, RIGHT);
+        Spec col2 = spec(1, LEFT);
+        Spec col3 = spec(2, FILL);
+        Spec col4a = spec(3);
+        Spec col4b = spec(3, FILL);
 
         {
             TextView v = new TextView(context);
-            v.setTextSize(48);
+            v.setTextSize(32);
             v.setText("Email setup");
             vg.addView(v, new LayoutParams(row1, col1a));
         }
         {
             TextView v = new TextView(context);
-            v.setTextSize(20);
+            v.setTextSize(16);
             v.setText("You can configure email in just a few steps:");
             vg.addView(v, new LayoutParams(row2, col1b));
         }
@@ -75,7 +76,7 @@
             v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
             {
                 LayoutParams lp = new LayoutParams(row3, col2);
-                lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone@bedrock.com    ");
+                lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone");
                 vg.addView(v, lp);
             }
         }
@@ -95,22 +96,19 @@
         }
         {
             Space v = new Space(context);
-            {
-                LayoutParams lp = new LayoutParams(row5, col3);
-                lp.columnGroup.flexibility = CAN_STRETCH;
-                lp.rowGroup.flexibility = CAN_STRETCH;
-                vg.addView(v, lp);
-            }
+            LayoutParams lp = new LayoutParams(row5, col3);
+            lp.setMargins(0, 0, 0, 0);
+            vg.addView(v, lp);
         }
         {
             Button v = new Button(context);
             v.setText("Manual setup");
-            vg.addView(v, new LayoutParams(row6, col4));
+            vg.addView(v, new LayoutParams(row6, col4a));
         }
         {
             Button v = new Button(context);
             v.setText("Next");
-            vg.addView(v, new LayoutParams(row7, col4));
+            vg.addView(v, new LayoutParams(row7, col4b));
         }
 
         return vg;
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java b/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java
index 505c83d..b1c4486 100755
--- a/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java
@@ -21,7 +21,6 @@
 import android.os.Bundle;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.GridLayout;
@@ -84,9 +83,7 @@
             Alignment va = VERTICAL_ALIGNMENTS[i];
             for (int j = 0; j < HORIZONTAL_ALIGNMENTS.length; j++) {
                 Alignment ha = HORIZONTAL_ALIGNMENTS[j];
-                Group rowGroup = new Group(i, va);
-                Group colGroup = new Group(j, ha);
-                LayoutParams layoutParams = new LayoutParams(rowGroup, colGroup);
+                LayoutParams layoutParams = new LayoutParams(spec(i, va), spec(j, ha));
                 String name = VERTICAL_NAMES[i] + "-" + HORIZONTAL_NAMES[j];
                 ViewFactory factory = FACTORIES[(i + j) % FACTORIES.length];
                 container.addView(factory.create(name, 20), layoutParams);
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java b/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java
index c5681e2..4ce449ac 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java
@@ -33,9 +33,9 @@
             int va = VERTICAL_ALIGNMENTS[i];
             for (int j = 0; j < HORIZONTAL_ALIGNMENTS.length; j++) {
                 int ha = HORIZONTAL_ALIGNMENTS[j];
-                GridLayout.Group rowGroup = new GridLayout.Group(UNDEFINED, null);
-                GridLayout.Group colGroup = new GridLayout.Group(UNDEFINED, null);
-                GridLayout.LayoutParams lp = new GridLayout.LayoutParams(rowGroup, colGroup);
+                Spec rowSpec = spec(UNDEFINED, null);
+                Spec colSpec = spec(UNDEFINED, null);
+                GridLayout.LayoutParams lp = new GridLayout.LayoutParams(rowSpec, colSpec);
                 //GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
                 lp.setGravity(va | ha);
                 View v = create(context, VERTICAL_NAMES[i] + "-" + HORIZONTAL_NAMES[j], 20);
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 32a6a65..9fcd05a 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -94,6 +94,15 @@
         </activity>
 
         <activity
+                android:name="CanvasTextureViewActivity"
+                android:label="_CanvasTextureView">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="GLTextureViewActivity"
                 android:label="_TextureViewGL">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/layout/list_activity.xml b/tests/HwAccelerationTest/res/layout/list_activity.xml
index 6bba370..1a5d3d9 100644
--- a/tests/HwAccelerationTest/res/layout/list_activity.xml
+++ b/tests/HwAccelerationTest/res/layout/list_activity.xml
@@ -30,8 +30,10 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="10dip"
             android:layout_marginRight="3dip"
+            
+            android:onClick="startProfiling"
 
-            android:text="Add" />
+            android:text="Start" />
         
         <Button
             android:layout_width="0dip"
@@ -39,8 +41,10 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="3dip"
             android:layout_marginRight="10dip"
+            
+            android:onClick="stopProfiling"
 
-            android:text="Remove" />
+            android:text="Stop" />
         
     </LinearLayout>
     
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java
new file mode 100644
index 0000000..81c22b8
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java
@@ -0,0 +1,120 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.TextureView;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class CanvasTextureViewActivity extends Activity
+        implements TextureView.SurfaceTextureListener {
+    private TextureView mTextureView;
+    private CanvasTextureViewActivity.RenderingThread mThread;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FrameLayout content = new FrameLayout(this);
+
+        mTextureView = new TextureView(this);
+        mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOpaque(false);
+
+        content.addView(mTextureView, new FrameLayout.LayoutParams(500, 500, Gravity.CENTER));
+        setContentView(content);
+    }
+
+    @Override
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        mThread = new RenderingThread(mTextureView);
+        mThread.start();
+    }
+
+    @Override
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        // Ignored
+    }
+
+    @Override
+    public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        if (mThread != null) mThread.stopRendering();
+    }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Ignored
+    }
+
+    private static class RenderingThread extends Thread {
+        private final TextureView mSurface;
+        private volatile boolean mRunning = true;
+
+        public RenderingThread(TextureView surface) {
+            mSurface = surface;
+        }
+
+        @Override
+        public void run() {
+            float x = 0.0f;
+            float y = 0.0f;
+            float speedX = 5.0f;
+            float speedY = 3.0f;
+            
+            Paint paint = new Paint();
+            paint.setColor(0xff00ff00);
+
+            while (mRunning && !Thread.interrupted()) {
+                final Canvas canvas = mSurface.lockCanvas(null);
+                try {
+                    canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
+                    canvas.drawRect(x, y, x + 20.0f, y + 20.0f, paint);
+                } finally {
+                    mSurface.unlockCanvasAndPost(canvas);
+                }
+
+                if (x + 20.0f + speedX >= mSurface.getWidth() || x + speedX <= 0.0f) {
+                    speedX = -speedX;
+                }
+                if (y + 20.0f + speedY >= mSurface.getHeight() || y + speedY <= 0.0f) {
+                    speedY = -speedY;
+                }
+
+                x += speedX;
+                y += speedY;
+
+                try {
+                    Thread.sleep(15);
+                } catch (InterruptedException e) {
+                    // Interrupted
+                }
+            }
+        }
+        
+        void stopRendering() {
+            interrupt();
+            mRunning = false;
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 8fd4f6b..13b6129 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -20,15 +20,19 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.Environment;
 import android.util.DisplayMetrics;
 import android.view.ContextMenu;
 import android.view.View;
+import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
+import java.io.File;
+
 @SuppressWarnings({"UnusedDeclaration"})
 public class ListActivity extends Activity {
     private static final String[] DATA_LIST = {
@@ -87,6 +91,12 @@
         
         registerForContextMenu(list);
     }
+    
+    public void startProfiling(View v) {
+    }
+    
+    public void stopProfiling(View v) {
+    }
 
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index e776463..9aa70b0 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -87,8 +87,6 @@
                     mIsProcessing = false;
                 }
 
-                // This is a hack to work around an invalidation bug
-                mBitmapOut.setPixel(0, 0, 0);
                 mOutPixelsAllocation.copyTo(mBitmapOut);
                 mDisplayView.invalidate();
             }
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
index 16ebe08..d93238c 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -84,10 +84,10 @@
     fs.radius = radius;
 
     fs.ain = rsGetAllocation(ScratchPixel1);
-    rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs);
+    rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
 
     fs.ain = rsGetAllocation(ScratchPixel2);
-    rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs);
+    rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
     rsSendToClientBlocking(CMD_FINISHED);
 }
 
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
index f046952..5c5b1c9 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
@@ -60,7 +60,7 @@
     robot2Ptr->transforms[1].w += 2.5f;
     robot2Ptr->isDirty = 1;
 
-    rsForEach(gTransformRS, gRootNode->children, gRootNode->children, 0);
+    rsForEach(gTransformRS, gRootNode->children, gRootNode->children);
 
     rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
     rsgClearDepth(1.0f);
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
index f328025..85c0630 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
@@ -91,6 +91,6 @@
 
     //rsDebug("Transform calling self with child ", (int)data->children.p);
     if (data->children.p) {
-        rsForEach(transformScript, data->children, data->children, (void*)&toChild);
+        rsForEach(transformScript, data->children, data->children, (void*)&toChild, sizeof(toChild));
     }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index eaafe1d..db97835 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -280,7 +280,7 @@
     testData.renderSurfaceW = gRenderSurfaceW;
     testData.renderSurfaceH = gRenderSurfaceH;
     testData.user = fillNum;
-    rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData);
+    rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
 }
 
 static void bindProgramVertexOrtho() {
@@ -520,7 +520,7 @@
     testData.user = 0;
     testData.user1 = useTexture ? 1 : 0;
     testData.user2 = numMeshes;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
 }
 
 static void displayCustomShaderSamples(int numMeshes) {
@@ -530,7 +530,7 @@
     testData.dt = gDt;
     testData.user = 1;
     testData.user1 = numMeshes;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
 }
 
 static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
@@ -541,7 +541,7 @@
     testData.user = 2;
     testData.user1 = numMeshes;
     testData.user2 = heavyVertex ? 1 : 0;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
 }
 
 static void displayMultitextureSample(bool blend, int quadCount) {
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index b212533..e75a079 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -100,22 +100,22 @@
         new Test("Double Remove") {
             public void run() {
                 Log.d(TAG, "set 0");
-                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null);
                 Log.d(TAG, "remove 1");
                 mStatusBarManager.removeIcon("tty");
 
                 SystemClock.sleep(1000);
 
                 Log.d(TAG, "set 1");
-                mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null);
                 if (false) {
                     Log.d(TAG, "set 2");
-                    mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0);
+                    mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null);
                 }
                 Log.d(TAG, "remove 2");
                 mStatusBarManager.removeIcon("tty");
                 Log.d(TAG, "set 3");
-                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null);
             }
         },
         new Test("Hide (FLAG_FULLSCREEN)") {
diff --git a/tests/TileBenchmark/Android.mk b/tests/TileBenchmark/Android.mk
new file mode 100644
index 0000000..430f0f1
--- /dev/null
+++ b/tests/TileBenchmark/Android.mk
@@ -0,0 +1,32 @@
+# 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_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := TileBenchmark
+
+include $(BUILD_PACKAGE)
+
+##################################################
+include $(CLEAR_VARS)
+
+include $(BUILD_MULTI_PREBUILT)
+
+# Use the folloing include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/TileBenchmark/AndroidManifest.xml b/tests/TileBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..ab61a9e
--- /dev/null
+++ b/tests/TileBenchmark/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      android:versionCode="1"
+      android:versionName="1.0" package="com.test.tilebenchmark">
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <application android:icon="@drawable/icon"
+                 android:label="@string/app_name"
+                 android:hardwareAccelerated="true">
+        <activity android:name=".ProfileActivity"
+                  android:label="@string/profile_activity"
+                  android:theme="@android:style/Theme.Holo.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".PlaybackActivity"
+                  android:label="@string/playback_activity"
+                  android:theme="@android:style/Theme.Holo.NoActionBar">
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/TileBenchmark/res/drawable-hdpi/icon.png b/tests/TileBenchmark/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/drawable-ldpi/icon.png b/tests/TileBenchmark/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584e
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/drawable-mdpi/icon.png b/tests/TileBenchmark/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/layout/main.xml b/tests/TileBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..577c466
--- /dev/null
+++ b/tests/TileBenchmark/res/layout/main.xml
@@ -0,0 +1,66 @@
+<?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:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <LinearLayout
+        android:id="@+id/top"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        >
+        <Spinner
+            android:id="@+id/movement"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:prompt="@string/movement_method"
+            />
+        <Spinner
+            android:id="@+id/velocity"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:prompt="@string/desired_scroll_velocity"
+            />
+        <ToggleButton
+            android:id="@+id/capture"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textOn="@string/capture_stop"
+            android:textOff="@string/capture_start"
+            />
+        <EditText
+            android:id="@+id/url"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:inputType="textUri"
+            android:imeOptions="actionGo"
+            android:layout_weight="1"
+            />
+        <Button
+            android:id="@+id/inspect"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/inspect_log"
+            />
+    </LinearLayout>
+    <com.test.tilebenchmark.ProfiledWebView
+        android:id="@+id/web"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+</LinearLayout>
diff --git a/tests/TileBenchmark/res/layout/playback.xml b/tests/TileBenchmark/res/layout/playback.xml
new file mode 100644
index 0000000..aa1c8a4
--- /dev/null
+++ b/tests/TileBenchmark/res/layout/playback.xml
@@ -0,0 +1,58 @@
+<?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:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <LinearLayout
+        android:id="@+id/top"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        >
+        <Button
+            android:id="@+id/backward"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/backward"
+            />
+        <TextView
+            android:id="@+id/frame_display"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:layout_weight="1"
+            />
+        <Button
+            android:id="@+id/forward"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/forward"
+            />
+        <SeekBar
+            android:id="@+id/seek_bar"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="10"
+            />
+    </LinearLayout>
+    <com.test.tilebenchmark.PlaybackView
+        android:id="@+id/playback"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+</LinearLayout>
diff --git a/tests/TileBenchmark/res/values/colors.xml b/tests/TileBenchmark/res/values/colors.xml
new file mode 100644
index 0000000..dbb8e72
--- /dev/null
+++ b/tests/TileBenchmark/res/values/colors.xml
@@ -0,0 +1,34 @@
+<?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>
+    <!-- The color of tiles with valid textures -->
+    <color name="ready_tile">#ff4ac230</color>
+    <!-- The color of tiles with stale / invalid textures -->
+    <color name="unready_tile">#ff744400</color>
+    <!-- Viewport overlay in playback -->
+    <color name="view">#50000050</color>
+    <!-- Invalidated region overlay in playback - start color -->
+    <color name="inval_region_start">#80ff0000</color>
+    <!-- Invalidated region overlay in playback - stop color-->
+    <color name="inval_region_stop">#80ffffff</color>
+
+    <!-- Background color for not testing -->
+    <color name="background_not_testing">#ff000000</color>
+    <!-- Background color for during testing -->
+    <color name="background_start_testing">#ff400000</color>
+    <!-- Background color for testing complete -->
+    <color name="background_stop_testing">#ff004000</color>
+</resources>
diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml
new file mode 100644
index 0000000..66972ac
--- /dev/null
+++ b/tests/TileBenchmark/res/values/strings.xml
@@ -0,0 +1,89 @@
+<?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>
+    <!-- Button, steps back a single frame [CHAR LIMIT=15] -->
+    <string name="backward">Backward</string>
+    <!-- Button, steps forward a single frame [CHAR LIMIT=15] -->
+    <string name="forward">Forward</string>
+    <!-- The name of the application [CHAR LIMIT=20] -->
+    <string name="app_name">TileBenchmark</string>
+    <!-- name of the auto-scroller / tile logger activity [CHAR LIMIT=100] -->
+    <string name="profile_activity">Webview Profiler</string>
+    <!-- name of the tile log playback activity [CHAR LIMIT=100] -->
+    <string name="playback_activity">Webview Tile Playback</string>
+    <!-- Button, loads another tile log [CHAR LIMIT=30] -->
+    <string name="loadbutton">Load</string>
+    <!-- Button, opens the playback activity [CHAR LIMIT=20] -->
+    <string name="inspect_log">Inspect Log</string>
+    <!-- ToggleButton label when pressing starts capture [CHAR LIMIT=15] -->
+    <string name="capture_start">Start Capture</string>
+    <!-- ToggleButton label when pressing stops capture [CHAR LIMIT=15] -->
+    <string name="capture_stop">Stop Capture</string>
+    <!-- The speed of auto-scrolling [CHAR LIMIT=30] -->
+    <string name="desired_scroll_velocity">Choose Scroll Velocity</string>
+    <!-- Pixels moved per frame [CHAR LIMIT=10] -->
+    <string-array name="velocity_array">
+        <item>1</item>
+        <item>25</item>
+        <item>50</item>
+        <item>100</item>
+        <item>200</item>
+        <item>400</item>
+    </string-array>
+    <!-- Drop down menu for selecting scrolling vs manual navigation for
+    capturing [CHAR LIMIT=15] -->
+    <string name="movement_method">Movement Method</string>
+    <!-- Drop down menu entry - automatically scroll to the end of the page
+    with scrollBy() [CHAR LIMIT=15] -->
+    <string name="movement_auto_scroll">Auto-scroll</string>
+    <!-- Drop down menu entry -  [CHAR LIMIT=15] -->
+    <string name="movement_auto_fling">Auto-fling</string>
+    <!-- Drop down menu entry - manually navigate the page(s), hit 'capture'
+    button [CHAR LIMIT=15] -->
+    <string name="movement_manual">Manual</string>
+
+    <!-- Error popup indicating log data couldn't be loaded [CHAR LIMIT=60] -->
+    <string name="error_no_data">Error: log data could not be loaded.</string>
+
+    <!-- 25th percentile - 25% of frames fall below this value [CHAR LIMIT=12]
+    -->
+    <string name="percentile_25">25%ile</string>
+    <!-- 50th percentile - 50% of frames fall below this value (aka median)
+    [CHAR LIMIT=12] -->
+    <string name="percentile_50">median</string>
+    <!-- 75th percentile - 75% of frames fall below this value [CHAR LIMIT=12]
+    -->
+    <string name="percentile_75">75%ile</string>
+    <!-- Frame rate [CHAR LIMIT=15] -->
+    <string name="frames_per_second">Frames/sec</string>
+    <!-- Portion of viewport covered by good tiles [CHAR LIMIT=15] -->
+    <string name="viewport_coverage">Coverage</string>
+    <!-- Format string for stat value overlay [CHAR LIMIT=15] -->
+    <string name="format_stat">%4.4f</string>
+    <!-- Format string for displaying aggregate stats+values (nr of valid tiles,
+    etc.) [CHAR LIMIT=20] -->
+    <string name="format_stat_name">%1$-20s %2$3d</string>
+    <!-- Text hovering over canvas, number of tiles ready [CHAR LIMIT=15] -->
+    <string name="ready_tiles">Ready Tiles</string>
+    <!-- Text hovering over canvas, number tiles not ready [CHAR LIMIT=15] -->
+    <string name="unready_tiles">Unready Tiles</string>
+    <!-- Text hovering over canvas, number of tiles that haven't been
+    allocated to a place on the page [CHAR LIMIT=15] -->
+    <string name="unplaced_tiles">Unplaced Tiles</string>
+    <!-- Text hovering over canvas, number of invalidated regions this frame
+    [CHAR LIMIT=15] -->
+    <string name="number_invalidates">Invalidates</string>
+</resources>
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
new file mode 100644
index 0000000..36694a7
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
@@ -0,0 +1,173 @@
+/*
+ * 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.test.tilebenchmark;
+
+import android.app.Activity;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * Interface for playing back WebView tile rendering status. Draws viewport and
+ * states of tiles and statistics for off-line analysis.
+ */
+public class PlaybackActivity extends Activity {
+    private static final float SCROLL_SCALER = 0.125f;
+
+    PlaybackView mPlaybackView;
+    SeekBar mSeekBar;
+    Button mForward;
+    Button mBackward;
+    TextView mFrameDisplay;
+
+    private int mFrame = -1;
+    private int mFrameMax;
+
+    private class TouchFrameChangeListener extends SimpleOnGestureListener {
+        float mDist = 0;
+
+        @Override
+        public boolean onScroll(MotionEvent e1, MotionEvent e2,
+                float distanceX, float distanceY) {
+            // aggregate scrolls so that small ones can add up
+            mDist += distanceY * SCROLL_SCALER;
+            int intComponent = (int) Math.floor(Math.abs(mDist));
+            if (intComponent >= 1) {
+                int scrollDist = (mDist > 0) ? intComponent : -intComponent;
+                setFrame(null, mFrame + scrollDist);
+                mDist -= scrollDist;
+            }
+            return super.onScroll(e1, e2, distanceX, distanceY);
+        }
+    };
+
+    private class SeekFrameChangeListener implements OnSeekBarChangeListener {
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress,
+                boolean fromUser) {
+            setFrame(seekBar, progress);
+        }
+    };
+
+    private class LoadFileTask extends AsyncTask<String, Void, TileData[][]> {
+        @Override
+        protected TileData[][] doInBackground(String... params) {
+            TileData[][] data = null;
+            try {
+                FileInputStream fis = openFileInput(params[0]);
+                ObjectInputStream in = new ObjectInputStream(fis);
+                data = (TileData[][]) in.readObject();
+                in.close();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            } catch (ClassNotFoundException ex) {
+                ex.printStackTrace();
+            }
+            return data;
+        }
+
+        @Override
+        protected void onPostExecute(TileData data[][]) {
+            if (data == null) {
+                Toast.makeText(getApplicationContext(),
+                        getResources().getString(R.string.error_no_data),
+                        Toast.LENGTH_LONG).show();
+                return;
+            }
+            mPlaybackView.setData(data);
+
+            mFrameMax = data.length - 1;
+            mSeekBar.setMax(mFrameMax);
+
+            setFrame(null, 0);
+        }
+    }
+
+    private void setFrame(View changer, int f) {
+        if (f < 0) {
+            f = 0;
+        } else if (f > mFrameMax) {
+            f = mFrameMax;
+        }
+
+        if (mFrame == f) {
+            return;
+        }
+
+        mFrame = f;
+        mForward.setEnabled(mFrame != mFrameMax);
+        mBackward.setEnabled(mFrame != 0);
+        if (changer != mSeekBar) {
+            mSeekBar.setProgress(mFrame);
+        }
+        mFrameDisplay.setText(Integer.toString(mFrame));
+        mPlaybackView.setFrame(mFrame);
+    };
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.playback);
+
+        mPlaybackView = (PlaybackView) findViewById(R.id.playback);
+        mSeekBar = (SeekBar) findViewById(R.id.seek_bar);
+        mForward = (Button) findViewById(R.id.forward);
+        mBackward = (Button) findViewById(R.id.backward);
+        mFrameDisplay = (TextView) findViewById(R.id.frame_display);
+
+        mForward.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                setFrame(v, mFrame + 1);
+            }
+        });
+
+        mBackward.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                setFrame(v, mFrame - 1);
+            }
+        });
+
+        mSeekBar.setOnSeekBarChangeListener(new SeekFrameChangeListener());
+
+        mPlaybackView.setOnGestureListener(new TouchFrameChangeListener());
+
+        new LoadFileTask().execute(ProfileActivity.TEMP_FILENAME);
+    }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
new file mode 100644
index 0000000..35b1563
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
@@ -0,0 +1,263 @@
+/*
+ * 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.test.tilebenchmark;
+
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.ShapeDrawable;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class PlaybackGraphs {
+    private static final int BAR_WIDTH = PlaybackView.TILE_SCALE * 3;
+    private static final float CANVAS_SCALE = 0.2f;
+    private static final double IDEAL_FRAMES = 60;
+    private static final int LABELOFFSET = 100;
+    private static Paint whiteLabels;
+
+    private static double viewportCoverage(TileData view, TileData tile) {
+        if (tile.left < view.right
+                && tile.right >= view.left
+                && tile.top < view.bottom
+                && tile.bottom >= view.top) {
+            return 1.0f;
+        }
+        return 0.0f;
+    }
+
+    private interface MetricGen {
+        public double getValue(TileData[] frame);
+
+        public double getMax();
+
+        public int getLabelId();
+    };
+
+    private static MetricGen[] Metrics = new MetricGen[] {
+            new MetricGen() {
+                // framerate graph
+                @Override
+                public double getValue(TileData[] frame) {
+                    int renderTimeUS = frame[0].level;
+                    return 1.0e6f / renderTimeUS;
+                }
+
+                @Override
+                public double getMax() {
+                    return IDEAL_FRAMES;
+                }
+
+                @Override
+                public int getLabelId() {
+                    return R.string.frames_per_second;
+                }
+            }, new MetricGen() {
+                // coverage graph
+                @Override
+                public double getValue(TileData[] frame) {
+                    double total = 0, totalCount = 0;
+                    for (int tileID = 1; tileID < frame.length; tileID++) {
+                        TileData data = frame[tileID];
+                        double coverage = viewportCoverage(frame[0], data);
+                        total += coverage * (data.isReady ? 1 : 0);
+                        totalCount += coverage;
+                    }
+                    if (totalCount == 0) {
+                        return -1;
+                    }
+                    return total / totalCount;
+                }
+
+                @Override
+                public double getMax() {
+                    return 1;
+                }
+
+                @Override
+                public int getLabelId() {
+                    return R.string.viewport_coverage;
+                }
+            }
+    };
+
+    private interface StatGen {
+        public double getValue(double sortedValues[]);
+
+        public int getLabelId();
+    }
+
+    public static double getPercentile(double sortedValues[], double ratioAbove) {
+        double index = ratioAbove * (sortedValues.length - 1);
+        int intIndex = (int) Math.floor(index);
+        if (index == intIndex) {
+            return sortedValues[intIndex];
+        }
+        double alpha = index - intIndex;
+        return sortedValues[intIndex] * (1 - alpha)
+                + sortedValues[intIndex + 1] * (alpha);
+    }
+
+    private static StatGen[] Stats = new StatGen[] {
+            new StatGen() {
+                @Override
+                public double getValue(double[] sortedValues) {
+                    return getPercentile(sortedValues, 0.25);
+                }
+
+                @Override
+                public int getLabelId() {
+                    return R.string.percentile_25;
+                }
+            }, new StatGen() {
+                @Override
+                public double getValue(double[] sortedValues) {
+                    return getPercentile(sortedValues, 0.5);
+                }
+
+                @Override
+                public int getLabelId() {
+                    return R.string.percentile_50;
+                }
+            }, new StatGen() {
+                @Override
+                public double getValue(double[] sortedValues) {
+                    return getPercentile(sortedValues, 0.75);
+                }
+
+                @Override
+                public int getLabelId() {
+                    return R.string.percentile_75;
+                }
+            },
+    };
+
+    public PlaybackGraphs() {
+        whiteLabels = new Paint();
+        whiteLabels.setColor(Color.WHITE);
+        whiteLabels.setTextSize(PlaybackView.TILE_SCALE / 3);
+    }
+
+    private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>();
+    private double[][] mStats = new double[Metrics.length][Stats.length];
+
+    public void setData(TileData[][] tileProfilingData) {
+        mShapes.clear();
+        double metricValues[] = new double[tileProfilingData.length];
+
+        if (tileProfilingData.length == 0) {
+            return;
+        }
+
+        for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+            // create graph out of rectangles, one per frame
+            int lastBar = 0;
+            for (int frameIndex = 0; frameIndex < tileProfilingData.length; frameIndex++) {
+                TileData frame[] = tileProfilingData[frameIndex];
+                int newBar = (frame[0].top + frame[0].bottom) / 2;
+
+                MetricGen s = Metrics[metricIndex];
+                double absoluteValue = s.getValue(frame);
+                double relativeValue = absoluteValue / s.getMax();
+                relativeValue = Math.min(1,relativeValue);
+                relativeValue = Math.max(0,relativeValue);
+                int rightPos = (int) (-BAR_WIDTH * metricIndex);
+                int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
+
+                ShapeDrawable graphBar = new ShapeDrawable();
+                graphBar.getPaint().setColor(Color.BLUE);
+                graphBar.setBounds(leftPos, lastBar, rightPos, newBar);
+
+                mShapes.add(graphBar);
+                metricValues[frameIndex] = absoluteValue;
+                lastBar = newBar;
+            }
+
+            // store aggregate statistics per metric (median, and similar)
+            Arrays.sort(metricValues);
+            for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+                mStats[metricIndex][statIndex] = Stats[statIndex]
+                        .getValue(metricValues);
+            }
+        }
+    }
+
+    public void drawVerticalShiftedShapes(Canvas canvas,
+            ArrayList<ShapeDrawable> shapes) {
+        // Shapes drawn here are drawn relative to the viewRect
+        Rect viewRect = shapes.get(shapes.size() - 1).getBounds();
+        canvas.translate(0, 5 * PlaybackView.TILE_SCALE - viewRect.top);
+
+        for (ShapeDrawable shape : mShapes) {
+            shape.draw(canvas);
+        }
+        for (ShapeDrawable shape : shapes) {
+            shape.draw(canvas);
+        }
+    }
+
+    public void draw(Canvas canvas, ArrayList<ShapeDrawable> shapes,
+            String[] strings, Resources resources) {
+        canvas.scale(CANVAS_SCALE, CANVAS_SCALE);
+
+        canvas.translate(BAR_WIDTH * Metrics.length, 0);
+
+        canvas.save();
+        drawVerticalShiftedShapes(canvas, shapes);
+        canvas.restore();
+
+        for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+            String label = resources.getString(
+                    Metrics[metricIndex].getLabelId());
+            int xPos = (metricIndex + 1) * -BAR_WIDTH;
+            int yPos = LABELOFFSET;
+            canvas.drawText(label, xPos, yPos, whiteLabels);
+            for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+                label = resources.getString(R.string.format_stat,
+                        mStats[metricIndex][statIndex]);
+                yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILE_SCALE
+                        / 2;
+                canvas.drawText(label, xPos, yPos, whiteLabels);
+            }
+        }
+        for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) {
+            int yPos = LABELOFFSET + stringIndex * PlaybackView.TILE_SCALE / 2;
+            canvas.drawText(strings[stringIndex], 0, yPos, whiteLabels);
+        }
+    }
+
+    public Bundle getStatBundle(Resources resources) {
+        Bundle b = new Bundle();
+
+        for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+            for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+                String metricLabel = resources.getString(
+                        Metrics[metricIndex].getLabelId());
+                String statLabel = resources.getString(
+                        Stats[statIndex].getLabelId());
+                double value = mStats[metricIndex][statIndex];
+                b.putDouble(metricLabel + " " + statLabel, value);
+            }
+        }
+
+        return b;
+    }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
new file mode 100644
index 0000000..edc8643
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
@@ -0,0 +1,213 @@
+/*
+ * 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.test.tilebenchmark;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.ShapeDrawable;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+public class PlaybackView extends View {
+    public static final int TILE_SCALE = 300;
+    private static final int INVAL_FLAG = -2;
+    private static final int INVAL_CYCLE = 250;
+
+    private Paint levelPaint = null, coordPaint = null, goldPaint = null;
+    private PlaybackGraphs mGraphs;
+
+    private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>();
+    private TileData mProfData[][] = null;
+    private GestureDetector mGestureDetector = null;
+    private String mRenderStrings[] = new String[4];
+
+    private class TileDrawable extends ShapeDrawable {
+        TileData tile;
+        String label;
+
+        public TileDrawable(TileData t, int colorId) {
+            this.tile = t;
+            getPaint().setColor(getResources().getColor(colorId));
+            if (colorId == R.color.ready_tile
+                    || colorId == R.color.unready_tile) {
+
+                label = (int) (t.left / TILE_SCALE) + ", "
+                        + (int) (t.top / TILE_SCALE);
+                // ignore scale value for tiles
+                setBounds(t.left, t.top,
+                        t.right, t.bottom);
+            } else {
+                setBounds((int) (t.left * t.scale),
+                        (int) (t.top * t.scale),
+                        (int) (t.right * t.scale),
+                        (int) (t.bottom * t.scale));
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public void setColor(int color) {
+            getPaint().setColor(color);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            if (label != null) {
+                canvas.drawText(Integer.toString(tile.level), getBounds().left,
+                        getBounds().bottom, levelPaint);
+                canvas.drawText(label, getBounds().left,
+                        ((getBounds().bottom + getBounds().top) / 2),
+                        coordPaint);
+            }
+        }
+    }
+
+    public PlaybackView(Context context) {
+        super(context);
+        init();
+    }
+
+    public PlaybackView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public PlaybackView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public void setOnGestureListener(OnGestureListener gl) {
+        mGestureDetector = new GestureDetector(getContext(), gl);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        mGestureDetector.onTouchEvent(event);
+        return true;
+    }
+
+    private void init() {
+        levelPaint = new Paint();
+        levelPaint.setColor(Color.WHITE);
+        levelPaint.setTextSize(TILE_SCALE / 2);
+        coordPaint = new Paint();
+        coordPaint.setColor(Color.BLACK);
+        coordPaint.setTextSize(TILE_SCALE / 3);
+        goldPaint = new Paint();
+        goldPaint.setColor(0xffa0e010);
+        mGraphs = new PlaybackGraphs();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        if (mTempShapes == null || mTempShapes.isEmpty()) {
+            return;
+        }
+
+        mGraphs.draw(canvas, mTempShapes, mRenderStrings, getResources());
+        invalidate(); // may have animations, force redraw
+    }
+
+    public int setFrame(int frame) {
+        if (mProfData == null || mProfData.length == 0) {
+            return 0;
+        }
+
+        int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0, numInvals = 0;
+        mTempShapes.clear();
+
+        // create tile shapes (as they're drawn on bottom)
+        for (TileData t : mProfData[frame]) {
+            if (t.level != INVAL_FLAG && t != mProfData[frame][0]) {
+                int colorId;
+                if (t.isReady) {
+                    readyTiles++;
+                    colorId = R.color.ready_tile;
+                } else {
+                    unreadyTiles++;
+                    colorId = R.color.unready_tile;
+                }
+                if (t.left < 0 || t.top < 0) {
+                    unplacedTiles++;
+                }
+                mTempShapes.add(new TileDrawable(t, colorId));
+            } else {
+                numInvals++;
+            }
+        }
+
+        // create invalidate shapes (drawn above tiles)
+        int invalId = 0;
+        for (TileData t : mProfData[frame]) {
+            if (t.level == INVAL_FLAG && t != mProfData[frame][0]) {
+                TileDrawable invalShape = new TileDrawable(t,
+                        R.color.inval_region_start);
+                ValueAnimator tileAnimator = ObjectAnimator.ofInt(invalShape,
+                        "color",
+                        getResources().getColor(R.color.inval_region_start),
+                        getResources().getColor(R.color.inval_region_stop));
+                tileAnimator.setDuration(numInvals * INVAL_CYCLE);
+                tileAnimator.setEvaluator(new ArgbEvaluator());
+                tileAnimator.setRepeatCount(ValueAnimator.INFINITE);
+                tileAnimator.setRepeatMode(ValueAnimator.RESTART);
+                float delay = (float) (invalId) * INVAL_CYCLE;
+                tileAnimator.setStartDelay((int) delay);
+                invalId++;
+                tileAnimator.start();
+
+                mTempShapes.add(invalShape);
+            }
+        }
+
+        mRenderStrings[0] = getResources().getString(R.string.format_stat_name,
+                getResources().getString(R.string.ready_tiles), readyTiles);
+        mRenderStrings[1] = getResources().getString(R.string.format_stat_name,
+                getResources().getString(R.string.unready_tiles), unreadyTiles);
+        mRenderStrings[2] = getResources().getString(R.string.format_stat_name,
+                getResources().getString(R.string.unplaced_tiles),
+                unplacedTiles);
+        mRenderStrings[3] = getResources().getString(R.string.format_stat_name,
+                getResources().getString(R.string.number_invalidates),
+                numInvals);
+
+        // draw view rect (using first TileData object, on top)
+        TileDrawable viewShape = new TileDrawable(mProfData[frame][0],
+                R.color.view);
+        mTempShapes.add(viewShape);
+        this.invalidate();
+        return frame;
+    }
+
+    public void setData(TileData[][] tileProfilingData) {
+        mProfData = tileProfilingData;
+
+        mGraphs.setData(mProfData);
+    }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
new file mode 100644
index 0000000..1521807
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
@@ -0,0 +1,320 @@
+/*
+ * 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.test.tilebenchmark;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Pair;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+import android.widget.ToggleButton;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
+/**
+ * Interface for profiling the webview's scrolling, with simple controls on how
+ * to scroll, and what content to load.
+ */
+public class ProfileActivity extends Activity {
+
+    public interface ProfileCallback {
+        public void profileCallback(TileData data[][]);
+    }
+
+    public static final String TEMP_FILENAME = "profile.tiles";
+    private static final int LOAD_TEST_DELAY = 2000; // nr of millis after load,
+                                                     // before test
+
+    Button mInspectButton;
+    ToggleButton mCaptureButton;
+    Spinner mVelocitySpinner;
+    Spinner mMovementSpinner;
+    EditText mUrl;
+    ProfiledWebView mWeb;
+    ProfileCallback mCallback;
+
+    LoggingWebViewClient mLoggingWebViewClient = new LoggingWebViewClient();
+    AutoLoggingWebViewClient mAutoLoggingWebViewClient = new AutoLoggingWebViewClient();
+
+    private enum TestingState {
+        NOT_TESTING,
+        PRE_TESTING,
+        START_TESTING,
+        STOP_TESTING,
+        SAVED_TESTING
+    };
+
+    private class VelocitySelectedListener implements OnItemSelectedListener {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view,
+                int position, long id) {
+            String speedStr = parent.getItemAtPosition(position).toString();
+            int speedInt = Integer.parseInt(speedStr);
+            mWeb.setAutoScrollSpeed(speedInt);
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+        }
+    }
+
+    private class MovementSelectedListener implements OnItemSelectedListener {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view,
+                int position, long id) {
+            String movementStr = parent.getItemAtPosition(position).toString();
+            if (movementStr == getResources().getString(
+                    R.string.movement_auto_scroll)
+                    || movementStr == getResources().getString(
+                            R.string.movement_auto_fling)) {
+                mWeb.setWebViewClient(mAutoLoggingWebViewClient);
+                mCaptureButton.setEnabled(false);
+                mVelocitySpinner.setEnabled(true);
+            } else if (movementStr == getResources().getString(
+                    R.string.movement_manual)) {
+                mWeb.setWebViewClient(mLoggingWebViewClient);
+                mCaptureButton.setEnabled(true);
+                mVelocitySpinner.setEnabled(false);
+            }
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+        }
+    }
+
+    private class LoggingWebViewClient extends WebViewClient {
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            return false;
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            mUrl.setText(url);
+        }
+    }
+
+    private class AutoLoggingWebViewClient extends LoggingWebViewClient {
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            view.requestFocus();
+            new CountDownTimer(LOAD_TEST_DELAY, LOAD_TEST_DELAY) {
+                @Override
+                public void onTick(long millisUntilFinished) {
+                }
+
+                @Override
+                public void onFinish() {
+                    startViewProfiling(true);
+                }
+            }.start();
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            setTestingState(TestingState.PRE_TESTING);
+        }
+    }
+
+    private class StoreFileTask extends
+            AsyncTask<Pair<String, TileData[][]>, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Pair<String, TileData[][]>... params) {
+            try {
+                FileOutputStream fos = openFileOutput(params[0].first,
+                        Context.MODE_PRIVATE);
+                ObjectOutputStream out = new ObjectOutputStream(fos);
+                out.writeObject(params[0].second);
+                out.close();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void v) {
+            setTestingState(TestingState.SAVED_TESTING);
+        }
+    }
+
+    public void setTestingState(TestingState state) {
+        switch (state) {
+            case NOT_TESTING:
+                mUrl.setBackgroundResource(R.color.background_not_testing);
+                mInspectButton.setEnabled(true);
+                mMovementSpinner.setEnabled(true);
+                break;
+            case PRE_TESTING:
+                mInspectButton.setEnabled(false);
+                mMovementSpinner.setEnabled(false);
+                break;
+            case START_TESTING:
+                mUrl.setBackgroundResource(R.color.background_start_testing);
+                mInspectButton.setEnabled(false);
+                mMovementSpinner.setEnabled(false);
+                break;
+            case STOP_TESTING:
+                mUrl.setBackgroundResource(R.color.background_stop_testing);
+                break;
+            case SAVED_TESTING:
+                mInspectButton.setEnabled(true);
+                mMovementSpinner.setEnabled(true);
+                break;
+        }
+    }
+
+    /** auto - automatically scroll. */
+    private void startViewProfiling(boolean auto) {
+        if (!auto) {
+            // manual, toggle capture button to indicate capture state to user
+            mCaptureButton.setChecked(true);
+        }
+        mWeb.startScrollTest(mCallback, auto);
+        setTestingState(TestingState.START_TESTING);
+    }
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        mInspectButton = (Button) findViewById(R.id.inspect);
+        mCaptureButton = (ToggleButton) findViewById(R.id.capture);
+        mVelocitySpinner = (Spinner) findViewById(R.id.velocity);
+        mMovementSpinner = (Spinner) findViewById(R.id.movement);
+        mUrl = (EditText) findViewById(R.id.url);
+        mWeb = (ProfiledWebView) findViewById(R.id.web);
+        mCallback = new ProfileCallback() {
+            @SuppressWarnings("unchecked")
+            @Override
+            public void profileCallback(TileData[][] data) {
+                new StoreFileTask().execute(new Pair<String, TileData[][]>(
+                        TEMP_FILENAME, data));
+                mCaptureButton.setChecked(false);
+                setTestingState(TestingState.STOP_TESTING);
+            }
+        };
+
+        // Inspect button (opens PlaybackActivity)
+        mInspectButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startActivity(new Intent(ProfileActivity.this,
+                        PlaybackActivity.class));
+            }
+        });
+
+        // Velocity spinner
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+                this, R.array.velocity_array,
+                android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(
+                android.R.layout.simple_spinner_dropdown_item);
+        mVelocitySpinner.setAdapter(adapter);
+        mVelocitySpinner.setOnItemSelectedListener(
+                new VelocitySelectedListener());
+        mVelocitySpinner.setSelection(3);
+
+        // Movement spinner
+        String content[] = {
+                getResources().getString(R.string.movement_auto_scroll),
+                getResources().getString(R.string.movement_auto_fling),
+                getResources().getString(R.string.movement_manual)
+        };
+        adapter = new ArrayAdapter<CharSequence>(this,
+                android.R.layout.simple_spinner_item, content);
+        adapter.setDropDownViewResource(
+                android.R.layout.simple_spinner_dropdown_item);
+        mMovementSpinner.setAdapter(adapter);
+        mMovementSpinner.setOnItemSelectedListener(
+                new MovementSelectedListener());
+        mMovementSpinner.setSelection(0);
+
+        // Capture toggle button
+        mCaptureButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mCaptureButton.isChecked()) {
+                    startViewProfiling(false);
+                } else {
+                    mWeb.stopScrollTest();
+                }
+            }
+        });
+
+        // Custom profiling WebView
+        WebSettings settings = mWeb.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setSupportZoom(true);
+        settings.setEnableSmoothTransition(true);
+        settings.setBuiltInZoomControls(true);
+        settings.setLoadWithOverviewMode(true);
+        mWeb.setWebViewClient(new LoggingWebViewClient());
+
+        // URL text entry
+        mUrl.setOnEditorActionListener(new OnEditorActionListener() {
+            public boolean onEditorAction(TextView v, int actionId,
+                    KeyEvent event) {
+                String url = mUrl.getText().toString();
+                mWeb.loadUrl(url);
+                mWeb.requestFocus();
+                return true;
+            }
+        });
+
+        setTestingState(TestingState.NOT_TESTING);
+    }
+
+    public void setCallback(ProfileCallback callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
+            mWeb.goBack();
+            return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
new file mode 100644
index 0000000..d3941be
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -0,0 +1,119 @@
+/*
+ * 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.test.tilebenchmark;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.webkit.WebView;
+
+import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
+
+public class ProfiledWebView extends WebView {
+    private int mSpeed;
+
+    private boolean isScrolling = false;
+    private ProfileCallback mCallback;
+
+    public ProfiledWebView(Context context) {
+        super(context);
+    }
+
+    public ProfiledWebView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ProfiledWebView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public ProfiledWebView(Context context, AttributeSet attrs, int defStyle,
+            boolean privateBrowsing) {
+        super(context, attrs, defStyle, privateBrowsing);
+    }
+
+    @Override
+    protected void onDraw(android.graphics.Canvas canvas) {
+        if (isScrolling) {
+            if (canScrollVertically(1)) {
+                scrollBy(0, mSpeed);
+            } else {
+                stopScrollTest();
+                isScrolling = false;
+            }
+        }
+        super.onDraw(canvas);
+    }
+
+    /*
+     * Called once the page is loaded to start scrolling for evaluating tiles.
+     * If autoScrolling isn't set, stop must be called manually.
+     */
+    public void startScrollTest(ProfileCallback callback, boolean autoScrolling) {
+        isScrolling = autoScrolling;
+        mCallback = callback;
+        tileProfilingStart();
+        invalidate();
+    }
+
+    /*
+     * Called once the page has stopped scrolling
+     */
+    public void stopScrollTest() {
+        super.tileProfilingStop();
+
+        if (mCallback == null) {
+            tileProfilingClear();
+            return;
+        }
+
+        TileData data[][] = new TileData[super.tileProfilingNumFrames()][];
+        for (int frame = 0; frame < data.length; frame++) {
+            data[frame] = new TileData[
+                    tileProfilingNumTilesInFrame(frame)];
+            for (int tile = 0; tile < data[frame].length; tile++) {
+                int left = tileProfilingGetInt(frame, tile, "left");
+                int top = tileProfilingGetInt(frame, tile, "top");
+                int right = tileProfilingGetInt(frame, tile, "right");
+                int bottom = tileProfilingGetInt(frame, tile, "bottom");
+
+                boolean isReady = super.tileProfilingGetInt(
+                        frame, tile, "isReady") == 1;
+                int level = tileProfilingGetInt(frame, tile, "level");
+
+                float scale = tileProfilingGetFloat(frame, tile, "scale");
+
+                data[frame][tile] = new TileData(left, top, right, bottom,
+                        isReady, level, scale);
+            }
+        }
+        super.tileProfilingClear();
+
+        mCallback.profileCallback(data);
+    }
+
+    @Override
+    public void loadUrl(String url) {
+        if (!url.startsWith("http://")) {
+            url = "http://" + url;
+        }
+        super.loadUrl(url);
+    }
+
+    public void setAutoScrollSpeed(int speedInt) {
+        mSpeed = speedInt;
+    }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
new file mode 100644
index 0000000..3e729a6
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
@@ -0,0 +1,42 @@
+/*
+ * 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.test.tilebenchmark;
+
+import java.io.Serializable;
+
+public class TileData implements Serializable {
+    int left, top, right, bottom;
+    public boolean isReady;
+    public int level;
+    public float scale;
+
+    public TileData(int left, int top, int right, int bottom, boolean isReady,
+            int level, float scale) {
+        this.left = left;
+        this.right = right;
+        this.top = top;
+        this.bottom = bottom;
+        this.isReady = isReady;
+        this.level = level;
+        this.scale = scale;
+    }
+
+    public String toString() {
+        return "Tile (" + left + "," + top + ")->("
+                + right + "," + bottom + ")";
+    }
+}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 29d2b87..d66cdf0 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1560,10 +1560,10 @@
 }
 
 ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
-                            const AaptGroupEntry& kind, const String8& resType)
+                            const AaptGroupEntry& kind, const String8& resType,
+                            sp<FilePathStore>& fullResPaths)
 {
     Vector<String8> fileNames;
-
     {
         DIR* dir = NULL;
 
@@ -1586,9 +1586,14 @@
             if (isHidden(srcDir.string(), entry->d_name))
                 continue;
 
-            fileNames.add(String8(entry->d_name));
+            String8 name(entry->d_name);
+            fileNames.add(name);
+            // Add fully qualified path for dependency purposes
+            // if we're collecting them
+            if (fullResPaths != NULL) {
+                fullResPaths->add(srcDir.appendPathCopy(name));
+            }
         }
-
         closedir(dir);
     }
 
@@ -1615,7 +1620,7 @@
                 notAdded = true;
             }
             ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
-                                                resType);
+                                                resType, fullResPaths);
             if (res < NO_ERROR) {
                 return res;
             }
@@ -1847,7 +1852,7 @@
         sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
         AaptGroupEntry group;
         count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
-                                            String8());
+                                            String8(), mFullAssetPaths);
         if (count < 0) {
             totalCount = count;
             goto bail;
@@ -1878,6 +1883,7 @@
                     sp<AaptAssets> nextOverlay = new AaptAssets();
                     current->setOverlay(nextOverlay);
                     current = nextOverlay;
+                    current->setFullResPaths(mFullResPaths);
                 }
                 count = current->slurpResourceTree(bundle, String8(res));
 
@@ -1920,7 +1926,7 @@
          * guarantees about ordering, so we're okay with an inorder search
          * using whatever order the OS happens to hand back to us.
          */
-        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8());
+        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths);
         if (count < 0) {
             /* failure; report error and remove archive */
             totalCount = count;
@@ -1946,9 +1952,10 @@
 
 ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
                                     const AaptGroupEntry& kind,
-                                    const String8& resType)
+                                    const String8& resType,
+                                    sp<FilePathStore>& fullResPaths)
 {
-    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType);
+    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths);
     if (res > 0) {
         mGroupEntries.add(kind);
     }
@@ -2010,7 +2017,7 @@
         if (type == kFileTypeDirectory) {
             sp<AaptDir> dir = makeDir(String8(entry->d_name));
             ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
-                                                resType);
+                                                resType, mFullResPaths);
             if (res < 0) {
                 count = res;
                 goto bail;
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 65743d8..82dfd71 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -140,6 +140,7 @@
 }
 
 class AaptGroup;
+class FilePathStore;
 
 /**
  * A single asset file we know about.
@@ -269,7 +270,8 @@
     virtual ssize_t slurpFullTree(Bundle* bundle,
                                   const String8& srcDir,
                                   const AaptGroupEntry& kind,
-                                  const String8& resType);
+                                  const String8& resType,
+                                  sp<FilePathStore>& fullResPaths);
 
     /*
      * Perform some sanity checks on the names of files and directories here.
@@ -484,6 +486,14 @@
     ResourceTypeSet();
 };
 
+// Storage for lists of fully qualified paths for
+// resources encountered during slurping.
+class FilePathStore : public RefBase,
+                      public Vector<String8>
+{
+public:
+    FilePathStore();
+};
 
 /**
  * Asset hierarchy being operated on.
@@ -517,7 +527,8 @@
     virtual ssize_t slurpFullTree(Bundle* bundle,
                                   const String8& srcDir,
                                   const AaptGroupEntry& kind,
-                                  const String8& resType);
+                                  const String8& resType,
+                                  sp<FilePathStore>& fullResPaths);
 
     ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
     ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
@@ -545,6 +556,14 @@
     inline void 
         setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
 
+    inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
+    inline void
+        setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
+
+    inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
+    inline void
+        setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
+
 private:
     String8 mPackage;
     SortedVector<AaptGroupEntry> mGroupEntries;
@@ -558,6 +577,9 @@
 
     sp<AaptAssets> mOverlay;
     KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
+
+    sp<FilePathStore> mFullResPaths;
+    sp<FilePathStore> mFullAssetPaths;
 };
 
 #endif // __AAPT_ASSETS_H
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 094b7db..e507fb9 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -13,6 +13,8 @@
 LOCAL_SRC_FILES := \
 	AaptAssets.cpp \
 	Command.cpp \
+	CrunchCache.cpp \
+	FileFinder.cpp \
 	Main.cpp \
 	Package.cpp \
 	StringPool.cpp \
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index fa84e93..539c312 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -25,6 +25,7 @@
     kCommandAdd,
     kCommandRemove,
     kCommandPackage,
+    kCommandCrunch,
 } Command;
 
 /*
@@ -41,13 +42,15 @@
           mCompressionMethod(0), mOutputAPKFile(NULL),
           mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
           mIsOverlayPackage(false),
-          mAutoAddOverlay(false), mAssetSourceDir(NULL), mProguardFile(NULL),
+          mAutoAddOverlay(false), mGenDependencies(false),
+          mAssetSourceDir(NULL), 
+          mCrunchedOutputDir(NULL), mProguardFile(NULL),
           mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
           mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
           mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
-          mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL),
+          mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL),
           mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL),
-          mArgc(0), mArgv(NULL)
+          mUseCrunchCache(false), mArgc(0), mArgv(NULL)
         {}
     ~Bundle(void) {}
 
@@ -97,12 +100,16 @@
     void setIsOverlayPackage(bool val) { mIsOverlayPackage = val; }
     bool getAutoAddOverlay() { return mAutoAddOverlay; }
     void setAutoAddOverlay(bool val) { mAutoAddOverlay = val; }
+    bool getGenDependencies() { return mGenDependencies; }
+    void setGenDependencies(bool val) { mGenDependencies = val; }
 
     /*
      * Input options.
      */
     const char* getAssetSourceDir() const { return mAssetSourceDir; }
     void setAssetSourceDir(const char* dir) { mAssetSourceDir = dir; }
+    const char* getCrunchedOutputDir() const { return mCrunchedOutputDir; }
+    void setCrunchedOutputDir(const char* dir) { mCrunchedOutputDir = dir; }
     const char* getProguardFile() const { return mProguardFile; }
     void setProguardFile(const char* file) { mProguardFile = file; }
     const android::Vector<const char*>& getResourceSourceDirs() const { return mResourceSourceDirs; }
@@ -138,6 +145,8 @@
     void setVersionName(const char* val) { mVersionName = val; }
     const char* getCustomPackage() const { return mCustomPackage; }
     void setCustomPackage(const char* val) { mCustomPackage = val; }
+    const char* getExtraPackages() const { return mExtraPackages; }
+    void setExtraPackages(const char* val) { mExtraPackages = val; }
     const char* getMaxResVersion() const { return mMaxResVersion; }
     void setMaxResVersion(const char * val) { mMaxResVersion = val; }
     bool getDebugMode() { return mDebugMode; }
@@ -146,6 +155,8 @@
     void setNonConstantId(bool val) { mNonConstantId = val; }
     const char* getProduct() const { return mProduct; }
     void setProduct(const char * val) { mProduct = val; }
+    void setUseCrunchCache(bool val) { mUseCrunchCache = val; }
+    bool getUseCrunchCache() { return mUseCrunchCache; }
 
     /*
      * Set and get the file specification.
@@ -224,7 +235,9 @@
     const char* mInstrumentationPackageNameOverride;
     bool        mIsOverlayPackage;
     bool        mAutoAddOverlay;
+    bool        mGenDependencies;
     const char* mAssetSourceDir;
+    const char* mCrunchedOutputDir;
     const char* mProguardFile;
     const char* mAndroidManifestFile;
     const char* mPublicOutputFile;
@@ -243,10 +256,12 @@
     const char* mVersionCode;
     const char* mVersionName;
     const char* mCustomPackage;
+    const char* mExtraPackages;
     const char* mMaxResVersion;
     bool        mDebugMode;
     bool        mNonConstantId;
     const char* mProduct;
+    bool        mUseCrunchCache;
 
     /* file specification */
     int         mArgc;
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
new file mode 100644
index 0000000..0e65589
--- /dev/null
+++ b/tools/aapt/CacheUpdater.h
@@ -0,0 +1,107 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Abstraction of calls to system to make directories and delete files and
+// wrapper to image processing.
+
+#ifndef CACHE_UPDATER_H
+#define CACHE_UPDATER_H
+
+#include <utils/String8.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include "Images.h"
+
+using namespace android;
+
+/** CacheUpdater
+ *  This is a pure virtual class that declares abstractions of functions useful
+ *  for managing a cache files. This manager is set up to be used in a
+ *  mirror cache where the source tree is duplicated and filled with processed
+ *  images. This class is abstracted to allow for dependency injection during
+ *  unit testing.
+ *  Usage:
+ *      To update/add a file to the cache, call processImage
+ *      To remove a file from the cache, call deleteFile
+ */
+class CacheUpdater {
+public:
+    // Make sure all the directories along this path exist
+    virtual void ensureDirectoriesExist(String8 path) = 0;
+
+    // Delete a file
+    virtual void deleteFile(String8 path) = 0;
+
+    // Process an image from source out to dest
+    virtual void processImage(String8 source, String8 dest) = 0;
+private:
+};
+
+/** SystemCacheUpdater
+ * This is an implementation of the above virtual cache updater specification.
+ * This implementations hits the filesystem to manage a cache and calls out to
+ * the PNG crunching in images.h to process images out to its cache components.
+ */
+class SystemCacheUpdater : public CacheUpdater {
+public:
+    // Constructor to set bundle to pass to preProcessImage
+    SystemCacheUpdater (Bundle* b)
+        : bundle(b) { };
+
+    // Make sure all the directories along this path exist
+    virtual void ensureDirectoriesExist(String8 path)
+    {
+        // Check to see if we're dealing with a fully qualified path
+        String8 existsPath;
+        String8 toCreate;
+        String8 remains;
+        struct stat s;
+
+        // Check optomistically to see if all directories exist.
+        // If something in the path doesn't exist, then walk the path backwards
+        // and find the place to start creating directories forward.
+        if (stat(path.string(),&s) == -1) {
+            // Walk backwards to find place to start creating directories
+            existsPath = path;
+            do {
+                // As we remove the end of existsPath add it to
+                // the string of paths to create.
+                toCreate = existsPath.getPathLeaf().appendPath(toCreate);
+                existsPath = existsPath.getPathDir();
+            } while (stat(existsPath.string(),&s) == -1);
+
+            // Walk forwards and build directories as we go
+            do {
+                // Advance to the next segment of the path
+                existsPath.appendPath(toCreate.walkPath(&remains));
+                toCreate = remains;
+#ifdef HAVE_MS_C_RUNTIME
+                _mkdir(existsPath.string());
+#else
+                mkdir(existsPath.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
+#endif
+            } while (remains.length() > 0);
+        } //if
+    };
+
+    // Delete a file
+    virtual void deleteFile(String8 path)
+    {
+        if (remove(path.string()) != 0)
+            fprintf(stderr,"ERROR DELETING %s\n",path.string());
+    };
+
+    // Process an image from source out to dest
+    virtual void processImage(String8 source, String8 dest)
+    {
+        // Make sure we're trying to write to a directory that is extant
+        ensureDirectoriesExist(dest.getPathDir());
+
+        preProcessImageToCache(bundle, source, dest);
+    };
+private:
+    Bundle* bundle;
+};
+
+#endif // CACHE_UPDATER_H
\ No newline at end of file
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 7852197..daf53e0 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -1508,6 +1508,8 @@
     status_t err;
     sp<AaptAssets> assets;
     int N;
+    FILE* fp;
+    String8 dependencyFile;
 
     // -c zz_ZZ means do pseudolocalization
     ResourceFilter filter;
@@ -1542,6 +1544,16 @@
 
     // Load the assets.
     assets = new AaptAssets();
+
+    // Set up the resource gathering in assets if we're going to generate
+    // dependency files
+    if (bundle->getGenDependencies()) {
+        sp<FilePathStore> resPathStore = new FilePathStore;
+        assets->setFullResPaths(resPathStore);
+        sp<FilePathStore> assetPathStore = new FilePathStore;
+        assets->setFullAssetPaths(assetPathStore);
+    }
+
     err = assets->slurpFromArgs(bundle);
     if (err < 0) {
         goto bail;
@@ -1551,7 +1563,7 @@
         assets->print();
     }
 
-    // If they asked for any files that need to be compiled, do so.
+    // If they asked for any fileAs that need to be compiled, do so.
     if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
         err = buildResources(bundle, assets);
         if (err != 0) {
@@ -1565,10 +1577,36 @@
         goto bail;
     }
 
+    if (bundle->getGenDependencies()) {
+        if (outputAPKFile) {
+            dependencyFile = String8(outputAPKFile);
+            // Strip the extension and add new one
+            dependencyFile = dependencyFile.getBasePath();
+            dependencyFile.append(".d");
+        } else {
+            dependencyFile = String8(bundle->getRClassDir());
+            dependencyFile.appendPath("R.d");
+        }
+        // Make sure we have a clean dependency file to start with
+        fp = fopen(dependencyFile, "w");
+        fclose(fp);
+    }
+
     // Write out R.java constants
     if (assets->getPackage() == assets->getSymbolsPrivatePackage()) {
         if (bundle->getCustomPackage() == NULL) {
             err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
+            // Copy R.java for libraries
+            if (bundle->getExtraPackages() != NULL) {
+                // Split on colon
+                String8 libs(bundle->getExtraPackages());
+                char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
+                while (packageString != NULL) {
+                    err = writeResourceSymbols(bundle, assets, String8(packageString), true);
+                    packageString = strtok(NULL, ":");
+                }
+                libs.unlockBuffer();
+            }
         } else {
             const String8 customPkg(bundle->getCustomPackage());
             err = writeResourceSymbols(bundle, assets, customPkg, true);
@@ -1602,6 +1640,18 @@
         }
     }
 
+    if (bundle->getGenDependencies()) {
+        // Now that writeResourceSymbols or writeAPK has taken care of writing
+        // the targets to our dependency file, we'll write the prereqs
+        fp = fopen(dependencyFile, "a+");
+        fprintf(fp, " : ");
+        bool includeRaw = (outputAPKFile != NULL);
+        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
+        // Also manually add the AndroidManifeset since it's a non-asset
+        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
+        fclose(fp);
+    }
+
     retVal = 0;
 bail:
     if (SourcePos::hasErrors()) {
@@ -1609,3 +1659,25 @@
     }
     return retVal;
 }
+
+/*
+ * Do PNG Crunching
+ * PRECONDITIONS
+ *  -S flag points to a source directory containing drawable* folders
+ *  -C flag points to destination directory. The folder structure in the
+ *     source directory will be mirrored to the destination (cache) directory
+ *
+ * POSTCONDITIONS
+ *  Destination directory will be updated to match the PNG files in
+ *  the source directory. 
+ */
+int doCrunch(Bundle* bundle)
+{
+    fprintf(stdout, "Crunching PNG Files in ");
+    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
+    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
+
+    updatePreProcessedCache(bundle);
+
+    return NO_ERROR;
+}
diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp
new file mode 100644
index 0000000..c4cf6bc
--- /dev/null
+++ b/tools/aapt/CrunchCache.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Implementation file for CrunchCache
+// This file defines functions laid out and documented in
+// CrunchCache.h
+
+#include <utils/Vector.h>
+#include <utils/String8.h>
+
+#include "DirectoryWalker.h"
+#include "FileFinder.h"
+#include "CacheUpdater.h"
+#include "CrunchCache.h"
+
+using namespace android;
+
+CrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff)
+    : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff)
+{
+    // We initialize the default value to return to 0 so if a file doesn't exist
+    // then all files are automatically "newer" than it.
+
+    // Set file extensions to look for. Right now just pngs.
+    mExtensions.push(String8(".png"));
+
+    // Load files into our data members
+    loadFiles();
+}
+
+size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite)
+{
+    size_t numFilesUpdated = 0;
+
+    // Iterate through the source files and compare to cache.
+    // After processing a file, remove it from the source files and
+    // from the dest files.
+    // We're done when we're out of files in source.
+    String8 relativePath;
+    while (mSourceFiles.size() > 0) {
+        // Get the full path to the source file, then convert to a c-string
+        // and offset our beginning pointer to the length of the sourcePath
+        // This efficiently strips the source directory prefix from our path.
+        // Also, String8 doesn't have a substring method so this is what we've
+        // got to work with.
+        const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length();
+        // Strip leading slash if present
+        int offset = 0;
+        if (rPathPtr[0] == OS_PATH_SEPARATOR)
+            offset = 1;
+        relativePath = String8(rPathPtr + offset);
+
+        if (forceOverwrite || needsUpdating(relativePath)) {
+            cu->processImage(mSourcePath.appendPathCopy(relativePath),
+                             mDestPath.appendPathCopy(relativePath));
+            numFilesUpdated++;
+            // crunchFile(relativePath);
+        }
+        // Delete this file from the source files and (if it exists) from the
+        // dest files.
+        mSourceFiles.removeItemsAt(0);
+        mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath));
+    }
+
+    // Iterate through what's left of destFiles and delete leftovers
+    while (mDestFiles.size() > 0) {
+        cu->deleteFile(mDestFiles.keyAt(0));
+        mDestFiles.removeItemsAt(0);
+    }
+
+    // Update our knowledge of the files cache
+    // both source and dest should be empty by now.
+    loadFiles();
+
+    return numFilesUpdated;
+}
+
+void CrunchCache::loadFiles()
+{
+    // Clear out our data structures to avoid putting in duplicates
+    mSourceFiles.clear();
+    mDestFiles.clear();
+
+    // Make a directory walker that points to the system.
+    DirectoryWalker* dw = new SystemDirectoryWalker();
+
+    // Load files in the source directory
+    mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw);
+
+    // Load files in the destination directory
+    mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw);
+
+    delete dw;
+}
+
+bool CrunchCache::needsUpdating(String8 relativePath) const
+{
+    // Retrieve modification dates for this file entry under the source and
+    // cache directory trees. The vectors will return a modification date of 0
+    // if the file doesn't exist.
+    time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath));
+    time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath));
+    return sourceDate > destDate;
+}
\ No newline at end of file
diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h
new file mode 100644
index 0000000..be3da5c
--- /dev/null
+++ b/tools/aapt/CrunchCache.h
@@ -0,0 +1,102 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Cache manager for pre-processed PNG files.
+// Contains code for managing which PNG files get processed
+// at build time.
+//
+
+#ifndef CRUNCHCACHE_H
+#define CRUNCHCACHE_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include "FileFinder.h"
+#include "CacheUpdater.h"
+
+using namespace android;
+
+/** CrunchCache
+ *  This class is a cache manager which can pre-process PNG files and store
+ *  them in a mirror-cache. It's capable of doing incremental updates to its
+ *  cache.
+ *
+ *  Usage:
+ *      Create an instance initialized with the root of the source tree, the
+ *      root location to store the cache files, and an instance of a file finder.
+ *      Then update the cache by calling crunch.
+ */
+class CrunchCache {
+public:
+    // Constructor
+    CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff);
+
+    // Nobody should be calling the default constructor
+    // So this space is intentionally left blank
+
+    // Default Copy Constructor and Destructor are fine
+
+    /** crunch is the workhorse of this class.
+     * It goes through all the files found in the sourcePath and compares
+     * them to the cached versions in the destPath. If the optional
+     * argument forceOverwrite is set to true, then all source files are
+     * re-crunched even if they have not been modified recently. Otherwise,
+     * source files are only crunched when they needUpdating. Afterwards,
+     * we delete any leftover files in the cache that are no longer present
+     * in source.
+     *
+     * PRECONDITIONS:
+     *      No setup besides construction is needed
+     * POSTCONDITIONS:
+     *      The cache is updated to fully reflect all changes in source.
+     *      The function then returns the number of files changed in cache
+     *      (counting deletions).
+     */
+    size_t crunch(CacheUpdater* cu, bool forceOverwrite=false);
+
+private:
+    /** loadFiles is a wrapper to the FileFinder that places matching
+     * files into mSourceFiles and mDestFiles.
+     *
+     *  POSTCONDITIONS
+     *      mDestFiles and mSourceFiles are refreshed to reflect the current
+     *      state of the files in the source and dest directories.
+     *      Any previous contents of mSourceFiles and mDestFiles are cleared.
+     */
+    void loadFiles();
+
+    /** needsUpdating takes a file path
+     * and returns true if the file represented by this path is newer in the
+     * sourceFiles than in the cache (mDestFiles).
+     *
+     * PRECONDITIONS:
+     *      mSourceFiles and mDestFiles must be initialized and filled.
+     * POSTCONDITIONS:
+     *      returns true if and only if source file's modification time
+     *      is greater than the cached file's mod-time. Otherwise returns false.
+     *
+     * USAGE:
+     *      Should be used something like the following:
+     *      if (needsUpdating(filePath))
+     *          // Recrunch sourceFile out to destFile.
+     *
+     */
+    bool needsUpdating(String8 relativePath) const;
+
+    // DATA MEMBERS ====================================================
+
+    String8 mSourcePath;
+    String8 mDestPath;
+
+    Vector<String8> mExtensions;
+
+    // Each vector of paths contains one entry per PNG file encountered.
+    // Each entry consists of a path pointing to that PNG.
+    DefaultKeyedVector<String8,time_t> mSourceFiles;
+    DefaultKeyedVector<String8,time_t> mDestFiles;
+
+    // Pointer to a FileFinder to use
+    FileFinder* mFileFinder;
+};
+
+#endif // CRUNCHCACHE_H
diff --git a/tools/aapt/DirectoryWalker.h b/tools/aapt/DirectoryWalker.h
new file mode 100644
index 0000000..88031d0
--- /dev/null
+++ b/tools/aapt/DirectoryWalker.h
@@ -0,0 +1,98 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+// Defines an abstraction for opening a directory on the filesystem and
+// iterating through it.
+
+#ifndef DIRECTORYWALKER_H
+#define DIRECTORYWALKER_H
+
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utils/String8.h>
+
+#include <stdio.h>
+
+using namespace android;
+
+// Directory Walker
+// This is an abstraction for walking through a directory and getting files
+// and descriptions.
+
+class DirectoryWalker {
+public:
+    virtual ~DirectoryWalker() {};
+    virtual bool openDir(String8 path) = 0;
+    virtual bool openDir(const char* path) = 0;
+    // Advance to next directory entry
+    virtual struct dirent* nextEntry() = 0;
+    // Get the stats for the current entry
+    virtual struct stat*   entryStats() = 0;
+    // Clean Up
+    virtual void closeDir() = 0;
+    // This class is able to replicate itself on the heap
+    virtual DirectoryWalker* clone() = 0;
+
+    // DATA MEMBERS
+    // Current directory entry
+    struct dirent mEntry;
+    // Stats for that directory entry
+    struct stat mStats;
+    // Base path
+    String8 mBasePath;
+};
+
+// System Directory Walker
+// This is an implementation of the above abstraction that calls
+// real system calls and is fully functional.
+// functions are inlined since they're very short and simple
+
+class SystemDirectoryWalker : public DirectoryWalker {
+
+    // Default constructor, copy constructor, and destructor are fine
+public:
+    virtual bool openDir(String8 path) {
+        mBasePath = path;
+        dir = NULL;
+        dir = opendir(mBasePath.string() );
+
+        if (dir == NULL)
+            return false;
+
+        return true;
+    };
+    virtual bool openDir(const char* path) {
+        String8 p(path);
+        openDir(p);
+        return true;
+    };
+    // Advance to next directory entry
+    virtual struct dirent* nextEntry() {
+        struct dirent* entryPtr = readdir(dir);
+        if (entryPtr == NULL)
+            return NULL;
+
+        mEntry = *entryPtr;
+        // Get stats
+        String8 fullPath = mBasePath.appendPathCopy(mEntry.d_name);
+        stat(fullPath.string(),&mStats);
+        return &mEntry;
+    };
+    // Get the stats for the current entry
+    virtual struct stat*   entryStats() {
+        return &mStats;
+    };
+    virtual void closeDir() {
+        closedir(dir);
+    };
+    virtual DirectoryWalker* clone() {
+        return new SystemDirectoryWalker(*this);
+    };
+private:
+    DIR* dir;
+};
+
+#endif // DIRECTORYWALKER_H
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
new file mode 100644
index 0000000..18775c0
--- /dev/null
+++ b/tools/aapt/FileFinder.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+
+// File Finder implementation.
+// Implementation for the functions declared and documented in FileFinder.h
+
+#include <utils/Vector.h>
+#include <utils/String8.h>
+#include <utils/KeyedVector.h>
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "DirectoryWalker.h"
+#include "FileFinder.h"
+
+//#define DEBUG
+
+using android::String8;
+
+// Private function to check whether a file is a directory or not
+bool isDirectory(const char* filename) {
+    struct stat fileStat;
+    if (stat(filename, &fileStat) == -1) {
+        return false;
+    }
+    return(S_ISDIR(fileStat.st_mode));
+}
+
+
+// Private function to check whether a file is a regular file or not
+bool isFile(const char* filename) {
+    struct stat fileStat;
+    if (stat(filename, &fileStat) == -1) {
+        return false;
+    }
+    return(S_ISREG(fileStat.st_mode));
+}
+
+bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions,
+                                 KeyedVector<String8,time_t>& fileStore,
+                                 DirectoryWalker* dw)
+{
+    // Scan the directory pointed to by basePath
+    // check files and recurse into subdirectories.
+    if (!dw->openDir(basePath)) {
+        return false;
+    }
+    /*
+     *  Go through all directory entries. Check each file using checkAndAddFile
+     *  and recurse into sub-directories.
+     */
+    struct dirent* entry;
+    while ((entry = dw->nextEntry()) != NULL) {
+        String8 entryName(entry->d_name);
+        if (entry->d_name[0] == '.') // Skip hidden files and directories
+            continue;
+
+        String8 fullPath = basePath.appendPathCopy(entryName);
+        // If this entry is a directory we'll recurse into it
+        if (isDirectory(fullPath.string()) ) {
+            DirectoryWalker* copy = dw->clone();
+            findFiles(fullPath, extensions, fileStore,copy);
+            delete copy;
+        }
+
+        // If this entry is a file, we'll pass it over to checkAndAddFile
+        if (isFile(fullPath.string()) ) {
+            checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore);
+        }
+    }
+
+    // Clean up
+    dw->closeDir();
+
+    return true;
+}
+
+void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
+                                       Vector<String8>& extensions,
+                                       KeyedVector<String8,time_t>& fileStore)
+{
+    // Loop over the extensions, checking for a match
+    bool done = false;
+    String8 ext(path.getPathExtension());
+    ext.toLower();
+    for (size_t i = 0; i < extensions.size() && !done; ++i) {
+        String8 ext2 = extensions[i].getPathExtension();
+        ext2.toLower();
+        // Compare the extensions. If a match is found, add to storage.
+        if (ext == ext2) {
+            done = true;
+            fileStore.add(path,stats->st_mtime);
+        }
+    }
+}
+
diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h
new file mode 100644
index 0000000..6974aee
--- /dev/null
+++ b/tools/aapt/FileFinder.h
@@ -0,0 +1,80 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+
+// File Finder.
+// This is a collection of useful functions for finding paths and modification
+// times of files that match an extension pattern in a directory tree.
+// and finding files in it.
+
+#ifndef FILEFINDER_H
+#define FILEFINDER_H
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DirectoryWalker.h"
+
+using namespace android;
+
+// Abstraction to allow for dependency injection. See MockFileFinder.h
+// for the testing implementation.
+class FileFinder {
+public:
+    virtual bool findFiles(String8 basePath, Vector<String8>& extensions,
+                           KeyedVector<String8,time_t>& fileStore,
+                           DirectoryWalker* dw) = 0;
+
+    virtual ~FileFinder() {};
+};
+
+class SystemFileFinder : public FileFinder {
+public:
+
+    /* findFiles takes a path, a Vector of extensions, and a destination KeyedVector
+     *           and places path/modification date key/values pointing to
+     *          all files with matching extensions found into the KeyedVector
+     * PRECONDITIONS
+     *     path is a valid system path
+     *     extensions should include leading "."
+     *                This is not necessary, but the comparison directly
+     *                compares the end of the path string so if the "."
+     *                is excluded there is a small chance you could have
+     *                a false positive match. (For example: extension "png"
+     *                would match a file called "blahblahpng")
+     *
+     * POSTCONDITIONS
+     *     fileStore contains (in no guaranteed order) paths to all
+     *                matching files encountered in subdirectories of path
+     *                as keys in the KeyedVector. Each key has the modification time
+     *                of the file as its value.
+     *
+     * Calls checkAndAddFile on each file encountered in the directory tree
+     * Recursively descends into subdirectories.
+     */
+    virtual bool findFiles(String8 basePath, Vector<String8>& extensions,
+                           KeyedVector<String8,time_t>& fileStore,
+                           DirectoryWalker* dw);
+
+private:
+    /**
+     * checkAndAddFile looks at a single file path and stat combo
+     * to determine whether it is a matching file (by looking at
+     * the extension)
+     *
+     * PRECONDITIONS
+     *    no setup is needed
+     *
+     * POSTCONDITIONS
+     *    If the given file has a matching extension then a new entry
+     *    is added to the KeyedVector with the path as the key and the modification
+     *    time as the value.
+     *
+     */
+    static void checkAndAddFile(String8 path, const struct stat* stats,
+                                Vector<String8>& extensions,
+                                KeyedVector<String8,time_t>& fileStore);
+
+};
+#endif // FILEFINDER_H
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 3c471ca..311ceea 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -1080,7 +1080,128 @@
     return error;
 }
 
+status_t preProcessImageToCache(Bundle* bundle, String8 source, String8 dest)
+{
+    png_structp read_ptr = NULL;
+    png_infop read_info = NULL;
 
+    FILE* fp;
+
+    image_info imageInfo;
+
+    png_structp write_ptr = NULL;
+    png_infop write_info = NULL;
+
+    status_t error = UNKNOWN_ERROR;
+
+    // Get a file handler to read from
+    fp = fopen(source.string(),"rb");
+    if (fp == NULL) {
+        fprintf(stderr, "%s ERROR: Unable to open PNG file\n", source.string());
+        return error;
+    }
+
+    // Call libpng to get a struct to read image data into
+    read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!read_ptr) {
+        fclose(fp);
+        png_destroy_read_struct(&read_ptr, &read_info,NULL);
+        return error;
+    }
+
+    // Call libpng to get a struct to read image info into
+    read_info = png_create_info_struct(read_ptr);
+    if (!read_info) {
+        fclose(fp);
+        png_destroy_read_struct(&read_ptr, &read_info,NULL);
+        return error;
+    }
+
+    // Set a jump point for libpng to long jump back to on error
+    if (setjmp(png_jmpbuf(read_ptr))) {
+        fclose(fp);
+        png_destroy_read_struct(&read_ptr, &read_info,NULL);
+        return error;
+    }
+
+    // Set up libpng to read from our file.
+    png_init_io(read_ptr,fp);
+
+    // Actually read data from the file
+    read_png(source.string(), read_ptr, read_info, &imageInfo);
+
+    // We're done reading so we can clean up
+    // Find old file size before releasing handle
+    fseek(fp, 0, SEEK_END);
+    size_t oldSize = (size_t)ftell(fp);
+    fclose(fp);
+    png_destroy_read_struct(&read_ptr, &read_info,NULL);
+
+    // Check to see if we're dealing with a 9-patch
+    // If we are, process appropriately
+    if (source.getBasePath().getPathExtension() == ".9")  {
+        if (do_9patch(source.string(), &imageInfo) != NO_ERROR) {
+            return error;
+        }
+    }
+
+    // Call libpng to create a structure to hold the processed image data
+    // that can be written to disk
+    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!write_ptr) {
+        png_destroy_write_struct(&write_ptr, &write_info);
+        return error;
+    }
+
+    // Call libpng to create a structure to hold processed image info that can
+    // be written to disk
+    write_info = png_create_info_struct(write_ptr);
+    if (!write_info) {
+        png_destroy_write_struct(&write_ptr, &write_info);
+        return error;
+    }
+
+    // Open up our destination file for writing
+    fp = fopen(dest.string(), "wb");
+    if (!fp) {
+        fprintf(stderr, "%s ERROR: Unable to open PNG file\n", dest.string());
+        png_destroy_write_struct(&write_ptr, &write_info);
+        return error;
+    }
+
+    // Set up libpng to write to our file
+    png_init_io(write_ptr, fp);
+
+    // Set up a jump for libpng to long jump back on on errors
+    if (setjmp(png_jmpbuf(write_ptr))) {
+        fclose(fp);
+        png_destroy_write_struct(&write_ptr, &write_info);
+        return error;
+    }
+
+    // Actually write out to the new png
+    write_png(dest.string(), write_ptr, write_info, imageInfo,
+              bundle->getGrayscaleTolerance());
+
+    if (bundle->getVerbose()) {
+        // Find the size of our new file
+        FILE* reader = fopen(dest.string(), "rb");
+        fseek(reader, 0, SEEK_END);
+        size_t newSize = (size_t)ftell(reader);
+        fclose(reader);
+
+        float factor = ((float)newSize)/oldSize;
+        int percent = (int)(factor*100);
+        printf("  (processed image to cache entry %s: %d%% size of source)\n",
+               dest.string(), percent);
+    }
+
+    //Clean up
+    fclose(fp);
+    png_destroy_write_struct(&write_ptr, &write_info);
+
+    return NO_ERROR;
+}
 
 status_t postProcessImage(const sp<AaptAssets>& assets,
                           ResourceTable* table, const sp<AaptFile>& file)
diff --git a/tools/aapt/Images.h b/tools/aapt/Images.h
index 168e22f..4816905 100644
--- a/tools/aapt/Images.h
+++ b/tools/aapt/Images.h
@@ -8,11 +8,19 @@
 #define IMAGES_H
 
 #include "ResourceTable.h"
+#include "Bundle.h"
+
+#include <utils/String8.h>
+#include <utils/RefBase.h>
+
+using android::String8;
 
 status_t preProcessImage(Bundle* bundle, const sp<AaptAssets>& assets,
                          const sp<AaptFile>& file, String8* outNewLeafName);
 
+status_t preProcessImageToCache(Bundle* bundle, String8 source, String8 dest);
+
 status_t postProcessImage(const sp<AaptAssets>& assets,
-						  ResourceTable* table, const sp<AaptFile>& file);
+                          ResourceTable* table, const sp<AaptFile>& file);
 
 #endif
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 1e63131..5135787 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -83,6 +83,9 @@
         " %s a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]\n"
         "   Add specified files to Zip-compatible archive.\n\n", gProgName);
     fprintf(stderr,
+        " %s c[runch] [-v] -S resource-sources ... -C output-folder ...\n"
+        "   Do PNG preprocessing and store the results in output folder.\n\n", gProgName);
+    fprintf(stderr,
         " %s v[ersion]\n"
         "   Print program version.\n\n", gProgName);
     fprintf(stderr,
@@ -145,6 +148,10 @@
         "       inserts android:versionName in to manifest.\n"
         "   --custom-package\n"
         "       generates R.java into a different package.\n"
+        "   --extra-packages\n"
+        "       generate R.java for libraries. Separate libraries with ':'.\n"
+        "   --generate-dependencies\n"
+        "       generate dependency files in the same directories for R.java and resource package\n"
         "   --auto-add-overlay\n"
         "       Automatically add resources that are only in overlays.\n"
         "   --rename-manifest-package\n"
@@ -186,6 +193,7 @@
     case kCommandAdd:       return doAdd(bundle);
     case kCommandRemove:    return doRemove(bundle);
     case kCommandPackage:   return doPackage(bundle);
+    case kCommandCrunch:    return doCrunch(bundle);
     default:
         fprintf(stderr, "%s: requested command not yet supported\n", gProgName);
         return 1;
@@ -223,6 +231,8 @@
         bundle.setCommand(kCommandRemove);
     else if (argv[1][0] == 'p')
         bundle.setCommand(kCommandPackage);
+    else if (argv[1][0] == 'c')
+        bundle.setCommand(kCommandCrunch);
     else {
         fprintf(stderr, "ERROR: Unknown command '%s'\n", argv[1]);
         wantUsage = true;
@@ -393,6 +403,17 @@
                 convertPath(argv[0]);
                 bundle.addResourceSourceDir(argv[0]);
                 break;
+            case 'C':
+                argc--;
+                argv++;
+                if (!argc) {
+                    fprintf(stderr, "ERROR: No argument supplied for '-C' option\n");
+                    wantUsage = true;
+                    goto bail;
+                }
+                convertPath(argv[0]);
+                bundle.setCrunchedOutputDir(argv[0]);
+                break;
             case '0':
                 argc--;
                 argv++;
@@ -475,6 +496,17 @@
                         goto bail;
                     }
                     bundle.setCustomPackage(argv[0]);
+                } else if (strcmp(cp, "-extra-packages") == 0) {
+                    argc--;
+                    argv++;
+                    if (!argc) {
+                        fprintf(stderr, "ERROR: No argument supplied for '--extra-packages' option\n");
+                        wantUsage = true;
+                        goto bail;
+                    }
+                    bundle.setExtraPackages(argv[0]);
+                } else if (strcmp(cp, "-generate-dependencies") == 0) {
+                    bundle.setGenDependencies(true);
                 } else if (strcmp(cp, "-utf16") == 0) {
                     bundle.setWantUTF16(true);
                 } else if (strcmp(cp, "-rename-manifest-package") == 0) {
@@ -508,7 +540,9 @@
                     bundle.setProduct(argv[0]);
                 } else if (strcmp(cp, "-non-constant-id") == 0) {
                     bundle.setNonConstantId(true);
-                } else {
+                } else if (strcmp(cp, "-no-crunch") == 0) {
+                    bundle.setUseCrunchCache(true);
+                }else {
                     fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
                     wantUsage = true;
                     goto bail;
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index 3ba4f39..d20c601 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -14,12 +14,21 @@
 #include "AaptAssets.h"
 #include "ZipFile.h"
 
+
+/* Benchmarking Flag */
+//#define BENCHMARK 1
+
+#if BENCHMARK
+    #include <time.h>
+#endif /* BENCHMARK */
+
 extern int doVersion(Bundle* bundle);
 extern int doList(Bundle* bundle);
 extern int doDump(Bundle* bundle);
 extern int doAdd(Bundle* bundle);
 extern int doRemove(Bundle* bundle);
 extern int doPackage(Bundle* bundle);
+extern int doCrunch(Bundle* bundle);
 
 extern int calcPercent(long uncompressedLen, long compressedLen);
 
@@ -27,6 +36,8 @@
     const sp<AaptAssets>& assets,
     const android::String8& outputFile);
 
+extern android::status_t updatePreProcessedCache(Bundle* bundle);
+
 extern android::status_t buildResources(Bundle* bundle,
     const sp<AaptAssets>& assets);
 
@@ -46,4 +57,6 @@
 String8 getAttribute(const ResXMLTree& tree, const char* ns,
                             const char* attr, String8* outError);
 
+status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets,
+                                FILE* fp, bool includeRaw);
 #endif // __MAIN_H
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index ab71f34..c9f6870 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -50,6 +50,11 @@
 status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets,
                        const String8& outputFile)
 {
+    #if BENCHMARK
+    fprintf(stdout, "BENCHMARK: Starting APK Bundling \n");
+    long startAPKTime = clock();
+    #endif /* BENCHMARK */
+
     status_t result = NO_ERROR;
     ZipFile* zip = NULL;
     int count;
@@ -172,6 +177,16 @@
         }
     }
 
+    if (bundle->getGenDependencies()) {
+        // Add this file to the dependency file
+        String8 dependencyFile = outputFile.getBasePath();
+        dependencyFile.append(".d");
+
+        FILE* fp = fopen(dependencyFile.string(), "a");
+        fprintf(fp, "%s \\\n", outputFile.string());
+        fclose(fp);
+    }
+
     assert(result == NO_ERROR);
 
 bail:
@@ -187,6 +202,10 @@
 
     if (result == NO_ERROR && bundle->getVerbose())
         printf("Done!\n");
+
+    #if BENCHMARK
+    fprintf(stdout, "BENCHMARK: End APK Bundling. Time Elapsed: %f ms \n",(clock() - startAPKTime)/1000.0);
+    #endif /* BENCHMARK */
     return result;
 }
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index b4ac929..cb6484f 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -10,6 +10,10 @@
 #include "ResourceTable.h"
 #include "Images.h"
 
+#include "CrunchCache.h"
+#include "FileFinder.h"
+#include "CacheUpdater.h"
+
 #define NOISY(x) // x
 
 // ==========================================================================
@@ -51,6 +55,12 @@
 {
 }
 
+FilePathStore::FilePathStore()
+    :RefBase(),
+     Vector<String8>()
+{
+}
+
 class ResourceDirIterator
 {
 public:
@@ -287,18 +297,19 @@
 static status_t preProcessImages(Bundle* bundle, const sp<AaptAssets>& assets,
                           const sp<ResourceTypeSet>& set, const char* type)
 {
-    ResourceDirIterator it(set, String8(type));
-    Vector<sp<AaptFile> > newNameFiles;
-    Vector<String8> newNamePaths;
     bool hasErrors = false;
-    ssize_t res;
-    while ((res=it.next()) == NO_ERROR) {
-        res = preProcessImage(bundle, assets, it.getFile(), NULL);
-        if (res < NO_ERROR) {
-            hasErrors = true;
+    ssize_t res = NO_ERROR;
+    if (bundle->getUseCrunchCache() == false) {
+        ResourceDirIterator it(set, String8(type));
+        Vector<sp<AaptFile> > newNameFiles;
+        Vector<String8> newNamePaths;
+        while ((res=it.next()) == NO_ERROR) {
+            res = preProcessImage(bundle, assets, it.getFile(), NULL);
+            if (res < NO_ERROR) {
+                hasErrors = true;
+            }
         }
     }
-
     return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
 }
 
@@ -748,6 +759,35 @@
             } \
         } while (0)
 
+status_t updatePreProcessedCache(Bundle* bundle)
+{
+    #if BENCHMARK
+    fprintf(stdout, "BENCHMARK: Starting PNG PreProcessing \n");
+    long startPNGTime = clock();
+    #endif /* BENCHMARK */
+
+    String8 source(bundle->getResourceSourceDirs()[0]);
+    String8 dest(bundle->getCrunchedOutputDir());
+
+    FileFinder* ff = new SystemFileFinder();
+    CrunchCache cc(source,dest,ff);
+
+    CacheUpdater* cu = new SystemCacheUpdater(bundle);
+    size_t numFiles = cc.crunch(cu);
+
+    if (bundle->getVerbose())
+        fprintf(stdout, "Crunched %d PNG files to update cache\n", (int)numFiles);
+
+    delete ff;
+    delete cu;
+
+    #if BENCHMARK
+    fprintf(stdout, "BENCHMARK: End PNG PreProcessing. Time Elapsed: %f ms \n"
+            ,(clock() - startPNGTime)/1000.0);
+    #endif /* BENCHMARK */
+    return 0;
+}
+
 status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
 {
     // First, look for a package file to parse.  This is required to
@@ -1917,6 +1957,16 @@
             return err;
         }
         fclose(fp);
+
+        if (bundle->getGenDependencies()) {
+            // Add this R.java to the dependency file
+            String8 dependencyFile(bundle->getRClassDir());
+            dependencyFile.appendPath("R.d");
+
+            fp = fopen(dependencyFile.string(), "a");
+            fprintf(fp,"%s \\\n", dest.string());
+            fclose(fp);
+        }
     }
 
     return NO_ERROR;
@@ -2244,3 +2294,27 @@
 
     return err;
 }
+
+// Loops through the string paths and writes them to the file pointer
+// Each file path is written on its own line with a terminating backslash.
+status_t writePathsToFile(const sp<FilePathStore>& files, FILE* fp)
+{
+    status_t deps = -1;
+    for (size_t file_i = 0; file_i < files->size(); ++file_i) {
+        // Add the full file path to the dependency file
+        fprintf(fp, "%s \\\n", files->itemAt(file_i).string());
+        deps++;
+    }
+    return deps;
+}
+
+status_t
+writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp, bool includeRaw)
+{
+    status_t deps = -1;
+    deps += writePathsToFile(assets->getFullResPaths(), fp);
+    if (includeRaw) {
+        deps += writePathsToFile(assets->getFullAssetPaths(), fp);
+    }
+    return deps;
+}
diff --git a/tools/aapt/tests/CrunchCache_test.cpp b/tools/aapt/tests/CrunchCache_test.cpp
new file mode 100644
index 0000000..20b5022
--- /dev/null
+++ b/tools/aapt/tests/CrunchCache_test.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+#include <utils/String8.h>
+#include <iostream>
+#include <errno.h>
+
+#include "CrunchCache.h"
+#include "FileFinder.h"
+#include "MockFileFinder.h"
+#include "CacheUpdater.h"
+#include "MockCacheUpdater.h"
+
+using namespace android;
+using std::cout;
+using std::endl;
+
+void expectEqual(int got, int expected, const char* desc) {
+    cout << "Checking " << desc << ": ";
+    cout << "Got " << got << ", expected " << expected << "...";
+    cout << ( (got == expected) ? "PASSED" : "FAILED") << endl;
+    errno += ((got == expected) ? 0 : 1);
+}
+
+int main() {
+
+    errno = 0;
+
+    String8 source("res");
+    String8 dest("res2");
+
+    // Create data for MockFileFinder to feed to the cache
+    KeyedVector<String8, time_t> sourceData;
+    // This shouldn't be updated
+    sourceData.add(String8("res/drawable/hello.png"),3);
+    // This should be updated
+    sourceData.add(String8("res/drawable/world.png"),5);
+    // This should cause make directory to be called
+    sourceData.add(String8("res/drawable-cool/hello.png"),3);
+
+    KeyedVector<String8, time_t> destData;
+    destData.add(String8("res2/drawable/hello.png"),3);
+    destData.add(String8("res2/drawable/world.png"),3);
+    // this should call delete
+    destData.add(String8("res2/drawable/dead.png"),3);
+
+    // Package up data and create mock file finder
+    KeyedVector<String8, KeyedVector<String8,time_t> > data;
+    data.add(source,sourceData);
+    data.add(dest,destData);
+    FileFinder* ff = new MockFileFinder(data);
+    CrunchCache cc(source,dest,ff);
+
+    MockCacheUpdater* mcu = new MockCacheUpdater();
+    CacheUpdater* cu(mcu);
+
+    cout << "Running Crunch...";
+    int result = cc.crunch(cu);
+    cout << ((result > 0) ? "PASSED" : "FAILED") << endl;
+    errno += ((result > 0) ? 0 : 1);
+
+    const int EXPECTED_RESULT = 2;
+    expectEqual(result, EXPECTED_RESULT, "number of files touched");
+
+    cout << "Checking calls to deleteFile and processImage:" << endl;
+    const int EXPECTED_DELETES = 1;
+    const int EXPECTED_PROCESSED = 2;
+    // Deletes
+    expectEqual(mcu->deleteCount, EXPECTED_DELETES, "deleteFile");
+    // processImage
+    expectEqual(mcu->processCount, EXPECTED_PROCESSED, "processImage");
+
+    const int EXPECTED_OVERWRITES = 3;
+    result = cc.crunch(cu, true);
+    expectEqual(result, EXPECTED_OVERWRITES, "number of files touched with overwrite");
+    \
+
+    if (errno == 0)
+        cout << "ALL TESTS PASSED!" << endl;
+    else
+        cout << errno << " TESTS FAILED" << endl;
+
+    delete ff;
+    delete cu;
+
+    // TESTS BELOW WILL GO AWAY SOON
+
+    String8 source2("ApiDemos/res");
+    String8 dest2("ApiDemos/res2");
+
+    FileFinder* sff = new SystemFileFinder();
+    CacheUpdater* scu = new SystemCacheUpdater();
+
+    CrunchCache scc(source2,dest2,sff);
+
+    scc.crunch(scu);
+}
\ No newline at end of file
diff --git a/tools/aapt/tests/FileFinder_test.cpp b/tools/aapt/tests/FileFinder_test.cpp
new file mode 100644
index 0000000..07bd665
--- /dev/null
+++ b/tools/aapt/tests/FileFinder_test.cpp
@@ -0,0 +1,101 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <iostream>
+#include <cassert>
+#include <utils/String8.h>
+#include <utility>
+
+#include "DirectoryWalker.h"
+#include "MockDirectoryWalker.h"
+#include "FileFinder.h"
+
+using namespace android;
+
+using std::pair;
+using std::cout;
+using std::endl;
+
+
+
+int main()
+{
+
+    cout << "\n\n STARTING FILE FINDER TESTS" << endl;
+    String8 path("ApiDemos");
+
+    // Storage to pass to findFiles()
+    KeyedVector<String8,time_t> testStorage;
+
+    // Mock Directory Walker initialization. First data, then sdw
+    Vector< pair<String8,time_t> > data;
+    data.push( pair<String8,time_t>(String8("hello.png"),3) );
+    data.push( pair<String8,time_t>(String8("world.PNG"),3) );
+    data.push( pair<String8,time_t>(String8("foo.pNg"),3) );
+    // Neither of these should be found
+    data.push( pair<String8,time_t>(String8("hello.jpg"),3) );
+    data.push( pair<String8,time_t>(String8(".hidden.png"),3));
+
+    DirectoryWalker* sdw = new StringDirectoryWalker(path,data);
+
+    // Extensions to look for
+    Vector<String8> exts;
+    exts.push(String8(".png"));
+
+    errno = 0;
+
+    // Make sure we get a valid mock directory walker
+    // Make sure we finish without errors
+    cout << "Checking DirectoryWalker...";
+    assert(sdw != NULL);
+    cout << "PASSED" << endl;
+
+    // Make sure we finish without errors
+    cout << "Running findFiles()...";
+    bool findStatus = FileFinder::findFiles(path,exts, testStorage, sdw);
+    assert(findStatus);
+    cout << "PASSED" << endl;
+
+    const size_t SIZE_EXPECTED = 3;
+    // Check to make sure we have the right number of things in our storage
+    cout << "Running size comparison: Size is " << testStorage.size() << ", ";
+    cout << "Expected " << SIZE_EXPECTED << "...";
+    if(testStorage.size() == SIZE_EXPECTED)
+        cout << "PASSED" << endl;
+    else {
+        cout << "FAILED" << endl;
+        errno++;
+    }
+
+    // Check to make sure that each of our found items has the right extension
+    cout << "Checking Returned Extensions...";
+    bool extsOkay = true;
+    String8 wrongExts;
+    for (size_t i = 0; i < SIZE_EXPECTED; ++i) {
+        String8 testExt(testStorage.keyAt(i).getPathExtension());
+        testExt.toLower();
+        if (testExt != ".png") {
+            wrongExts += testStorage.keyAt(i);
+            wrongExts += "\n";
+            extsOkay = false;
+        }
+    }
+    if (extsOkay)
+        cout << "PASSED" << endl;
+    else {
+        cout << "FAILED" << endl;
+        cout << "The following extensions didn't check out" << endl << wrongExts;
+    }
+
+    // Clean up
+    delete sdw;
+
+    if(errno == 0) {
+        cout << "ALL TESTS PASSED" << endl;
+    } else {
+        cout << errno << " TESTS FAILED" << endl;
+    }
+    return errno;
+}
\ No newline at end of file
diff --git a/tools/aapt/tests/MockCacheUpdater.h b/tools/aapt/tests/MockCacheUpdater.h
new file mode 100644
index 0000000..c7f4bd7
--- /dev/null
+++ b/tools/aapt/tests/MockCacheUpdater.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+#ifndef MOCKCACHEUPDATER_H
+#define MOCKCACHEUPDATER_H
+
+#include <utils/String8.h>
+#include "CacheUpdater.h"
+
+using namespace android;
+
+class MockCacheUpdater : public CacheUpdater {
+public:
+
+    MockCacheUpdater()
+        : deleteCount(0), processCount(0) { };
+
+    // Make sure all the directories along this path exist
+    virtual void ensureDirectoriesExist(String8 path)
+    {
+        // Nothing to do
+    };
+
+    // Delete a file
+    virtual void deleteFile(String8 path) {
+        deleteCount++;
+    };
+
+    // Process an image from source out to dest
+    virtual void processImage(String8 source, String8 dest) {
+        processCount++;
+    };
+
+    // DATA MEMBERS
+    int deleteCount;
+    int processCount;
+private:
+};
+
+#endif // MOCKCACHEUPDATER_H
\ No newline at end of file
diff --git a/tools/aapt/tests/MockDirectoryWalker.h b/tools/aapt/tests/MockDirectoryWalker.h
new file mode 100644
index 0000000..5900cf3
--- /dev/null
+++ b/tools/aapt/tests/MockDirectoryWalker.h
@@ -0,0 +1,85 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+#ifndef MOCKDIRECTORYWALKER_H
+#define MOCKDIRECTORYWALKER_H
+
+#include <utils/Vector.h>
+#include <utils/String8.h>
+#include <utility>
+#include "DirectoryWalker.h"
+
+using namespace android;
+using std::pair;
+
+// String8 Directory Walker
+// This is an implementation of the Directory Walker abstraction that is built
+// for testing.
+// Instead of system calls it queries a private data structure for the directory
+// entries. It takes a path and a map of filenames and their modification times.
+// functions are inlined since they are short and simple
+
+class StringDirectoryWalker : public DirectoryWalker {
+public:
+    StringDirectoryWalker(String8& path, Vector< pair<String8,time_t> >& data)
+        :  mPos(0), mBasePath(path), mData(data) {
+        //fprintf(stdout,"StringDW built to mimic %s with %d files\n",
+        //       mBasePath.string());
+    };
+    // Default copy constructor, and destructor are fine
+
+    virtual bool openDir(String8 path) {
+        // If the user is trying to query the "directory" that this
+        // walker was initialized with, then return success. Else fail.
+        return path == mBasePath;
+    };
+    virtual bool openDir(const char* path) {
+        String8 p(path);
+        openDir(p);
+        return true;
+    };
+    // Advance to next entry in the Vector
+    virtual struct dirent* nextEntry() {
+        // Advance position and check to see if we're done
+        if (mPos >= mData.size())
+            return NULL;
+
+        // Place data in the entry descriptor. This class only returns files.
+        mEntry.d_type = DT_REG;
+        mEntry.d_ino = mPos;
+        // Copy chars from the string name to the entry name
+        size_t i = 0;
+        for (i; i < mData[mPos].first.size(); ++i)
+            mEntry.d_name[i] = mData[mPos].first[i];
+        mEntry.d_name[i] = '\0';
+
+        // Place data in stats
+        mStats.st_ino = mPos;
+        mStats.st_mtime = mData[mPos].second;
+
+        // Get ready to move to the next entry
+        mPos++;
+
+        return &mEntry;
+    };
+    // Get the stats for the current entry
+    virtual struct stat*   entryStats() {
+        return &mStats;
+    };
+    // Nothing to do in clean up
+    virtual void closeDir() {
+        // Nothing to do
+    };
+    virtual DirectoryWalker* clone() {
+        return new StringDirectoryWalker(*this);
+    };
+private:
+    // Current position in the Vector
+    size_t mPos;
+    // Base path
+    String8 mBasePath;
+    // Data to simulate a directory full of files.
+    Vector< pair<String8,time_t> > mData;
+};
+
+#endif // MOCKDIRECTORYWALKER_H
\ No newline at end of file
diff --git a/tools/aapt/tests/MockFileFinder.h b/tools/aapt/tests/MockFileFinder.h
new file mode 100644
index 0000000..da5ea4f
--- /dev/null
+++ b/tools/aapt/tests/MockFileFinder.h
@@ -0,0 +1,55 @@
+//
+// Copyright 2011 The Android Open Source Project
+//
+
+#ifndef MOCKFILEFINDER_H
+#define MOCKFILEFINDER_H
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DirectoryWalker.h"
+
+using namespace android;
+
+class MockFileFinder : public FileFinder {
+public:
+    MockFileFinder (KeyedVector<String8, KeyedVector<String8,time_t> >& files)
+        : mFiles(files)
+    {
+        // Nothing left to do
+    };
+
+    /**
+     * findFiles implementation for the abstraction.
+     * PRECONDITIONS:
+     *  No checking is done, so there MUST be an entry in mFiles with
+     *  path matching basePath.
+     *
+     * POSTCONDITIONS:
+     *  fileStore is filled with a copy of the data in mFiles corresponding
+     *  to the basePath.
+     */
+
+    virtual bool findFiles(String8 basePath, Vector<String8>& extensions,
+                           KeyedVector<String8,time_t>& fileStore,
+                           DirectoryWalker* dw)
+    {
+        const KeyedVector<String8,time_t>* payload(&mFiles.valueFor(basePath));
+        // Since KeyedVector doesn't implement swap
+        // (who doesn't use swap??) we loop and add one at a time.
+        for (size_t i = 0; i < payload->size(); ++i) {
+            fileStore.add(payload->keyAt(i),payload->valueAt(i));
+        }
+        return true;
+    }
+
+private:
+    // Virtual mapping between "directories" and the "files" contained
+    // in them
+    KeyedVector<String8, KeyedVector<String8,time_t> > mFiles;
+};
+
+
+#endif // MOCKFILEFINDER_H
\ No newline at end of file
diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp
index a44072d..6b69864 100755
--- a/tools/aidl/Type.cpp
+++ b/tools/aidl/Type.cpp
@@ -198,7 +198,7 @@
 }
 
 void
-Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -207,7 +207,7 @@
 }
 
 void
-Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -226,7 +226,7 @@
 
 void
 Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -235,7 +235,7 @@
 }
 
 void
-Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -284,7 +284,7 @@
 }
 
 void
-BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallMethod)));
 }
@@ -303,13 +303,13 @@
 
 void
 BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayMethod)));
 }
 
 void
-BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, m_readArrayMethod, 1, v));
 }
@@ -331,7 +331,7 @@
 }
 
 void
-BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new Comparison(new LiteralExpression("0"),
                     "!=", new MethodCall(parcel, "readInt"))));
@@ -351,13 +351,13 @@
 
 void
 BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray")));
 }
 
 void
-BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v));
 }
@@ -378,7 +378,7 @@
 }
 
 void
-CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this));
 }
@@ -397,13 +397,13 @@
 
 void
 CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray")));
 }
 
 void
-CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readCharArray", 1, v));
 }
@@ -428,7 +428,7 @@
 }
 
 void
-StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readString")));
 }
@@ -447,13 +447,13 @@
 
 void
 StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray")));
 }
 
 void
-StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readStringArray", 1, v));
 }
@@ -496,7 +496,7 @@
 
 void
 CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                Variable* parcel)
+                                Variable* parcel, Variable**)
 {
     // if (0 != parcel.readInt()) {
     //     v = TextUtils.createFromParcel(parcel)
@@ -532,7 +532,7 @@
 }
 
 void
-RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -551,7 +551,7 @@
 }
 
 void
-RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -571,7 +571,7 @@
 }
 
 void
-IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder")));
 }
@@ -584,13 +584,13 @@
 
 void
 IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray")));
 }
 
 void
-IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v));
 }
@@ -610,7 +610,7 @@
 }
 
 void
-IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -631,7 +631,7 @@
 
 void
 BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel)
+                                    Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -652,7 +652,7 @@
 
 void
 BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel)
+                                    Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -672,7 +672,7 @@
 }
 
 void
-ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -691,7 +691,7 @@
 }
 
 void
-ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -709,25 +709,31 @@
     addTo->Add(new MethodCall(parcel, "writeMap", 1, v));
 }
 
-void
-MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+static void EnsureClassLoader(StatementBlock* addTo, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl,
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, cl)));
+    // We don't want to look up the class loader once for every
+    // collection argument, so ensure we do it at most once per method.
+    if (*cl == NULL) {
+        *cl = new Variable(CLASSLOADER_TYPE, "cl");
+        addTo->Add(new VariableDeclaration(*cl,
+                new LiteralExpression("this.getClass().getClassLoader()"),
+                CLASSLOADER_TYPE));
+    }
+}
+
+void
+MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl)
+{
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, *cl)));
 }
 
 void
 MapType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new MethodCall(parcel, "readMap", 2, v, cl));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new MethodCall(parcel, "readMap", 2, v, *cl));
 }
 
 
@@ -751,24 +757,18 @@
 }
 
 void
-ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, cl)));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, *cl)));
 }
 
 void
 ListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new MethodCall(parcel, "readList", 2, v, cl));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new MethodCall(parcel, "readList", 2, v, *cl));
 }
 
 
@@ -811,7 +811,7 @@
 }
 
 void
-ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     // if (0 != parcel.readInt()) {
     //     v = CLASS.CREATOR.createFromParcel(parcel)
@@ -833,7 +833,7 @@
 
 void
 ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable**)
 {
     // TODO: really, we don't need to have this extra check, but we
     // don't have two separate marshalling code paths
@@ -862,7 +862,7 @@
 
 void
 ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
     addTo->Add(new Assignment(v, new MethodCall(parcel,
@@ -870,7 +870,7 @@
 }
 
 void
-ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
     addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
@@ -907,7 +907,7 @@
 }
 
 void
-InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     // v = Interface.asInterface(parcel.readStrongBinder());
     string type = v->type->QualifiedName();
@@ -961,14 +961,14 @@
 }
 
 void
-GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "implement GenericType::CreateFromParcel\n");
 }
 
 void
 GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     fprintf(stderr, "implement GenericType::ReadFromParcel\n");
 }
@@ -1009,7 +1009,7 @@
 }
 
 void
-GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     if (m_creator == STRING_TYPE->CreatorName()) {
         addTo->Add(new Assignment(v,
@@ -1027,7 +1027,7 @@
 
 void
 GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     if (m_creator == STRING_TYPE->CreatorName()) {
         addTo->Add(new MethodCall(parcel, "readStringList", 1, v));
diff --git a/tools/aidl/Type.h b/tools/aidl/Type.h
index 2ea3ac9..662e3a2 100755
--- a/tools/aidl/Type.h
+++ b/tools/aidl/Type.h
@@ -46,18 +46,18 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
 protected:
     void SetQualifiedName(const string& qualified);
@@ -89,16 +89,16 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
 private:
     string m_marshallMethod;
@@ -116,16 +116,16 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class CharType : public Type
@@ -136,16 +136,16 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 
@@ -159,16 +159,16 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class CharSequenceType : public Type
@@ -181,7 +181,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class RemoteExceptionType : public Type
@@ -192,7 +192,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class RuntimeExceptionType : public Type
@@ -203,7 +203,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class IBinderType : public Type
@@ -214,14 +214,14 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class IInterfaceType : public Type
@@ -232,7 +232,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class BinderType : public Type
@@ -243,7 +243,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class BinderProxyType : public Type
@@ -254,7 +254,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class ParcelType : public Type
@@ -265,7 +265,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class ParcelableInterfaceType : public Type
@@ -276,7 +276,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class MapType : public Type
@@ -287,9 +287,9 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class ListType : public Type
@@ -302,9 +302,9 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class ParcelableType : public Type
@@ -318,18 +318,18 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
     virtual bool    CanBeArray() const;
 
     virtual void    WriteArrayToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 };
 
 class InterfaceType : public Type
@@ -344,7 +344,7 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
                                     
 private:
     bool m_oneway;
@@ -364,9 +364,9 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
 private:
     string m_genericArguments;
@@ -387,9 +387,9 @@
     virtual void    WriteToParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, int flags);
     virtual void    CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
     virtual void    ReadFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel);
+                                    Variable* parcel, Variable** cl);
 
 private:
     string m_creator;
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index f17f66b..92f5b64 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -948,8 +948,6 @@
 int
 main(int argc, const char **argv)
 {
-    int err = 0;
-
     Options options;
     int result = parse_options(argc, argv, &options);
     if (result) {
diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp
index 0f18132..83e3bbc 100644
--- a/tools/aidl/generate_java.cpp
+++ b/tools/aidl/generate_java.cpp
@@ -286,25 +286,25 @@
 
 static void
 generate_create_from_parcel(Type* t, StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable** cl)
 {
     if (v->dimension == 0) {
-        t->CreateFromParcel(addTo, v, parcel);
+        t->CreateFromParcel(addTo, v, parcel, cl);
     }
     if (v->dimension == 1) {
-        t->CreateArrayFromParcel(addTo, v, parcel);
+        t->CreateArrayFromParcel(addTo, v, parcel, cl);
     }
 }
 
 static void
 generate_read_from_parcel(Type* t, StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable** cl)
 {
     if (v->dimension == 0) {
-        t->ReadFromParcel(addTo, v, parcel);
+        t->ReadFromParcel(addTo, v, parcel, cl);
     }
     if (v->dimension == 1) {
-        t->ReadArrayFromParcel(addTo, v, parcel);
+        t->ReadArrayFromParcel(addTo, v, parcel, cl);
     }
 }
 
@@ -362,6 +362,7 @@
             "enforceInterface", 1, new LiteralExpression("DESCRIPTOR")));
 
     // args
+    Variable* cl = NULL;
     VariableFactory stubArgs("_arg");
     arg = method->args;
     while (arg != NULL) {
@@ -373,7 +374,7 @@
 
         if (convert_direction(arg->direction.data) & IN_PARAMETER) {
             generate_create_from_parcel(t, c->statements, v,
-                    stubClass->transact_data);
+                    stubClass->transact_data, &cl);
         } else {
             if (arg->type.dimension == 0) {
                 c->statements->Add(new Assignment(
@@ -531,7 +532,7 @@
     if (_reply != NULL) {
         if (_result != NULL) {
             generate_create_from_parcel(proxy->returnType,
-                                    tryStatement->statements, _result, _reply);
+                    tryStatement->statements, _result, _reply, &cl);
         }
 
         // the out/inout parameters
@@ -541,7 +542,7 @@
             Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
             if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
                 generate_read_from_parcel(t, tryStatement->statements,
-                                            v, _reply);
+                                            v, _reply, &cl);
             }
             arg = arg->next;
         }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index b4448a9..8e3ed93 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1093,33 +1093,6 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextWithGlyphs(int nativeCanvas, char[] text,
-            int index, int count, float x,
-            float y, int flags, int paint) {
-        native_drawText(nativeCanvas, text, index, count, x, y, flags, paint);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void native_drawTextWithGlyphs(int nativeCanvas, String text,
-            int start, int end, float x,
-            float y, int flags, int paint) {
-        int count = end - start;
-        char[] buffer = TemporaryBuffer.obtain(count);
-        TextUtils.getChars(text, start, end, buffer, 0);
-
-        native_drawText(nativeCanvas, text, 0, count, x, y, flags, paint);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void native_drawGlyphs(int nativeCanvas, char[] glyphs,
-            int index, int count, float x,
-            float y, int flags, int paint) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Canvas.drawGlyphs is not supported.", null, null /*data*/);
-    }
-
-    @LayoutlibDelegate
     /*package*/ static void native_drawPosText(int nativeCanvas,
                                                   char[] text, int index,
                                                   int count, float[] pos,
diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
new file mode 100644
index 0000000..52b8f34
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+
+/**
+ * Delegate used to provide new implementation for the native methods of {@link AndroidBidi}
+ *
+ * Through the layoutlib_create tool, the original  methods of AndroidBidi have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class AndroidBidi_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static int runBidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo) {
+        // return the equivalent of Layout.DIR_LEFT_TO_RIGHT
+        // TODO: actually figure the direction.
+        return 0;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
index ec7a67e..f056040 100644
--- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
@@ -19,6 +19,7 @@
 import com.android.layoutlib.bridge.android.BridgeIInputMethodManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.content.Context;
 import android.os.Looper;
 
 
@@ -44,6 +45,18 @@
                     mainLooper);
         }
         return InputMethodManager.mInstance;
+    }
 
+    @LayoutlibDelegate
+    /*package*/ static InputMethodManager getInstance(Context context) {
+        synchronized (InputMethodManager.mInstanceSync) {
+            if (InputMethodManager.mInstance != null) {
+                return InputMethodManager.mInstance;
+            }
+
+            InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
+                    Looper.myLooper());
+        }
+        return InputMethodManager.mInstance;
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 1394c32..23e0ca1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -107,7 +107,7 @@
 
     }
 
-    public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
+    public boolean setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
             throws RemoteException {
         // TODO Auto-generated method stub
         return false;
@@ -188,4 +188,10 @@
         return null;
     }
 
+    public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 260cdc8..fc2f2f8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -131,6 +131,10 @@
      */
     @Override
     public CharSequence getText(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (mResourceData[index] != null) {
             // FIXME: handle styled strings!
             return mResourceData[index].getValue();
@@ -149,6 +153,10 @@
      */
     @Override
     public String getString(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (mResourceData[index] != null) {
             return mResourceData[index].getValue();
         }
@@ -166,6 +174,10 @@
      */
     @Override
     public boolean getBoolean(int index, boolean defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -188,6 +200,10 @@
      */
     @Override
     public int getInt(int index, int defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -252,6 +268,10 @@
      */
     @Override
     public float getFloat(int index, float defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -287,6 +307,10 @@
      */
     @Override
     public int getColor(int index, int defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -311,6 +335,10 @@
      */
     @Override
     public ColorStateList getColorStateList(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (mResourceData[index] == null) {
             return null;
         }
@@ -395,6 +423,10 @@
      */
     @Override
     public float getDimension(int index, float defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -568,6 +600,10 @@
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         if (mResourceData[index] == null) {
             return defValue;
         }
@@ -607,6 +643,10 @@
      */
     @Override
     public int getResourceId(int index, int defValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return defValue;
+        }
+
         // get the Resource for this index
         ResourceValue resValue = mResourceData[index];
 
@@ -718,6 +758,10 @@
      */
     @Override
     public Drawable getDrawable(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (mResourceData[index] == null) {
             return null;
         }
@@ -744,6 +788,10 @@
      */
     @Override
     public CharSequence[] getTextArray(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (mResourceData[index] == null) {
             return null;
         }
@@ -776,6 +824,10 @@
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
+        if (index < 0 || index >= mResourceData.length) {
+            return false;
+        }
+
         if (mResourceData[index] == null) {
             return false;
         }
@@ -795,6 +847,10 @@
      */
     @Override
     public boolean hasValue(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return false;
+        }
+
         return mResourceData[index] != null;
     }
 
@@ -811,6 +867,10 @@
      */
     @Override
     public TypedValue peekValue(int index) {
+        if (index < 0 || index >= mResourceData.length) {
+            return null;
+        }
+
         if (getValue(index, mValue)) {
             return mValue;
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 13cd9ec..d94f369 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -76,6 +76,9 @@
     public void getDisplaySize(Point arg0) throws RemoteException {
     }
 
+    public void getRealDisplaySize(Point arg0) throws RemoteException {
+    }
+
     // ---- unused implementation of IWindowManager ----
 
     public boolean canStatusBarHide() throws RemoteException {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index df7e04f..93a35cc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -155,6 +155,7 @@
         "android.graphics.Typeface",
         "android.graphics.Xfermode",
         "android.os.SystemClock",
+        "android.text.AndroidBidi",
         "android.util.FloatMath",
         "android.view.Display",
         "libcore.icu.ICU",
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
index 49ddf1d..0e24cc0 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
@@ -117,8 +117,10 @@
 
         int accessDelegate = access;
         // change access to public for the original one
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
 
         MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
                                                      desc, signature, exceptions);
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index ce48069..9bf52c7 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -37,7 +37,7 @@
  * which does:
  * <pre>
  * $ make layoutlib_create &lt;bunch of framework jars&gt;
- * $ out/host/linux-x86/framework/bin/layoutlib_create \
+ * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \
  *        out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \
  *        out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \
  *        out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
@@ -45,6 +45,12 @@
  */
 public class Main {
 
+    public static class Options {
+        public boolean generatePublicAccess = true;
+    }
+
+    public static final Options sOptions = new Options();
+
     public static void main(String[] args) {
 
         Log log = new Log();
@@ -53,7 +59,7 @@
         String[] osDestJar = { null };
 
         if (!processArgs(log, args, osJarPath, osDestJar)) {
-            log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
+            log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ...");
             System.exit(1);
         }
 
@@ -136,6 +142,8 @@
             String s = args[i];
             if (s.equals("-v")) {
                 log.setVerbose(true);
+            } else if (s.equals("-p")) {
+                sOptions.generatePublicAccess = false;
             } else if (!s.startsWith("-")) {
                 if (osDestJar[0] == null) {
                     osDestJar[0] = s;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
index f2d9755..5a0a44a4 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
@@ -72,8 +72,10 @@
         name = mClassName;
 
         // remove protected or private and set as public
-        access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
         // note: leave abstract classes as such
@@ -87,8 +89,10 @@
     @Override
     public void visitInnerClass(String name, String outerName, String innerName, int access) {
         // remove protected or private and set as public
-        access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
         // note: leave abstract classes as such
@@ -117,8 +121,10 @@
         String methodSignature = mClassName.replace('/', '.') + "#" + name;
 
         // change access to public
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
 
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
@@ -155,9 +161,10 @@
     public FieldVisitor visitField(int access, String name, String desc, String signature,
             Object value) {
         // change access to public
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
-
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         return super.visitField(access, name, desc, signature, value);
     }
 
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index c1affa6..fcdbd2c 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -57,6 +57,7 @@
     private static final boolean RELEASE_SOCKET = true;
     private static final boolean DONT_RELEASE_SOCKET = false;
     private static final int SESSION_TIMEOUT = 5; // in seconds
+    private static final int TRANSFER_TIMEOUT = 15; // in seconds
 
     /** Listener for events relating to a SIP call, such as when a call is being
      * recieved ("on ringing") or a call is outgoing ("on calling").
@@ -537,10 +538,14 @@
                 Log.v(TAG, "onCallTransferring mSipSession:"
                         + mSipSession + " newSession:" + newSession);
                 mTransferringSession = newSession;
-                // session changing request
                 try {
-                    String answer = createAnswer(sessionDescription).encode();
-                    newSession.answerCall(answer, SESSION_TIMEOUT);
+                    if (sessionDescription == null) {
+                        newSession.makeCall(newSession.getPeerProfile(),
+                                createOffer().encode(), TRANSFER_TIMEOUT);
+                    } else {
+                        String answer = createAnswer(sessionDescription).encode();
+                        newSession.answerCall(answer, SESSION_TIMEOUT);
+                    }
                 } catch (Throwable e) {
                     Log.e(TAG, "onCallTransferring()", e);
                     newSession.endCall();
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index c031bc1..dc628e0 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -19,6 +19,9 @@
 import gov.nist.javax.sip.SipStackExt;
 import gov.nist.javax.sip.clientauthutils.AccountManager;
 import gov.nist.javax.sip.clientauthutils.AuthenticationHelper;
+import gov.nist.javax.sip.header.extensions.ReferencesHeader;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
 
 import android.net.sip.SipProfile;
 import android.util.Log;
@@ -284,14 +287,18 @@
     }
 
     public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
-            String sessionDescription, String tag)
-            throws SipException {
+            String sessionDescription, String tag, ReferredByHeader referredBy,
+            String replaces) throws SipException {
         try {
             Request request = createRequest(Request.INVITE, caller, callee, tag);
+            if (referredBy != null) request.addHeader(referredBy);
+            if (replaces != null) {
+                request.addHeader(mHeaderFactory.createHeader(
+                        ReplacesHeader.NAME, replaces));
+            }
             request.setContent(sessionDescription,
                     mHeaderFactory.createContentTypeHeader(
                             "application", "sdp"));
-
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
             if (DEBUG) Log.d(TAG, "send INVITE: " + request);
@@ -455,6 +462,25 @@
         }
     }
 
+    public void sendReferNotify(Dialog dialog, String content)
+            throws SipException {
+        try {
+            Request request = dialog.createRequest(Request.NOTIFY);
+            request.addHeader(mHeaderFactory.createSubscriptionStateHeader(
+                    "active;expires=60"));
+            // set content here
+            request.setContent(content,
+                    mHeaderFactory.createContentTypeHeader(
+                            "message", "sipfrag"));
+            request.addHeader(mHeaderFactory.createEventHeader(
+                    ReferencesHeader.REFER));
+            if (DEBUG) Log.d(TAG, "send NOTIFY: " + request);
+            dialog.sendRequest(mSipProvider.getNewClientTransaction(request));
+        } catch (ParseException e) {
+            throw new SipException("sendReferNotify()", e);
+        }
+    }
+
     public void sendInviteRequestTerminated(Request inviteRequest,
             ServerTransaction inviteTransaction) throws SipException {
         try {
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 4e44402..48d9b17 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -18,12 +18,15 @@
 
 import gov.nist.javax.sip.clientauthutils.AccountManager;
 import gov.nist.javax.sip.clientauthutils.UserCredentials;
-import gov.nist.javax.sip.header.SIPHeaderNames;
 import gov.nist.javax.sip.header.ProxyAuthenticate;
+import gov.nist.javax.sip.header.ReferTo;
+import gov.nist.javax.sip.header.SIPHeaderNames;
+import gov.nist.javax.sip.header.StatusLine;
 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 gov.nist.javax.sip.message.SIPResponse;
 
 import android.net.sip.ISipSession;
 import android.net.sip.ISipSessionListener;
@@ -71,12 +74,15 @@
 import javax.sip.header.CSeqHeader;
 import javax.sip.header.ExpiresHeader;
 import javax.sip.header.FromHeader;
+import javax.sip.header.HeaderAddress;
 import javax.sip.header.MinExpiresHeader;
+import javax.sip.header.ReferToHeader;
 import javax.sip.header.ViaHeader;
 import javax.sip.message.Message;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 
+
 /**
  * Manages {@link ISipSession}'s for a SIP account.
  */
@@ -390,25 +396,26 @@
         }
     }
 
+    private SipSessionImpl createNewSession(RequestEvent event,
+            ISipSessionListener listener, ServerTransaction transaction,
+            int newState) throws SipException {
+        SipSessionImpl newSession = new SipSessionImpl(listener);
+        newSession.mServerTransaction = transaction;
+        newSession.mState = newState;
+        newSession.mDialog = newSession.mServerTransaction.getDialog();
+        newSession.mInviteReceived = event;
+        newSession.mPeerProfile = createPeerProfile((HeaderAddress)
+                event.getRequest().getHeader(FromHeader.NAME));
+        newSession.mPeerSessionDescription =
+                extractContent(event.getRequest());
+        return newSession;
+    }
+
     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();
@@ -452,7 +459,8 @@
                     // got INVITE w/ replaces request.
                     newSession = createNewSession(event,
                             replacedSession.mProxy.getListener(),
-                            mSipHelper.getServerTransaction(event));
+                            mSipHelper.getServerTransaction(event),
+                            SipSession.State.INCOMING_CALL);
                     newSession.mProxy.onCallTransferring(newSession,
                             newSession.mPeerSessionDescription);
                 } else {
@@ -461,7 +469,8 @@
             } else {
                 // New Incoming call.
                 newSession = createNewSession(event, mProxy,
-                        mSipHelper.sendRinging(event, generateTag()));
+                        mSipHelper.sendRinging(event, generateTag()),
+                        SipSession.State.INCOMING_CALL);
                 mProxy.onRinging(newSession, newSession.mPeerProfile,
                         newSession.mPeerSessionDescription);
             }
@@ -507,6 +516,11 @@
 
         private SipSessionImpl mKeepAliveSession;
 
+        // the following three members are used for handling refer request.
+        SipSessionImpl mReferSession;
+        ReferredByHeader mReferredBy;
+        String mReplaces;
+
         // lightweight timer
         class SessionTimer {
             private boolean mRunning = true;
@@ -556,6 +570,9 @@
             mInviteReceived = null;
             mPeerSessionDescription = null;
             mAuthenticationRetryCount = 0;
+            mReferSession = null;
+            mReferredBy = null;
+            mReplaces = null;
 
             if (mDialog != null) mDialog.delete();
             mDialog = null;
@@ -969,15 +986,26 @@
             return (proxyAuth == null) ? null : proxyAuth.getNonce();
         }
 
+        private String getResponseString(int statusCode) {
+            StatusLine statusLine = new StatusLine();
+            statusLine.setStatusCode(statusCode);
+            statusLine.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode));
+            return statusLine.encode();
+        }
+
         private boolean readyForCall(EventObject evt) throws SipException {
             // expect MakeCallCommand, RegisterCommand, DEREGISTER
             if (evt instanceof MakeCallCommand) {
                 mState = SipSession.State.OUTGOING_CALL;
                 MakeCallCommand cmd = (MakeCallCommand) evt;
                 mPeerProfile = cmd.getPeerProfile();
-                mClientTransaction = mSipHelper.sendInvite(mLocalProfile,
-                        mPeerProfile, cmd.getSessionDescription(),
-                        generateTag());
+                if (mReferSession != null) {
+                    mSipHelper.sendReferNotify(mReferSession.mDialog,
+                            getResponseString(Response.TRYING));
+                }
+                mClientTransaction = mSipHelper.sendInvite(
+                        mLocalProfile, mPeerProfile, cmd.getSessionDescription(),
+                        generateTag(), mReferredBy, mReplaces);
                 mDialog = mClientTransaction.getDialog();
                 addSipSession(this);
                 startSessionTimer(cmd.getTimeout());
@@ -1072,6 +1100,12 @@
                     }
                     return true;
                 case Response.OK:
+                    if (mReferSession != null) {
+                        mSipHelper.sendReferNotify(mReferSession.mDialog,
+                                getResponseString(Response.OK));
+                        // since we don't need to remember the session anymore.
+                        mReferSession = null;
+                    }
                     mSipHelper.sendInviteAck(event, mDialog);
                     mPeerSessionDescription = extractContent(response);
                     establishCall(true);
@@ -1087,6 +1121,10 @@
                     // rfc3261#section-14.1; re-schedule invite
                     return true;
                 default:
+                    if (mReferSession != null) {
+                        mSipHelper.sendReferNotify(mReferSession.mDialog,
+                                getResponseString(Response.SERVICE_UNAVAILABLE));
+                    }
                     if (statusCode >= 400) {
                         // error: an ack is sent automatically by the stack
                         onError(response);
@@ -1155,6 +1193,38 @@
             return false;
         }
 
+        private boolean processReferRequest(RequestEvent event)
+                throws SipException {
+            try {
+                ReferToHeader referto = (ReferToHeader) event.getRequest()
+                        .getHeader(ReferTo.NAME);
+                Address address = referto.getAddress();
+                SipURI uri = (SipURI) address.getURI();
+                String replacesHeader = uri.getHeader(ReplacesHeader.NAME);
+                String username = uri.getUser();
+                if (username == null) {
+                    mSipHelper.sendResponse(event, Response.BAD_REQUEST);
+                    return false;
+                }
+                // send notify accepted
+                mSipHelper.sendResponse(event, Response.ACCEPTED);
+                SipSessionImpl newSession = createNewSession(event,
+                        this.mProxy.getListener(),
+                        mSipHelper.getServerTransaction(event),
+                        SipSession.State.READY_TO_CALL);
+                newSession.mReferSession = this;
+                newSession.mReferredBy = (ReferredByHeader) event.getRequest()
+                        .getHeader(ReferredByHeader.NAME);
+                newSession.mReplaces = replacesHeader;
+                newSession.mPeerProfile = createPeerProfile(referto);
+                newSession.mProxy.onCallTransferring(newSession,
+                        null);
+                return true;
+            } catch (IllegalArgumentException e) {
+                throw new SipException("createPeerProfile()", e);
+            }
+        }
+
         private boolean inCall(EventObject evt) throws SipException {
             // expect END_CALL cmd, BYE request, hold call (MakeCallCommand)
             // OK retransmission is handled in SipStack
@@ -1175,6 +1245,8 @@
                 mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
                 endCallNormally();
                 return true;
+            } else if (isRequestEvent(Request.REFER, evt)) {
+                return processReferRequest((RequestEvent) evt);
             } else if (evt instanceof MakeCallCommand) {
                 // to change call
                 mState = SipSession.State.OUTGOING_CALL;
@@ -1182,6 +1254,8 @@
                         ((MakeCallCommand) evt).getSessionDescription());
                 startSessionTimer(((MakeCallCommand) evt).getTimeout());
                 return true;
+            } else if (evt instanceof ResponseEvent) {
+                if (expectResponse(Request.NOTIFY, evt)) return true;
             }
             return false;
         }
@@ -1558,12 +1632,10 @@
         return false;
     }
 
-    private static SipProfile createPeerProfile(Request request)
+    private static SipProfile createPeerProfile(HeaderAddress header)
             throws SipException {
         try {
-            FromHeader fromHeader =
-                    (FromHeader) request.getHeader(FromHeader.NAME);
-            Address address = fromHeader.getAddress();
+            Address address = header.getAddress();
             SipURI uri = (SipURI) address.getURI();
             String username = uri.getUser();
             if (username == null) username = ANONYMOUS;
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index 47ed658..0815294 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -49,7 +49,8 @@
 	frameworks/base/media/libstagefright/codecs/amrnb/enc/include \
 	frameworks/base/media/libstagefright/codecs/amrnb/enc/src \
 	frameworks/base/media/libstagefright/codecs/amrnb/dec/include \
-	frameworks/base/media/libstagefright/codecs/amrnb/dec/src
+	frameworks/base/media/libstagefright/codecs/amrnb/dec/src \
+	system/media/audio_effects/include
 
 LOCAL_CFLAGS += -fvisibility=hidden
 
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 85ed1c8..529b425 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -40,7 +40,8 @@
 #include <media/AudioRecord.h>
 #include <media/AudioTrack.h>
 #include <media/mediarecorder.h>
-
+#include <media/AudioEffect.h>
+#include <audio_effects/effect_aec.h>
 #include <system/audio.h>
 
 #include "jni.h"
@@ -481,6 +482,7 @@
     bool sendDtmf(int event);
     bool add(AudioStream *stream);
     bool remove(int socket);
+    bool platformHasAec() { return mPlatformHasAec; }
 
 private:
     enum {
@@ -491,6 +493,8 @@
         LAST_MODE = 3,
     };
 
+    bool checkPlatformAec();
+
     AudioStream *mChain;
     int mEventQueue;
     volatile int mDtmfEvent;
@@ -499,6 +503,7 @@
     int mSampleRate;
     int mSampleCount;
     int mDeviceSocket;
+    bool mPlatformHasAec;
 
     class NetworkThread : public Thread
     {
@@ -550,6 +555,7 @@
     mDeviceSocket = -1;
     mNetworkThread = new NetworkThread(this);
     mDeviceThread = new DeviceThread(this);
+    mPlatformHasAec = checkPlatformAec();
 }
 
 AudioGroup::~AudioGroup()
@@ -630,10 +636,6 @@
     if (mode == NORMAL && !strcmp(value, "herring")) {
         mode = ECHO_SUPPRESSION;
     }
-    if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters(
-        0, String8("ec_supported")) == "ec_supported=yes") {
-        mode = NORMAL;
-    }
     if (mMode == mode) {
         return true;
     }
@@ -759,6 +761,25 @@
     return true;
 }
 
+bool AudioGroup::checkPlatformAec()
+{
+    effect_descriptor_t fxDesc;
+    uint32_t numFx;
+
+    if (AudioEffect::queryNumberEffects(&numFx) != NO_ERROR) {
+        return false;
+    }
+    for (uint32_t i = 0; i < numFx; i++) {
+        if (AudioEffect::queryEffect(i, &fxDesc) != NO_ERROR) {
+            continue;
+        }
+        if (memcmp(&fxDesc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool AudioGroup::DeviceThread::threadLoop()
 {
     int mode = mGroup->mMode;
@@ -798,10 +819,6 @@
     }
     LOGD("latency: output %d, input %d", track.latency(), record.latency());
 
-    // Initialize echo canceler.
-    EchoSuppressor echo(sampleCount,
-        (track.latency() + record.latency()) * sampleRate / 1000);
-
     // Give device socket a reasonable buffer size.
     setsockopt(deviceSocket, SOL_SOCKET, SO_RCVBUF, &output, sizeof(output));
     setsockopt(deviceSocket, SOL_SOCKET, SO_SNDBUF, &output, sizeof(output));
@@ -810,6 +827,33 @@
     char c;
     while (recv(deviceSocket, &c, 1, MSG_DONTWAIT) == 1);
 
+    // check if platform supports echo cancellation and do not active local echo suppression in
+    // this case
+    EchoSuppressor *echo = NULL;
+    AudioEffect *aec = NULL;
+    if (mode == ECHO_SUPPRESSION) {
+        if (mGroup->platformHasAec()) {
+            aec = new AudioEffect(FX_IID_AEC,
+                                    NULL,
+                                    0,
+                                    0,
+                                    0,
+                                    record.getSessionId(),
+                                    record.getInput());
+            status_t status = aec->initCheck();
+            if (status == NO_ERROR || status == ALREADY_EXISTS) {
+                aec->setEnabled(true);
+            } else {
+                delete aec;
+                aec = NULL;
+            }
+        }
+        // Create local echo suppressor if platform AEC cannot be used.
+        if (aec == NULL) {
+             echo = new EchoSuppressor(sampleCount,
+                                       (track.latency() + record.latency()) * sampleRate / 1000);
+        }
+    }
     // Start AudioRecord before AudioTrack. This prevents AudioTrack from being
     // disabled due to buffer underrun while waiting for AudioRecord.
     if (mode != MUTED) {
@@ -843,7 +887,7 @@
                     track.releaseBuffer(&buffer);
                 } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
                     LOGE("cannot write to AudioTrack");
-                    return true;
+                    goto exit;
                 }
             }
 
@@ -859,7 +903,7 @@
                     record.releaseBuffer(&buffer);
                 } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
                     LOGE("cannot read from AudioRecord");
-                    return true;
+                    goto exit;
                 }
             }
         }
@@ -870,15 +914,18 @@
         }
 
         if (mode != MUTED) {
-            if (mode == NORMAL) {
-                send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
-            } else {
-                echo.run(output, input);
-                send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
+            if (echo != NULL) {
+                LOGV("echo->run()");
+                echo->run(output, input);
             }
+            send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
         }
     }
-    return false;
+
+exit:
+    delete echo;
+    delete aec;
+    return true;
 }
 
 //------------------------------------------------------------------------------
diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java
new file mode 100644
index 0000000..8ab5982
--- /dev/null
+++ b/wifi/java/android/net/wifi/StateChangeResult.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ package android.net.wifi;
+
+/**
+ * Stores supplicant state change information passed from WifiMonitor to
+ * a state machine. WifiStateMachine, SupplicantStateTracker and WpsStateMachine
+ * are example state machines that handle it.
+ * @hide
+ */
+public class StateChangeResult {
+    StateChangeResult(int networkId, String BSSID, SupplicantState state) {
+        this.state = state;
+        this.BSSID = BSSID;
+        this.networkId = networkId;
+    }
+    int networkId;
+    String BSSID;
+    SupplicantState state;
+}
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 0c4f9f6..9168e62 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -19,7 +19,7 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
-import android.net.wifi.WifiStateMachine.StateChangeResult;
+import android.net.wifi.StateChangeResult;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
@@ -159,11 +159,11 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-                case WifiStateMachine.AUTHENTICATION_FAILURE_EVENT:
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
                     mAuthenticationFailuresCount++;
                     mAuthFailureInSupplicantBroadcast = true;
                     break;
-                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
                     sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
@@ -251,7 +251,7 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
                     if (SupplicantState.isHandshakeState(state)) {
@@ -293,7 +293,7 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
                     sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e3661bf..7bb927b 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -81,6 +81,24 @@
         mHiddenSSID = false;
     }
 
+    /**
+     * Copy constructor
+     * @hide
+     */
+    public WifiInfo(WifiInfo source) {
+        if (source != null) {
+            mSupplicantState = source.mSupplicantState;
+            mBSSID = source.mBSSID;
+            mSSID = source.mSSID;
+            mNetworkId = source.mNetworkId;
+            mHiddenSSID = source.mHiddenSSID;
+            mRssi = source.mRssi;
+            mLinkSpeed = source.mLinkSpeed;
+            mIpAddress = source.mIpAddress;
+            mMacAddress = source.mMacAddress;
+        }
+    }
+
     void setSSID(String SSID) {
         mSSID = SSID;
         // network is considered not hidden by default
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9d1bdd4..cd6621f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -230,11 +230,13 @@
     /**
      * Broadcast intent action indicating that the state of Wi-Fi connectivity
      * has changed. One extra provides the new state
-     * in the form of a {@link android.net.NetworkInfo} object. If the new state is
-     * CONNECTED, a second extra may provide the BSSID of the access point,
+     * in the form of a {@link android.net.NetworkInfo} object. If the new
+     * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
+     * the access point.
      * as a {@code String}.
      * @see #EXTRA_NETWORK_INFO
      * @see #EXTRA_BSSID
+     * @see #EXTRA_WIFI_INFO
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -252,6 +254,13 @@
      */
     public static final String EXTRA_BSSID = "bssid";
     /**
+     * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
+     * information about the access point to which we are connected. Only present
+     * when the new state is CONNECTED.  Retrieve with
+     * {@link android.content.Intent#getParcelableExtra(String)}.
+     */
+    public static final String EXTRA_WIFI_INFO = "wifiInfo";
+    /**
      * Broadcast intent action indicating that the state of establishing a connection to
      * an access point has changed.One extra provides the new
      * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 4ec4cfc..2ccc8a2 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -16,15 +16,24 @@
 
 package android.net.wifi;
 
-import android.util.Log;
 import android.net.NetworkInfo;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.StateChangeResult;
+import android.os.Message;
+import android.util.Log;
+
+
+import com.android.internal.util.Protocol;
+import com.android.internal.util.StateMachine;
 
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 
 /**
  * Listens for events from the wpa_supplicant server, and passes them on
- * to the {@link WifiStateMachine} for handling. Runs in its own thread.
+ * to the {@link StateMachine} for handling. Runs in its own thread.
  *
  * @hide
  */
@@ -45,16 +54,16 @@
     private static final int UNKNOWN      = 9;
 
     /** All events coming from the supplicant start with this prefix */
-    private static final String eventPrefix = "CTRL-EVENT-";
-    private static final int eventPrefixLen = eventPrefix.length();
+    private static final String EVENT_PREFIX_STR = "CTRL-EVENT-";
+    private static final int EVENT_PREFIX_LEN_STR = EVENT_PREFIX_STR.length();
 
     /** All WPA events coming from the supplicant start with this prefix */
-    private static final String wpaEventPrefix = "WPA:";
-    private static final String passwordKeyMayBeIncorrectEvent =
+    private static final String WPA_EVENT_PREFIX_STR = "WPA:";
+    private static final String PASSWORD_MAY_BE_INCORRECT_STR =
        "pre-shared key may be incorrect";
 
     /* WPS events */
-    private static final String wpsOverlapEvent = "WPS-OVERLAP-DETECTED";
+    private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED";
 
     /**
      * Names of events from wpa_supplicant (minus the prefix). In the
@@ -68,26 +77,26 @@
      * </pre>
      * <code>xx:xx:xx:xx:xx:xx</code> is the BSSID of the associated access point
      */
-    private static final String connectedEvent =    "CONNECTED";
+    private static final String CONNECTED_STR =    "CONNECTED";
     /**
      * <pre>
      * CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys
      * </pre>
      */
-    private static final String disconnectedEvent = "DISCONNECTED";
+    private static final String DISCONNECTED_STR = "DISCONNECTED";
     /**
      * <pre>
      * CTRL-EVENT-STATE-CHANGE x
      * </pre>
      * <code>x</code> is the numerical value of the new state.
      */
-    private static final String stateChangeEvent =  "STATE-CHANGE";
+    private static final String STATE_CHANGE_STR =  "STATE-CHANGE";
     /**
      * <pre>
      * CTRL-EVENT-SCAN-RESULTS ready
      * </pre>
      */
-    private static final String scanResultsEvent =  "SCAN-RESULTS";
+    private static final String SCAN_RESULTS_STR =  "SCAN-RESULTS";
 
     /**
      * <pre>
@@ -95,32 +104,32 @@
      * </pre>
      * {@code x} is the link speed in Mb/sec.
      */
-    private static final String linkSpeedEvent = "LINK-SPEED";
+    private static final String LINK_SPEED_STR = "LINK-SPEED";
     /**
      * <pre>
      * CTRL-EVENT-TERMINATING - signal x
      * </pre>
      * <code>x</code> is the signal that caused termination.
      */
-    private static final String terminatingEvent =  "TERMINATING";
+    private static final String TERMINATING_STR =  "TERMINATING";
     /**
      * <pre>
      * CTRL-EVENT-DRIVER-STATE state
      * </pre>
      * <code>state</code> can be HANGED
      */
-    private static final String driverStateEvent = "DRIVER-STATE";
+    private static final String DRIVER_STATE_STR = "DRIVER-STATE";
     /**
      * <pre>
      * CTRL-EVENT-EAP-FAILURE EAP authentication failed
      * </pre>
      */
-    private static final String eapFailureEvent = "EAP-FAILURE";
+    private static final String EAP_FAILURE_STR = "EAP-FAILURE";
 
     /**
      * This indicates an authentication failure on EAP FAILURE event
      */
-    private static final String eapAuthFailure = "EAP authentication failed";
+    private static final String EAP_AUTH_FAILURE_STR = "EAP authentication failed";
 
     /**
      * Regex pattern for extracting an Ethernet-style MAC address from a string.
@@ -130,17 +139,116 @@
     private static Pattern mConnectedEventPattern =
         Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) ");
 
-    private final WifiStateMachine mWifiStateMachine;
+    /** P2P events */
+    private static final String P2P_EVENT_PREFIX_STR = "P2P";
+
+    /* P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13 pri_dev_type=1-0050F204-1
+       name='p2p-TEST1' config_methods=0x188 dev_capab=0x27 group_capab=0x0 */
+    private static final String P2P_DEVICE_FOUND_STR = "P2P-DEVICE-FOUND";
+
+    /* P2P-DEVICE-LOST p2p_dev_addr=42:fc:89:e1:e2:27 */
+    private static final String P2P_DEVICE_LOST_STR = "P2P-DEVICE-LOST";
+
+    /* P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 */
+    private static final String P2P_GO_NEG_REQUEST_STR = "P2P-GO-NEG-REQUEST";
+
+    private static final String P2P_GO_NEG_SUCCESS_STR = "P2P-GO-NEG-SUCCESS";
+
+    private static final String P2P_GO_NEG_FAILURE_STR = "P2P-GO-NEG-FAILURE";
+
+    private static final String P2P_GROUP_FORMATION_SUCCESS_STR =
+            "P2P-GROUP-FORMATION-SUCCESS";
+
+    private static final String P2P_GROUP_FORMATION_FAILURE_STR =
+            "P2P-GROUP-FORMATION-FAILURE";
+
+    /* P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437
+       [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|passphrase="fKG4jMe3"]
+       go_dev_addr=fa:7b:7a:42:02:13 */
+    private static final String P2P_GROUP_STARTED_STR = "P2P-GROUP-STARTED";
+
+    /* P2P-GROUP-REMOVED p2p-wlan0-0 [client|GO] reason=REQUESTED */
+    private static final String P2P_GROUP_REMOVED_STR = "P2P-GROUP-REMOVED";
+
+    /* P2P-INVITATION-RECEIVED sa=fa:7b:7a:42:02:13 go_dev_addr=f8:7b:7a:42:02:13
+        bssid=fa:7b:7a:42:82:13 unknown-network */
+    private static final String P2P_INVITATION_RECEIVED_STR = "P2P-INVITATION-RECEIVED";
+
+    /* P2P-INVITATION-RESULT status=1 */
+    private static final String P2P_INVITATION_RESULT_STR = "P2P-INVITATION-RESULT";
+
+    /* P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
+       pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+       group_capab=0x0 */
+    private static final String P2P_PROV_DISC_PBC_REQ_STR = "P2P-PROV-DISC-PBC-REQ";
+    /* P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
+       pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+       group_capab=0x0 */
+    private static final String P2P_PROV_DISC_ENTER_PIN_STR = "P2P-PROV-DISC-ENTER-PIN";
+    /* P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27
+       pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+       group_capab=0x0 */
+    private static final String P2P_PROV_DISC_SHOW_PIN_STR = "P2P-PROV-DISC-SHOW-PIN";
+
+    private static final String HOST_AP_EVENT_PREFIX_STR = "AP";
+    /* AP-STA-CONNECTED 42:fc:89:a8:96:09 */
+    private static final String AP_STA_CONNECTED_STR = "AP-STA-CONNECTED";
+    /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */
+    private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED";
+
+    private final StateMachine mStateMachine;
+
+    /* Supplicant events reported to a state machine */
+    private static final int BASE = Protocol.BASE_WIFI_MONITOR;
+
+    /* Connection to supplicant established */
+    public static final int SUP_CONNECTION_EVENT                 = BASE + 1;
+    /* Connection to supplicant lost */
+    public static final int SUP_DISCONNECTION_EVENT              = BASE + 2;
+   /* Network connection completed */
+    public static final int NETWORK_CONNECTION_EVENT             = BASE + 3;
+    /* Network disconnection completed */
+    public static final int NETWORK_DISCONNECTION_EVENT          = BASE + 4;
+    /* Scan results are available */
+    public static final int SCAN_RESULTS_EVENT                   = BASE + 5;
+    /* Supplicate state changed */
+    public static final int SUPPLICANT_STATE_CHANGE_EVENT        = BASE + 6;
+    /* Password failure and EAP authentication failure */
+    public static final int AUTHENTICATION_FAILURE_EVENT         = BASE + 7;
+    /* WPS overlap detected */
+    public static final int WPS_OVERLAP_EVENT                    = BASE + 8;
+    /* Driver was hung */
+    public static final int DRIVER_HUNG_EVENT                    = BASE + 9;
+
+    /* P2P events */
+    public static final int P2P_DEVICE_FOUND_EVENT               = BASE + 21;
+    public static final int P2P_DEVICE_LOST_EVENT                = BASE + 22;
+    public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT     = BASE + 23;
+    public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT     = BASE + 25;
+    public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT     = BASE + 26;
+    public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT    = BASE + 27;
+    public static final int P2P_GROUP_FORMATION_FAILURE_EVENT    = BASE + 28;
+    public static final int P2P_GROUP_STARTED_EVENT              = BASE + 29;
+    public static final int P2P_GROUP_REMOVED_EVENT              = BASE + 30;
+    public static final int P2P_INVITATION_RECEIVED_EVENT        = BASE + 31;
+    public static final int P2P_INVITATION_RESULT_EVENT          = BASE + 32;
+    public static final int P2P_PROV_DISC_PBC_REQ_EVENT          = BASE + 33;
+    public static final int P2P_PROV_DISC_ENTER_PIN_EVENT        = BASE + 34;
+    public static final int P2P_PROV_DISC_SHOW_PIN_EVENT         = BASE + 35;
+
+    /* hostap events */
+    public static final int AP_STA_DISCONNECTED_EVENT            = BASE + 41;
+    public static final int AP_STA_CONNECTED_EVENT               = BASE + 42;
 
     /**
      * This indicates the supplicant connection for the monitor is closed
      */
-    private static final String monitorSocketClosed = "connection closed";
+    private static final String MONITOR_SOCKET_CLOSED_STR = "connection closed";
 
     /**
      * This indicates a read error on the monitor socket conenction
      */
-    private static final String wpaRecvError = "recv error";
+    private static final String WPA_RECV_ERROR_STR = "recv error";
 
     /**
      * Tracks consecutive receive errors
@@ -152,8 +260,8 @@
      */
     private static final int MAX_RECV_ERRORS    = 10;
 
-    public WifiMonitor(WifiStateMachine wifiStateMachine) {
-        mWifiStateMachine = wifiStateMachine;
+    public WifiMonitor(StateMachine wifiStateMachine) {
+        mStateMachine = wifiStateMachine;
     }
 
     public void startMonitoring() {
@@ -170,9 +278,9 @@
             if (connectToSupplicant()) {
                 // Send a message indicating that it is now possible to send commands
                 // to the supplicant
-                mWifiStateMachine.notifySupplicantConnection();
+                mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
             } else {
-                mWifiStateMachine.notifySupplicantLost();
+                mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                 return;
             }
 
@@ -181,20 +289,24 @@
                 String eventStr = WifiNative.waitForEvent();
 
                 // Skip logging the common but mostly uninteresting scan-results event
-                if (false && eventStr.indexOf(scanResultsEvent) == -1) {
-                    Log.v(TAG, "Event [" + eventStr + "]");
+                if (false && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
+                    Log.d(TAG, "Event [" + eventStr + "]");
                 }
-                if (!eventStr.startsWith(eventPrefix)) {
-                    if (eventStr.startsWith(wpaEventPrefix) &&
-                            0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
-                        mWifiStateMachine.notifyAuthenticationFailure();
-                    } else if (eventStr.startsWith(wpsOverlapEvent)) {
-                        mWifiStateMachine.notifyWpsOverlap();
+                if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
+                    if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
+                            0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
+                        mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
+                    } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
+                        mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
+                    } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
+                        handleP2pEvents(eventStr);
+                    } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
+                        handleHostApEvents(eventStr);
                     }
                     continue;
                 }
 
-                String eventName = eventStr.substring(eventPrefixLen);
+                String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
                 int nameEnd = eventName.indexOf(' ');
                 if (nameEnd != -1)
                     eventName = eventName.substring(0, nameEnd);
@@ -206,21 +318,21 @@
                  * Map event name into event enum
                  */
                 int event;
-                if (eventName.equals(connectedEvent))
+                if (eventName.equals(CONNECTED_STR))
                     event = CONNECTED;
-                else if (eventName.equals(disconnectedEvent))
+                else if (eventName.equals(DISCONNECTED_STR))
                     event = DISCONNECTED;
-                else if (eventName.equals(stateChangeEvent))
+                else if (eventName.equals(STATE_CHANGE_STR))
                     event = STATE_CHANGE;
-                else if (eventName.equals(scanResultsEvent))
+                else if (eventName.equals(SCAN_RESULTS_STR))
                     event = SCAN_RESULTS;
-                else if (eventName.equals(linkSpeedEvent))
+                else if (eventName.equals(LINK_SPEED_STR))
                     event = LINK_SPEED;
-                else if (eventName.equals(terminatingEvent))
+                else if (eventName.equals(TERMINATING_STR))
                     event = TERMINATING;
-                else if (eventName.equals(driverStateEvent))
+                else if (eventName.equals(DRIVER_STATE_STR))
                     event = DRIVER_STATE;
-                else if (eventName.equals(eapFailureEvent))
+                else if (eventName.equals(EAP_FAILURE_STR))
                     event = EAP_FAILURE;
                 else
                     event = UNKNOWN;
@@ -249,7 +361,7 @@
                      * If monitor socket is closed, we have already
                      * stopped the supplicant, simply exit the monitor thread
                      */
-                    if (eventData.startsWith(monitorSocketClosed)) {
+                    if (eventData.startsWith(MONITOR_SOCKET_CLOSED_STR)) {
                         if (false) {
                             Log.d(TAG, "Monitor socket is closed, exiting thread");
                         }
@@ -260,7 +372,7 @@
                      * Close the supplicant connection if we see
                      * too many recv errors
                      */
-                    if (eventData.startsWith(wpaRecvError)) {
+                    if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
                         if (++mRecvErrors > MAX_RECV_ERRORS) {
                             if (false) {
                                 Log.d(TAG, "too many recv errors, closing connection");
@@ -271,11 +383,11 @@
                     }
 
                     // notify and exit
-                    mWifiStateMachine.notifySupplicantLost();
+                    mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                     break;
                 } else if (event == EAP_FAILURE) {
-                    if (eventData.startsWith(eapAuthFailure)) {
-                        mWifiStateMachine.notifyAuthenticationFailure();
+                    if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
+                        mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
                     }
                 } else {
                     handleEvent(event, eventData);
@@ -305,7 +417,7 @@
                 return;
             }
             if (state.equals("HANGED")) {
-                mWifiStateMachine.notifyDriverHung();
+                mStateMachine.sendMessage(DRIVER_HUNG_EVENT);
             }
         }
 
@@ -326,7 +438,7 @@
                     break;
 
                 case SCAN_RESULTS:
-                    mWifiStateMachine.notifyScanResultsAvailable();
+                    mStateMachine.sendMessage(SCAN_RESULTS_EVENT);
                     break;
 
                 case UNKNOWN:
@@ -335,6 +447,59 @@
         }
 
         /**
+         * Handle p2p events
+         */
+        private void handleP2pEvents(String dataString) {
+            if (dataString.startsWith(P2P_DEVICE_FOUND_STR)) {
+                mStateMachine.sendMessage(P2P_DEVICE_FOUND_EVENT, new WifiP2pDevice(dataString));
+            } else if (dataString.startsWith(P2P_DEVICE_LOST_STR)) {
+                mStateMachine.sendMessage(P2P_DEVICE_LOST_EVENT, new WifiP2pDevice(dataString));
+            } else if (dataString.startsWith(P2P_GO_NEG_REQUEST_STR)) {
+                mStateMachine.sendMessage(P2P_GO_NEGOTIATION_REQUEST_EVENT,
+                        new WifiP2pConfig(dataString));
+            } else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
+                mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT);
+            } else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
+                mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT);
+            } else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
+                mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT);
+            } else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
+                mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT);
+            } else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
+                mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString));
+            } else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
+                mStateMachine.sendMessage(P2P_GROUP_REMOVED_EVENT, new WifiP2pGroup(dataString));
+            } else if (dataString.startsWith(P2P_INVITATION_RECEIVED_STR)) {
+                mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT,
+                        new WifiP2pGroup(dataString));
+            } else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
+                String[] tokens = dataString.split(" ");
+                if (tokens.length != 2) return;
+                String[] nameValue = tokens[1].split("=");
+                if (nameValue.length != 2) return;
+                mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, nameValue[1]);
+            } else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
+                mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT,
+                        new WifiP2pDevice(dataString));
+            } else if (dataString.startsWith(P2P_PROV_DISC_ENTER_PIN_STR)) {
+                mStateMachine.sendMessage(P2P_PROV_DISC_ENTER_PIN_EVENT,
+                        new WifiP2pDevice(dataString));
+            }
+        }
+
+        /**
+         * Handle hostap events
+         */
+        private void handleHostApEvents(String dataString) {
+            String[] tokens = dataString.split(" ");
+            if (tokens[0].equals(AP_STA_CONNECTED_STR)) {
+                mStateMachine.sendMessage(AP_STA_CONNECTED_EVENT, tokens[1]);
+            } else if (tokens[0].equals(AP_STA_DISCONNECTED_STR)) {
+                mStateMachine.sendMessage(AP_STA_DISCONNECTED_EVENT, tokens[1]);
+            }
+        }
+
+        /**
          * Handle the supplicant STATE-CHANGE event
          * @param dataString New supplicant state string in the format:
          * id=network-id state=new-state
@@ -383,7 +548,7 @@
             if (newSupplicantState == SupplicantState.INVALID) {
                 Log.w(TAG, "Invalid supplicant state: " + newState);
             }
-            mWifiStateMachine.notifySupplicantStateChange(networkId, BSSID, newSupplicantState);
+            notifySupplicantStateChange(networkId, BSSID, newSupplicantState);
         }
     }
 
@@ -403,7 +568,40 @@
                 }
             }
         }
-        mWifiStateMachine.notifyNetworkStateChange(newState, BSSID, networkId);
+        notifyNetworkStateChange(newState, BSSID, networkId);
+    }
+
+    /**
+     * Send the state machine a notification that the state of Wifi connectivity
+     * has changed.
+     * @param networkId the configured network on which the state change occurred
+     * @param newState the new network state
+     * @param BSSID when the new state is {@link DetailedState#CONNECTED
+     * NetworkInfo.DetailedState.CONNECTED},
+     * this is the MAC address of the access point. Otherwise, it
+     * is {@code null}.
+     */
+    void notifyNetworkStateChange(NetworkInfo.DetailedState newState, String BSSID, int netId) {
+        if (newState == NetworkInfo.DetailedState.CONNECTED) {
+            Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT,
+                    netId, 0, BSSID);
+            mStateMachine.sendMessage(m);
+        } else {
+            Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT,
+                    netId, 0, BSSID);
+            mStateMachine.sendMessage(m);
+        }
+    }
+
+    /**
+     * Send the state machine a notification that the state of the supplicant
+     * has changed.
+     * @param networkId the configured network on which the state change occurred
+     * @param newState the new {@code SupplicantState}
+     */
+    void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) {
+        mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
+                new StateChangeResult(networkId, BSSID, newState)));
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 6e13d0f..3b043b3 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -16,6 +16,16 @@
 
 package android.net.wifi;
 
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.lang.Process;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Native calls for sending requests to the supplicant daemon, and for
  * receiving asynchronous events. All methods of the form "xxxxCommand()"
@@ -28,6 +38,10 @@
  * WifiStateTracker class except for waitForEvent() call which is
  * on a separate monitor channel for WifiMonitor
  *
+ * TODO: clean up the API and move the functionality from JNI to here. We should
+ * be able to get everything done with doBooleanCommand, doIntCommand and
+ * doStringCommand native commands
+ *
  * {@hide}
  */
 public class WifiNative {
@@ -104,18 +118,30 @@
 
     public native static boolean stopDriverCommand();
 
-    /**
-     * Start filtering out multicast packets, to reduce battery consumption
-     * that would result from processing them, only to discard them.
-     * @return {@code true} if the operation succeeded, {@code false} otherwise
-     */
-    public native static boolean startPacketFiltering();
 
     /**
-     * Stop filtering out multicast packets.
+     * Start filtering out Multicast V4 packets
      * @return {@code true} if the operation succeeded, {@code false} otherwise
      */
-    public native static boolean stopPacketFiltering();
+    public native static boolean startFilteringMulticastV4Packets();
+
+    /**
+     * Stop filtering out Multicast V4 packets.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean stopFilteringMulticastV4Packets();
+
+    /**
+     * Start filtering out Multicast V6 packets
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean startFilteringMulticastV6Packets();
+
+    /**
+     * Stop filtering out Multicast V6 packets.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean stopFilteringMulticastV6Packets();
 
     public native static boolean setPowerModeCommand(int mode);
 
@@ -174,4 +200,141 @@
     public native static void enableBackgroundScanCommand(boolean enable);
 
     public native static void setScanIntervalCommand(int scanInterval);
+
+    private native static boolean doBooleanCommand(String command);
+
+    //STOPSHIP: remove this after native interface works and replace all
+    //calls to doBooleanTempCommand() with doBooleanCommand()
+    private static boolean doBooleanTempCommand(String command) {
+        try {
+            String str = "/system/bin/wpa_cli " + command;
+            Log.e("WifiNative", "===> " + str);
+            Runtime.getRuntime()
+                .exec(str).waitFor();
+        } catch (Exception e) {
+            Log.e("WifiNative", "exception with doBooleanTempCommand");
+            return false;
+        }
+        return true;
+    }
+
+    private static String doStringTempCommand(String command) {
+        String lines[] = null;
+        try {
+            String str = "/system/bin/wpa_cli " + command;
+            Log.e("WifiNative", "===> " + str);
+            Process p = Runtime.getRuntime()
+                .exec(str);
+            InputStream in = p.getInputStream();
+            p.waitFor();
+            byte[] bytes=new byte[in.available()];
+            in.read(bytes);
+            String s = new String(bytes);
+            Log.e("WifiNative", "====> doString: " + s);
+            lines = s.split("\\r?\\n");
+        } catch (Exception e) {
+            Log.e("WifiNative", "exception with doBooleanTempCommand");
+            return null;
+        }
+        return lines[1];
+    }
+
+    private native static int doIntCommand(String command);
+
+    private native static String doStringCommand(String command);
+
+    public static boolean p2pFind() {
+        return doBooleanTempCommand("p2p_find");
+    }
+
+    public static boolean p2pFind(int timeout) {
+        if (timeout <= 0) {
+            return p2pFind();
+        }
+        return doBooleanTempCommand("p2p_find " + timeout);
+    }
+
+    public static boolean p2pListen() {
+        return doBooleanTempCommand("p2p_listen");
+    }
+
+    public static boolean p2pListen(int timeout) {
+        if (timeout <= 0) {
+            return p2pListen();
+        }
+        return doBooleanTempCommand("p2p_listen " + timeout);
+    }
+
+    public static boolean p2pFlush() {
+        return doBooleanTempCommand("p2p_flush");
+    }
+
+    /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
+        [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
+    public static String p2pConnect(WifiP2pConfig config) {
+        if (config == null) return null;
+        List<String> args = new ArrayList<String>();
+        WpsConfiguration wpsConfig = config.wpsConfig;
+        args.add(config.deviceAddress);
+
+        switch (wpsConfig.setup) {
+            case PBC:
+                args.add("pbc");
+                break;
+            case DISPLAY:
+                //TODO: pass the pin back for display
+                args.add("pin");
+                args.add("display");
+                break;
+            case KEYPAD:
+                args.add(wpsConfig.pin);
+                args.add("keypad");
+                break;
+            case LABEL:
+                args.add(wpsConfig.pin);
+                args.add("label");
+            default:
+                break;
+        }
+
+        if (config.isPersistent) args.add("persistent");
+        if (config.joinExistingGroup) args.add("join");
+
+        args.add("go_intent=" + config.groupOwnerIntent);
+        if (config.channel > 0) args.add("freq=" + config.channel);
+
+        String command = "p2p_connect ";
+        for (String s : args) command += s + " ";
+
+        return doStringTempCommand(command);
+    }
+
+    public static boolean p2pGroupAdd() {
+        return doBooleanTempCommand("p2p_group_add");
+    }
+
+    public static boolean p2pGroupRemove(String iface) {
+        if (iface == null) return false;
+        return doBooleanTempCommand("p2p_group_remove " + iface);
+    }
+
+    public static boolean p2pReject(String deviceAddress) {
+        return doBooleanTempCommand("p2p_reject " + deviceAddress);
+    }
+
+    /* Invite a peer to a group */
+    public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
+        if (group == null || deviceAddress == null) return false;
+        return doBooleanTempCommand("p2p_invite group=" + group.getInterface()
+                + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
+    }
+
+    public static boolean p2pWpsPbc() {
+        return doBooleanTempCommand("wps_pbc");
+    }
+
+    public static boolean p2pWpsPin(String pin) {
+        return doBooleanTempCommand("wps_pin any " + pin);
+    }
+
 }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 8c28319..de49eb4 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -56,6 +56,8 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkUtils;
 import android.net.wifi.WpsResult.Status;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.StateChangeResult;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
@@ -67,6 +69,7 @@
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.WorkSource;
+import android.server.WifiP2pService;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
@@ -82,12 +85,21 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Pattern;
 
 /**
  * Track the state of Wifi connectivity. All event handling is done here,
  * and all changes in connectivity state are initiated here.
  *
+ * Wi-Fi now supports three modes of operation: Client, Soft Ap and Direct
+ * In the current implementation, we do not support any concurrency and thus only
+ * one of Client, Soft Ap or Direct operation is supported at any time.
+ *
+ * The WifiStateMachine supports Soft Ap and Client operations while WifiP2pService
+ * handles Direct. WifiP2pService and WifiStateMachine co-ordinate to ensure only
+ * one exists at a certain time.
+ *
  * @hide
  */
 public class WifiStateMachine extends StateMachine {
@@ -96,7 +108,7 @@
     private static final String NETWORKTYPE = "WIFI";
     private static final boolean DBG = false;
 
-    /* TODO: fetch a configurable interface */
+    /* TODO: This is no more used with the hostapd code. Clean up */
     private static final String SOFTAP_IFACE = "wl0.1";
 
     private WifiMonitor mWifiMonitor;
@@ -160,9 +172,16 @@
     /* Tracks current frequency mode */
     private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO);
 
+    /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */
+    private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true);
+
     // Channel for sending replies.
     private AsyncChannel mReplyChannel = new AsyncChannel();
 
+    private WifiP2pManager mWifiP2pManager;
+    //Used to initiate a connection with WifiP2pService
+    private AsyncChannel mWifiP2pChannel = new AsyncChannel();
+
     // Event log tags (must be in sync with event-log-tags)
     private static final int EVENTLOG_WIFI_STATE_CHANGED        = 50021;
     private static final int EVENTLOG_WIFI_EVENT_HANDLED        = 50022;
@@ -198,33 +217,20 @@
 
     /* Start the soft access point */
     static final int CMD_START_AP                         = BASE + 21;
+    /* Indicates soft ap start succeded */
+    static final int CMD_START_AP_SUCCESS                 = BASE + 22;
+    /* Indicates soft ap start failed */
+    static final int CMD_START_AP_FAILURE                 = BASE + 23;
     /* Stop the soft access point */
-    static final int CMD_STOP_AP                          = BASE + 22;
+    static final int CMD_STOP_AP                          = BASE + 24;
     /* Set the soft access point configuration */
-    static final int CMD_SET_AP_CONFIG                    = BASE + 23;
+    static final int CMD_SET_AP_CONFIG                    = BASE + 25;
     /* Get the soft access point configuration */
-    static final int CMD_GET_AP_CONFIG                    = BASE + 24;
+    static final int CMD_GET_AP_CONFIG                    = BASE + 26;
+    /* Set configuration on tether interface */
+    static final int CMD_TETHER_INTERFACE                 = BASE + 27;
 
-    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 25;
-
-    /* Supplicant events */
-    /* Connection to supplicant established */
-    static final int SUP_CONNECTION_EVENT                 = BASE + 31;
-    /* Connection to supplicant lost */
-    static final int SUP_DISCONNECTION_EVENT              = BASE + 32;
-   /* Network connection completed */
-    static final int NETWORK_CONNECTION_EVENT             = BASE + 33;
-    /* Network disconnection completed */
-    static final int NETWORK_DISCONNECTION_EVENT          = BASE + 34;
-    /* Scan results are available */
-    static final int SCAN_RESULTS_EVENT                   = BASE + 35;
-    /* Supplicate state changed */
-    static final int SUPPLICANT_STATE_CHANGE_EVENT        = BASE + 36;
-    /* Password failure and EAP authentication failure */
-    static final int AUTHENTICATION_FAILURE_EVENT         = BASE + 37;
-    /* WPS overlap detected */
-    static final int WPS_OVERLAP_EVENT                    = BASE + 38;
-
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 28;
 
     /* Supplicant commands */
     /* Is supplicant alive ? */
@@ -285,6 +291,11 @@
     static final int CMD_START_PACKET_FILTERING           = BASE + 84;
     /* Clear packet filter */
     static final int CMD_STOP_PACKET_FILTERING            = BASE + 85;
+
+    /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */
+    static final int MULTICAST_V6  = 1;
+    static final int MULTICAST_V4  = 0;
+
     /* Connect to a specified network (network id
      * or WifiConfiguration) This involves increasing
      * the priority of the network, enabling the network
@@ -321,6 +332,10 @@
     /* Reset the WPS state machine */
     static final int CMD_RESET_WPS_STATE                  = BASE + 122;
 
+    /* Interaction with WifiP2pService */
+    public static final int WIFI_ENABLE_PENDING           = BASE + 131;
+    public static final int P2P_ENABLE_PROCEED            = BASE + 132;
+
     private static final int CONNECT_MODE   = 1;
     private static final int SCAN_ONLY_MODE = 2;
 
@@ -365,10 +380,6 @@
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
 
-    /* Constants to indicate if soft ap is running or stopped */
-    private static final int SOFT_AP_STOPPED = 0;
-    private static final int SOFT_AP_RUNNING = 1;
-
     /* Default parent state */
     private State mDefaultState = new DefaultState();
     /* Temporary initial state */
@@ -412,8 +423,15 @@
     /* Waiting for WPS to be completed*/
     private State mWaitForWpsCompletionState = new WaitForWpsCompletionState();
 
-    /* Soft Ap is running */
+    /* Soft ap is starting up */
+    private State mSoftApStartingState = new SoftApStartingState();
+    /* Soft ap is running */
     private State mSoftApStartedState = new SoftApStartedState();
+    /* Soft ap is running and we are tethered through connectivity service */
+    private State mTetheredState = new TetheredState();
+
+    /* Wait till p2p is disabled */
+    private State mWaitForP2pDisableState = new WaitForP2pDisableState();
 
 
     /**
@@ -504,13 +522,9 @@
             new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-
                     ArrayList<String> available = intent.getStringArrayListExtra(
                             ConnectivityManager.EXTRA_AVAILABLE_TETHER);
-                    ArrayList<String> active = intent.getStringArrayListExtra(
-                            ConnectivityManager.EXTRA_ACTIVE_TETHER);
-                    updateTetherState(available, active);
-
+                    sendMessage(CMD_TETHER_INTERFACE, available);
                 }
             },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
 
@@ -549,7 +563,10 @@
                 addState(mDriverStoppingState, mSupplicantStartedState);
                 addState(mDriverStoppedState, mSupplicantStartedState);
             addState(mSupplicantStoppingState, mDefaultState);
+            addState(mSoftApStartingState, mDefaultState);
             addState(mSoftApStartedState, mDefaultState);
+                addState(mTetheredState, mSoftApStartedState);
+            addState(mWaitForP2pDisableState, mDefaultState);
 
         setInitialState(mInitialState);
 
@@ -868,17 +885,33 @@
     }
 
     /**
-     * Start packet filtering
+     * Start filtering Multicast v4 packets
      */
-    public void startPacketFiltering() {
-        sendMessage(CMD_START_PACKET_FILTERING);
+    public void startFilteringMulticastV4Packets() {
+        mFilteringMulticastV4Packets.set(true);
+        sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0));
     }
 
     /**
-     * Stop packet filtering
+     * Stop filtering Multicast v4 packets
      */
-    public void stopPacketFiltering() {
-        sendMessage(CMD_STOP_PACKET_FILTERING);
+    public void stopFilteringMulticastV4Packets() {
+        mFilteringMulticastV4Packets.set(false);
+        sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0));
+    }
+
+    /**
+     * Start filtering Multicast v4 packets
+     */
+    public void startFilteringMulticastV6Packets() {
+        sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0));
+    }
+
+    /**
+     * Stop filtering Multicast v4 packets
+     */
+    public void stopFilteringMulticastV6Packets() {
+        sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0));
     }
 
     /**
@@ -1023,14 +1056,17 @@
      * Internal private functions
      ********************************************************/
 
-    private void updateTetherState(ArrayList<String> available, ArrayList<String> tethered) {
-
-        boolean wifiTethered = false;
-        boolean wifiAvailable = false;
-
+    private void checkAndSetConnectivityInstance() {
         if (mCm == null) {
             mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         }
+    }
+
+    private boolean startTethering(ArrayList<String> available) {
+
+        boolean wifiAvailable = false;
+
+        checkAndSetConnectivityInstance();
 
         String[] wifiRegexs = mCm.getTetherableWifiRegexs();
 
@@ -1052,18 +1088,43 @@
                     } catch (Exception e) {
                         Log.e(TAG, "Error configuring interface " + intf + ", :" + e);
                         setWifiApEnabled(null, false);
-                        return;
+                        return false;
                     }
 
                     if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                         Log.e(TAG, "Error tethering on " + intf);
                         setWifiApEnabled(null, false);
-                        return;
+                        return false;
                     }
-                    break;
+                    return true;
                 }
             }
         }
+        // We found no interfaces to tether
+        return false;
+    }
+
+    private void stopTethering() {
+
+        checkAndSetConnectivityInstance();
+
+        /* Clear the interface config to allow dhcp correctly configure new
+           ip settings */
+        InterfaceConfiguration ifcg = null;
+        try {
+            ifcg = nwService.getInterfaceConfig(mInterfaceName);
+            if (ifcg != null) {
+                ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
+                            "0.0.0.0"), 0);
+                nwService.setInterfaceConfig(mInterfaceName, ifcg);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error resetting interface " + mInterfaceName + ", :" + e);
+        }
+
+        if (mCm.untether(mInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+            Log.e(TAG, "Untether initiate failed!");
+        }
     }
 
     /**
@@ -1374,6 +1435,8 @@
         intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties));
         if (bssid != null)
             intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
+        if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED)
+            intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo));
         mContext.sendStickyBroadcast(intent);
     }
 
@@ -1579,130 +1642,33 @@
         WifiNative.reconnectCommand();
     }
 
-    private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) {
+    /* Current design is to not set the config on a running hostapd but instead
+     * stop and start tethering when user changes config on a running access point
+     *
+     * TODO: Add control channel setup through hostapd that allows changing config
+     * on a running daemon
+     */
+    private boolean startSoftApWithConfig(WifiConfiguration config) {
         if (config == null) {
             config = WifiApConfigStore.getApConfiguration();
         } else {
             WifiApConfigStore.setApConfiguration(config);
         }
         try {
-            if (currentStatus == SOFT_AP_STOPPED) {
-                nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
-            } else if (currentStatus == SOFT_AP_RUNNING) {
-                nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
-            }
+            nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
         } catch (Exception e) {
             Log.e(TAG, "Exception in softap start " + e);
             try {
-                nwService.stopAccessPoint();
+                nwService.stopAccessPoint(mInterfaceName);
                 nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
-            } catch (Exception ee) {
-                Log.e(TAG, "Exception during softap restart : " + ee);
+            } catch (Exception e1) {
+                Log.e(TAG, "Exception in softap re-start " + e1);
                 return false;
             }
         }
         return true;
     }
 
-
-    /*********************************************************
-     * Notifications from WifiMonitor
-     ********************************************************/
-
-    /**
-     * Stores supplicant state change information passed from WifiMonitor
-     */
-    static class StateChangeResult {
-        StateChangeResult(int networkId, String BSSID, SupplicantState state) {
-            this.state = state;
-            this.BSSID = BSSID;
-            this.networkId = networkId;
-        }
-        int networkId;
-        String BSSID;
-        SupplicantState state;
-    }
-
-    /**
-     * Send the tracker a notification that a user provided
-     * configuration caused authentication failure - this could
-     * be a password failure or a EAP authentication failure
-     */
-    void notifyAuthenticationFailure() {
-        sendMessage(AUTHENTICATION_FAILURE_EVENT);
-    }
-
-    /**
-     * Send a notification that the supplicant has detected overlapped
-     * WPS sessions
-     */
-    void notifyWpsOverlap() {
-        sendMessage(WPS_OVERLAP_EVENT);
-    }
-
-    /**
-     * Send the tracker a notification that a connection to the supplicant
-     * daemon has been established.
-     */
-    void notifySupplicantConnection() {
-        sendMessage(SUP_CONNECTION_EVENT);
-    }
-
-    /**
-     * Send the tracker a notification that connection to the supplicant
-     * daemon is lost
-     */
-    void notifySupplicantLost() {
-        sendMessage(SUP_DISCONNECTION_EVENT);
-    }
-
-    /**
-     * Send the tracker a notification that the state of Wifi connectivity
-     * has changed.
-     * @param networkId the configured network on which the state change occurred
-     * @param newState the new network state
-     * @param BSSID when the new state is {@link DetailedState#CONNECTED
-     * NetworkInfo.DetailedState.CONNECTED},
-     * this is the MAC address of the access point. Otherwise, it
-     * is {@code null}.
-     */
-    void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
-        if (newState == NetworkInfo.DetailedState.CONNECTED) {
-            sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT, networkId, 0, BSSID));
-        } else {
-            sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT, networkId, 0, BSSID));
-        }
-    }
-
-    /**
-     * Send the tracker a notification that the state of the supplicant
-     * has changed.
-     * @param networkId the configured network on which the state change occurred
-     * @param newState the new {@code SupplicantState}
-     */
-    void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) {
-        sendMessage(obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
-                new StateChangeResult(networkId, BSSID, newState)));
-    }
-
-    /**
-     * Send the tracker a notification that a scan has completed, and results
-     * are available.
-     */
-    void notifyScanResultsAvailable() {
-        /**
-         * Switch scan mode over to passive.
-         * Turning off scan-only mode happens only in "Connect" mode
-         */
-        setScanType(false);
-        sendMessage(SCAN_RESULTS_EVENT);
-    }
-
-    void notifyDriverHung() {
-        setWifiEnabled(false);
-        setWifiEnabled(true);
-    }
-
     /********************************************************
      * HSM states
      *******************************************************/
@@ -1712,6 +1678,18 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                    } else {
+                        Log.e(TAG, "WifiP2pService connection failure, error=" + message.arg1);
+                    }
+                    break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    Log.e(TAG, "WifiP2pService channel lost, message.arg1 =" + message.arg1);
+                    //TODO: Re-establish connection to state machine after a delay
+                    //mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
+                    break;
                 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
                     mBluetoothConnectionActive = (message.arg1 !=
                             BluetoothAdapter.STATE_DISCONNECTED);
@@ -1746,19 +1724,22 @@
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
                 case CMD_START_AP:
+                case CMD_START_AP_SUCCESS:
+                case CMD_START_AP_FAILURE:
                 case CMD_STOP_AP:
+                case CMD_TETHER_INTERFACE:
                 case CMD_START_SCAN:
                 case CMD_DISCONNECT:
                 case CMD_RECONNECT:
                 case CMD_REASSOCIATE:
-                case SUP_CONNECTION_EVENT:
-                case SUP_DISCONNECTION_EVENT:
-                case NETWORK_CONNECTION_EVENT:
-                case NETWORK_DISCONNECTION_EVENT:
-                case SCAN_RESULTS_EVENT:
-                case SUPPLICANT_STATE_CHANGE_EVENT:
-                case AUTHENTICATION_FAILURE_EVENT:
-                case WPS_OVERLAP_EVENT:
+                case WifiMonitor.SUP_CONNECTION_EVENT:
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.SCAN_RESULTS_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                case WifiMonitor.WPS_OVERLAP_EVENT:
                 case CMD_BLACKLIST_NETWORK:
                 case CMD_CLEAR_BLACKLIST:
                 case CMD_SET_SCAN_MODE:
@@ -1775,11 +1756,20 @@
                 case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                     break;
+                case WifiMonitor.DRIVER_HUNG_EVENT:
+                    setWifiEnabled(false);
+                    setWifiEnabled(true);
+                    break;
                 case CMD_START_WPS:
                     /* Return failure when the state machine cannot handle WPS initiation*/
                     mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED,
                                 new WpsResult(Status.FAILURE));
                     break;
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    // turn off wifi and defer to be handled in DriverUnloadedState
+                    setWifiEnabled(false);
+                    deferMessage(message);
+                    break;
                 default:
                     Log.e(TAG, "Error! unhandled message" + message);
                     break;
@@ -1806,6 +1796,11 @@
             else {
                 transitionTo(mDriverUnloadedState);
             }
+
+            //Connect to WifiP2pService
+            mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
+            mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
+
         }
     }
 
@@ -1912,14 +1907,7 @@
                     }
                     break;
                 case CMD_START_AP:
-                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_STOPPED)) {
-                        Log.d(TAG, "Soft AP start successful");
-                        setWifiApState(WIFI_AP_STATE_ENABLED);
-                        transitionTo(mSoftApStartedState);
-                    } else {
-                        Log.d(TAG, "Soft AP start failed");
-                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                    }
+                    transitionTo(mSoftApStartingState);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2021,7 +2009,11 @@
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
                 case CMD_LOAD_DRIVER:
-                    transitionTo(mDriverLoadingState);
+                    mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
+                    transitionTo(mWaitForP2pDisableState);
+                    break;
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2055,7 +2047,7 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case SUP_CONNECTION_EVENT:
+                case WifiMonitor.SUP_CONNECTION_EVENT:
                     Log.d(TAG, "Supplicant connection established");
                     setWifiState(WIFI_STATE_ENABLED);
                     mSupplicantRestartCount = 0;
@@ -2072,13 +2064,10 @@
 
                     WifiConfigStore.initialize(mContext);
 
-                    //TODO: initialize and fix multicast filtering
-                    //mWM.initializeMulticastFiltering();
-
                     sendSupplicantConnectionChangedBroadcast(true);
                     transitionTo(mDriverStartedState);
                     break;
-                case SUP_DISCONNECTION_EVENT:
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
                     if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
                         Log.e(TAG, "Failed to setup control channel, restart supplicant");
                         WifiNative.killSupplicant();
@@ -2141,7 +2130,7 @@
                 case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */
                     transitionTo(mSupplicantStoppingState);
                     break;
-                case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
                     Log.e(TAG, "Connection lost, restart supplicant");
                     WifiNative.killSupplicant();
                     WifiNative.closeSupplicantConnection();
@@ -2153,7 +2142,7 @@
                     transitionTo(mDriverLoadedState);
                     sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     break;
-                case SCAN_RESULTS_EVENT:
+                case WifiMonitor.SCAN_RESULTS_EVENT:
                     eventLoggingEnabled = false;
                     setScanResults(WifiNative.scanResultsCommand());
                     sendScanResultsAvailableBroadcast();
@@ -2255,10 +2244,10 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case SUP_CONNECTION_EVENT:
+                case WifiMonitor.SUP_CONNECTION_EVENT:
                     Log.e(TAG, "Supplicant connection received while stopping");
                     break;
-                case SUP_DISCONNECTION_EVENT:
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
                     Log.d(TAG, "Supplicant connection lost");
                     WifiNative.closeSupplicantConnection();
                     transitionTo(mDriverLoadedState);
@@ -2298,7 +2287,7 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-               case SUPPLICANT_STATE_CHANGE_EVENT:
+               case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     SupplicantState state = handleSupplicantStateChange(message);
                     /* If suplicant is exiting out of INTERFACE_DISABLED state into
                      * a state that indicates driver has started, it is ready to
@@ -2311,10 +2300,10 @@
                     /* Queue driver commands & connection events */
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
-                case NETWORK_CONNECTION_EVENT:
-                case NETWORK_DISCONNECTION_EVENT:
-                case AUTHENTICATION_FAILURE_EVENT:
-                case WPS_OVERLAP_EVENT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                case WifiMonitor.WPS_OVERLAP_EVENT:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_COUNTRY_CODE:
@@ -2357,6 +2346,16 @@
             /* initialize network state */
             setNetworkDetailedState(DetailedState.DISCONNECTED);
 
+            /* Remove any filtering on Multicast v6 at start */
+            WifiNative.stopFilteringMulticastV6Packets();
+
+            /* Reset Multicast v4 filtering state */
+            if (mFilteringMulticastV4Packets.get()) {
+                WifiNative.startFilteringMulticastV4Packets();
+            } else {
+                WifiNative.stopFilteringMulticastV4Packets();
+            }
+
             if (mIsScanMode) {
                 WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
                 WifiNative.disconnectCommand();
@@ -2417,10 +2416,22 @@
                     mWakeLock.release();
                     break;
                 case CMD_START_PACKET_FILTERING:
-                    WifiNative.startPacketFiltering();
+                    if (message.arg1 == MULTICAST_V6) {
+                        WifiNative.startFilteringMulticastV6Packets();
+                    } else if (message.arg1 == MULTICAST_V4) {
+                        WifiNative.startFilteringMulticastV4Packets();
+                    } else {
+                        Log.e(TAG, "Illegal arugments to CMD_START_PACKET_FILTERING");
+                    }
                     break;
                 case CMD_STOP_PACKET_FILTERING:
-                    WifiNative.stopPacketFiltering();
+                    if (message.arg1 == MULTICAST_V6) {
+                        WifiNative.stopFilteringMulticastV6Packets();
+                    } else if (message.arg1 == MULTICAST_V4) {
+                        WifiNative.stopFilteringMulticastV4Packets();
+                    } else {
+                        Log.e(TAG, "Illegal arugments to CMD_STOP_PACKET_FILTERING");
+                    }
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2449,7 +2460,7 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     SupplicantState state = handleSupplicantStateChange(message);
                     if (state == SupplicantState.INTERFACE_DISABLED) {
                         transitionTo(mDriverStoppedState);
@@ -2493,7 +2504,7 @@
                    WifiNative.startDriverCommand();
                    mWakeLock.release();
                    break;
-                case SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     SupplicantState state = handleSupplicantStateChange(message);
                     /* A driver start causes supplicant to first report an INTERFACE_DISABLED
                      * state before transitioning out of it for connection. Stay in
@@ -2539,9 +2550,9 @@
                 case CMD_DISCONNECT:
                 case CMD_RECONNECT:
                 case CMD_REASSOCIATE:
-                case SUPPLICANT_STATE_CHANGE_EVENT:
-                case NETWORK_CONNECTION_EVENT:
-                case NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2562,14 +2573,14 @@
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             StateChangeResult stateChangeResult;
             switch(message.what) {
-                case AUTHENTICATION_FAILURE_EVENT:
-                    mSupplicantStateTracker.sendMessage(AUTHENTICATION_FAILURE_EVENT);
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                    mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT);
                     break;
-                case WPS_OVERLAP_EVENT:
+                case WifiMonitor.WPS_OVERLAP_EVENT:
                     /* We just need to broadcast the error */
                     sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR);
                     break;
-                case SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     handleSupplicantStateChange(message);
                    break;
                     /* Do a redundant disconnect without transition */
@@ -2611,12 +2622,12 @@
                     mWpsStateMachine.sendMessage(Message.obtain(message));
                     transitionTo(mWaitForWpsCompletionState);
                     break;
-                case SCAN_RESULTS_EVENT:
+                case WifiMonitor.SCAN_RESULTS_EVENT:
                     /* Set the scan setting back to "connect" mode */
                     WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
                     /* Handle scan results */
                     return NOT_HANDLED;
-                case NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
                     Log.d(TAG,"Network connection established");
                     mLastNetworkId = message.arg1;
                     mLastBssid = (String) message.obj;
@@ -2630,7 +2641,7 @@
                     sendNetworkStateChangeBroadcast(mLastBssid);
                     transitionTo(mConnectingState);
                     break;
-                case NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                     Log.d(TAG,"Network connection lost");
                     handleNetworkDisconnect();
                     transitionTo(mDisconnectedState);
@@ -2717,7 +2728,7 @@
                   deferMessage(message);
                   break;
                   /* Ignore */
-              case NETWORK_CONNECTION_EVENT:
+              case WifiMonitor.NETWORK_CONNECTION_EVENT:
                   break;
               case CMD_STOP_DRIVER:
                   sendMessage(CMD_DISCONNECT);
@@ -2782,10 +2793,7 @@
                     deferMessage(message);
                     break;
                 case CMD_REQUEST_CM_WAKELOCK:
-                    if (mCm == null) {
-                        mCm = (ConnectivityManager)mContext.getSystemService(
-                                Context.CONNECTIVITY_SERVICE);
-                    }
+                    checkAndSetConnectivityInstance();
                     mCm.requestNetworkTransitionWakelock(TAG);
                     break;
                 case CMD_SET_SCAN_MODE:
@@ -2827,7 +2835,7 @@
                     }
                     break;
                     /* Ignore */
-                case NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
                     break;
                 case CMD_RSSI_POLL:
                     eventLoggingEnabled = false;
@@ -2888,7 +2896,7 @@
                     }
                     break;
                     /* Handle in  DisconnectedState */
-                case SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     deferMessage(message);
                     break;
                 default:
@@ -2973,9 +2981,9 @@
                     }
                     break;
                     /* Ignore network disconnect */
-                case NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                     break;
-                case SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
                     /* ConnectModeState does the rest of the handling */
@@ -2987,7 +2995,7 @@
                     }
                     /* Handled in parent state */
                     return NOT_HANDLED;
-                case SCAN_RESULTS_EVENT:
+                case WifiMonitor.SCAN_RESULTS_EVENT:
                     /* Re-enable background scan when a pending scan result is received */
                     if (mEnableBackgroundScan && mScanResultIsPending) {
                         WifiNative.enableBackgroundScanCommand(true);
@@ -3030,10 +3038,10 @@
                 case CMD_ENABLE_NETWORK:
                 case CMD_RECONNECT:
                 case CMD_REASSOCIATE:
-                case NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */
+                case WifiMonitor.NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */
                     deferMessage(message);
                     break;
-                case NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                     Log.d(TAG,"Network connection lost");
                     handleNetworkDisconnect();
                     break;
@@ -3050,6 +3058,67 @@
         }
     }
 
+    class SoftApStartingState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Log.d(TAG, getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+            final Message message = Message.obtain(getCurrentMessage());
+            final WifiConfiguration config = (WifiConfiguration) message.obj;
+
+            // start hostapd on a seperate thread
+            new Thread(new Runnable() {
+                public void run() {
+                    if (startSoftApWithConfig(config)) {
+                        Log.d(TAG, "Soft AP start successful");
+                        sendMessage(CMD_START_AP_SUCCESS);
+                    } else {
+                        Log.d(TAG, "Soft AP start failed");
+                        sendMessage(CMD_START_AP_FAILURE);
+                    }
+                }
+            }).start();
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch(message.what) {
+                case CMD_LOAD_DRIVER:
+                case CMD_UNLOAD_DRIVER:
+                case CMD_START_SUPPLICANT:
+                case CMD_STOP_SUPPLICANT:
+                case CMD_START_AP:
+                case CMD_STOP_AP:
+                case CMD_START_DRIVER:
+                case CMD_STOP_DRIVER:
+                case CMD_SET_SCAN_MODE:
+                case CMD_SET_SCAN_TYPE:
+                case CMD_SET_HIGH_PERF_MODE:
+                case CMD_SET_COUNTRY_CODE:
+                case CMD_SET_FREQUENCY_BAND:
+                case CMD_START_PACKET_FILTERING:
+                case CMD_STOP_PACKET_FILTERING:
+                case CMD_TETHER_INTERFACE:
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    deferMessage(message);
+                    break;
+                case CMD_START_AP_SUCCESS:
+                    setWifiApState(WIFI_AP_STATE_ENABLED);
+                    transitionTo(mSoftApStartedState);
+                    break;
+                case CMD_START_AP_FAILURE:
+                    // initiate driver unload
+                    sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            return HANDLED;
+        }
+    }
+
     class SoftApStartedState extends State {
         @Override
         public void enter() {
@@ -3063,37 +3132,33 @@
                 case CMD_STOP_AP:
                     Log.d(TAG,"Stopping Soft AP");
                     setWifiApState(WIFI_AP_STATE_DISABLING);
-
-                    if (mCm == null) {
-                        mCm = (ConnectivityManager) mContext.getSystemService(
-                                Context.CONNECTIVITY_SERVICE);
-                    }
-                    if (mCm.untether(SOFTAP_IFACE) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                        Log.e(TAG, "Untether initiate failed!");
-                    }
+                    stopTethering();
                     try {
-                        nwService.stopAccessPoint();
+                        nwService.stopAccessPoint(mInterfaceName);
                     } catch(Exception e) {
                         Log.e(TAG, "Exception in stopAccessPoint()");
                     }
                     transitionTo(mDriverLoadedState);
                     break;
                 case CMD_START_AP:
-                    Log.d(TAG,"SoftAP set on a running access point");
-                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_RUNNING)) {
-                        Log.d(TAG, "Soft AP start successful");
-                        setWifiApState(WIFI_AP_STATE_ENABLED);
-                        transitionTo(mSoftApStartedState);
-                    } else {
-                        Log.d(TAG, "Soft AP start failed");
-                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                    }
+                    // Ignore a start on a running access point
                     break;
-                /* Fail client mode operation when soft AP is enabled */
+                    /* Fail client mode operation when soft AP is enabled */
                 case CMD_START_SUPPLICANT:
                     Log.e(TAG,"Cannot start supplicant with a running soft AP");
                     setWifiState(WIFI_STATE_UNKNOWN);
                     break;
+                case CMD_TETHER_INTERFACE:
+                    ArrayList<String> available = (ArrayList<String>) message.obj;
+                    if (startTethering(available)) {
+                        transitionTo(mTetheredState);
+                    }
+                    break;
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    // turn of soft Ap and defer to be handled in DriverUnloadedState
+                    setWifiApEnabled(null, false);
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -3101,4 +3166,68 @@
             return HANDLED;
         }
     }
+
+    class WaitForP2pDisableState extends State {
+        private int mSavedArg;
+        @Override
+        public void enter() {
+            if (DBG) Log.d(TAG, getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+            //Preserve the argument arg1 that has information used in DriverLoadingState
+            mSavedArg = getCurrentMessage().arg1;
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch(message.what) {
+                case WifiP2pService.WIFI_ENABLE_PROCEED:
+                    //restore argument from original message (CMD_LOAD_DRIVER)
+                    message.arg1 = mSavedArg;
+                    transitionTo(mDriverLoadingState);
+                    break;
+                case CMD_LOAD_DRIVER:
+                case CMD_UNLOAD_DRIVER:
+                case CMD_START_SUPPLICANT:
+                case CMD_STOP_SUPPLICANT:
+                case CMD_START_AP:
+                case CMD_STOP_AP:
+                case CMD_START_DRIVER:
+                case CMD_STOP_DRIVER:
+                case CMD_SET_SCAN_MODE:
+                case CMD_SET_SCAN_TYPE:
+                case CMD_SET_HIGH_PERF_MODE:
+                case CMD_SET_COUNTRY_CODE:
+                case CMD_SET_FREQUENCY_BAND:
+                case CMD_START_PACKET_FILTERING:
+                case CMD_STOP_PACKET_FILTERING:
+                    deferMessage(message);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            return HANDLED;
+        }
+    }
+
+    class TetheredState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Log.d(TAG, getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch(message.what) {
+               case CMD_TETHER_INTERFACE:
+                    // Ignore any duplicate interface available notifications
+                    // when in tethered state
+                    return HANDLED;
+                default:
+                    return NOT_HANDLED;
+            }
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiWatchdogService.java b/wifi/java/android/net/wifi/WifiWatchdogService.java
deleted file mode 100644
index bce4b3a..0000000
--- a/wifi/java/android/net/wifi/WifiWatchdogService.java
+++ /dev/null
@@ -1,765 +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 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;
-    }
-}
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
new file mode 100644
index 0000000..192abf0
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.DnsPinger;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.os.Message;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.util.Slog;
+
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+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;
+import java.util.regex.Pattern;
+
+/**
+ * {@link WifiWatchdogStateMachine} 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 window is activated if a walled garden is detected.
+ *
+ * @hide
+ */
+public class WifiWatchdogStateMachine extends StateMachine {
+
+
+    private static final boolean VDBG = false;
+    private static final boolean DBG = true;
+    private static final String WWSM_TAG = "WifiWatchdogStateMachine";
+
+    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 = 1;
+
+    private static final long DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS = 2 * 60 * 1000;
+    private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 10 * 60 * 1000;
+    private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000;
+
+    private static final int DEFAULT_MAX_SSID_BLACKLISTS = 7;
+    private static final int DEFAULT_NUM_DNS_PINGS = 5;
+    private static final int DEFAULT_MIN_DNS_RESPONSES = 3;
+    private static final long DNS_PING_INTERVAL_MS = 100;
+
+    private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 1500;
+
+    private static final long DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000;
+
+    private static final String DEFAULT_WALLED_GARDEN_URL = "http://www.google.com/";
+    private static final String DEFAULT_WALLED_GARDEN_PATTERN = "<title>.*Google.*</title>";
+
+
+    private static final int BASE = Protocol.BASE_WIFI_WATCHDOG;
+
+    /**
+     * Indicates the enable setting of WWS may have changed
+     */
+    private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1;
+
+    /**
+     * Indicates the wifi network state has changed. Passed w/ original intent
+     * which has a non-null networkInfo object
+     */
+    private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2;
+    /**
+     * Indicates the signal has changed. Passed with arg1
+     * {@link #mNetEventCounter} and arg2 [raw signal strength]
+     */
+    private static final int EVENT_RSSI_CHANGE = BASE + 3;
+    private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4;
+    private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5;
+    private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6;
+
+    private static final int MESSAGE_CHECK_STEP = BASE + 100;
+    private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101;
+    private static final int MESSAGE_HANDLE_BAD_AP = BASE + 102;
+    /**
+     * arg1 == mOnlineWatchState.checkCount
+     */
+    private static final int MESSAGE_SINGLE_DNS_CHECK = BASE + 103;
+    private static final int MESSAGE_NETWORK_FOLLOWUP = BASE + 104;
+
+    private Context mContext;
+    private ContentResolver mContentResolver;
+    private WifiManager mWifiManager;
+    private DnsPinger mDnsPinger;
+    private IntentFilter mIntentFilter;
+    private BroadcastReceiver mBroadcastReceiver;
+
+    private DefaultState mDefaultState = new DefaultState();
+    private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState();
+    private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState();
+    private NotConnectedState mNotConnectedState = new NotConnectedState();
+    private ConnectedState mConnectedState = new ConnectedState();
+    private DnsCheckingState mDnsCheckingState = new DnsCheckingState();
+    private OnlineWatchState mOnlineWatchState = new OnlineWatchState();
+    private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState();
+    private WalledGardenState mWalledGardenState = new WalledGardenState();
+    private BlacklistedApState mBlacklistedApState = new BlacklistedApState();
+
+    private long mDnsCheckShortIntervalMs;
+    private long mDnsCheckLongIntervalMs;
+    private long mWalledGardenIntervalMs;
+    private int mMaxSsidBlacklists;
+    private int mNumDnsPings;
+    private int mMinDnsResponses;
+    private int mDnsPingTimeoutMs;
+    private long mBlacklistFollowupIntervalMs;
+    private boolean mWalledGardenTestEnabled;
+    private String mWalledGardenUrl;
+    private Pattern mWalledGardenPattern;
+
+    private boolean mShowDisabledNotification;
+    /**
+     * The {@link WifiInfo} object passed to WWSM on network broadcasts
+     */
+    private WifiInfo mInitialConnInfo;
+    private int mNetEventCounter = 0;
+
+    /**
+     * Currently maintained but not used, TODO
+     */
+    private HashSet<String> mBssids = new HashSet<String>();
+    private int mNumCheckFailures = 0;
+
+    private Long mLastWalledGardenCheckTime = null;
+
+    /**
+     * This is set by the blacklisted state and reset when connected to a new AP.
+     * It triggers a disableNetwork call if a DNS check fails.
+     */
+    public boolean mDisableAPNextFailure = false;
+    public ConnectivityManager mConnectivityManager;
+
+    /**
+     * STATE MAP
+     *          Default
+     *         /       \
+     * Disabled     Enabled
+     *             /       \
+     * NotConnected      Connected
+     *                  /---------\
+     *               (all other states)
+     */
+    private WifiWatchdogStateMachine(Context context) {
+        super(WWSM_TAG);
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context,
+                ConnectivityManager.TYPE_WIFI);
+
+        setupNetworkReceiver();
+
+        // The content observer to listen needs a handler
+        registerForSettingsChanges();
+        registerForWatchdogToggle();
+        addState(mDefaultState);
+            addState(mWatchdogDisabledState, mDefaultState);
+            addState(mWatchdogEnabledState, mDefaultState);
+                addState(mNotConnectedState, mWatchdogEnabledState);
+                addState(mConnectedState, mWatchdogEnabledState);
+                    addState(mDnsCheckingState, mConnectedState);
+                    addState(mDnsCheckFailureState, mConnectedState);
+                    addState(mWalledGardenState, mConnectedState);
+                    addState(mBlacklistedApState, mConnectedState);
+                    addState(mOnlineWatchState, mConnectedState);
+
+        setInitialState(mWatchdogDisabledState);
+        updateSettings();
+        mShowDisabledNotification = getSettingsBoolean(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true);
+    }
+
+    public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
+        ContentResolver contentResolver = context.getContentResolver();
+        // Disable for wifi only devices.
+        if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null &&
+                "wifi-only".equals(SystemProperties.get("ro.carrier"))) {
+            putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false);
+        }
+        WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
+        wwsm.start();
+        wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED);
+        return wwsm;
+    }
+
+    /**
+   *
+   */
+    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)) {
+                    sendMessage(EVENT_NETWORK_STATE_CHANGE, intent);
+                } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+                    obtainMessage(EVENT_RSSI_CHANGE, mNetEventCounter,
+                            intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)).sendToTarget();
+                } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                    sendMessage(EVENT_SCAN_RESULTS_AVAILABLE);
+                } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                    sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE,
+                            intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                                    WifiManager.WIFI_STATE_UNKNOWN));
+                }
+            }
+        };
+
+        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 registerForWatchdogToggle() {
+        ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                sendMessage(EVENT_WATCHDOG_TOGGLED);
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON),
+                false, contentObserver);
+    }
+
+    /**
+     * Observes watchdogs secure setting changes.
+     */
+    private void registerForSettingsChanges() {
+        ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                sendMessage(EVENT_WATCHDOG_SETTINGS_CHANGE);
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS),
+                        false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_NUM_DNS_PINGS),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS),
+                        false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
+                false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN),
+                false, contentObserver);
+    }
+
+    /**
+     * 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(mWalledGardenUrl);
+            urlConnection = (HttpURLConnection) url.openConnection();
+            in = new BufferedInputStream(urlConnection.getInputStream());
+            Scanner scanner = new Scanner(in);
+            if (scanner.findInLine(mWalledGardenPattern) != 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 boolean rssiStrengthAboveCutoff(int rssi) {
+        return WifiManager.calculateSignalLevel(rssi, WIFI_SIGNAL_LEVELS) > LOW_SIGNAL_CUTOFF;
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("WatchdogStatus: ");
+        pw.print("State " + getCurrentState());
+        pw.println(", network [" + mInitialConnInfo + "]");
+        pw.print("checkFailures   " + mNumCheckFailures);
+        pw.println(", bssids: " + mBssids);
+        pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime);
+    }
+
+    private boolean isWatchdogEnabled() {
+        return getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true);
+    }
+
+    private void updateSettings() {
+        mDnsCheckShortIntervalMs = Secure.getLong(mContentResolver,
+                Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS,
+                DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS);
+        mDnsCheckLongIntervalMs = Secure.getLong(mContentResolver,
+                Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS,
+                DEFAULT_DNS_CHECK_LONG_INTERVAL_MS);
+        mMaxSsidBlacklists = Secure.getInt(mContentResolver,
+                Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS,
+                DEFAULT_MAX_SSID_BLACKLISTS);
+        mNumDnsPings = Secure.getInt(mContentResolver,
+                Secure.WIFI_WATCHDOG_NUM_DNS_PINGS,
+                DEFAULT_NUM_DNS_PINGS);
+        mMinDnsResponses = Secure.getInt(mContentResolver,
+                Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES,
+                DEFAULT_MIN_DNS_RESPONSES);
+        mDnsPingTimeoutMs = Secure.getInt(mContentResolver,
+                Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS,
+                DEFAULT_DNS_PING_TIMEOUT_MS);
+        mBlacklistFollowupIntervalMs = Secure.getLong(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS,
+                DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS);
+        mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true);
+        mWalledGardenUrl = getSettingsStr(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL,
+                DEFAULT_WALLED_GARDEN_URL);
+        mWalledGardenPattern = Pattern.compile(getSettingsStr(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN,
+                DEFAULT_WALLED_GARDEN_PATTERN));
+        mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
+                Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
+                DEFAULT_WALLED_GARDEN_INTERVAL_MS);
+    }
+
+    /**
+     * 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(). Null if never.
+     * @return non negative time to wait
+     */
+    private static long waitTime(long interval, Long lastTime) {
+        if (lastTime == null)
+            return 0;
+        long wait = interval + lastTime - SystemClock.elapsedRealtime();
+        return wait > 0 ? wait : 0;
+    }
+
+    private static String wifiInfoToStr(WifiInfo wifiInfo) {
+        if (wifiInfo == null)
+            return "null";
+        return "(" + wifiInfo.getSSID() + ", " + wifiInfo.getBSSID() + ")";
+    }
+
+    /**
+   *
+   */
+    private void resetWatchdogState() {
+        mInitialConnInfo = null;
+        mDisableAPNextFailure = false;
+        mLastWalledGardenCheckTime = null;
+        mNumCheckFailures = 0;
+        mBssids.clear();
+    }
+
+    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 displayDisabledNetworkNotification() {
+        Resources r = Resources.getSystem();
+        CharSequence title =
+                r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled);
+        CharSequence msg =
+                r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled_detailed);
+
+        Notification wifiDisabledWarning = new Notification.Builder(mContext)
+            .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
+            .setDefaults(Notification.DEFAULT_ALL)
+            .setTicker(title)
+            .setContentTitle(title)
+            .setContentText(msg)
+            .setContentIntent(PendingIntent.getActivity(mContext, 0,
+                    new Intent(Settings.ACTION_WIFI_IP_SETTINGS)
+                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
+            .setWhen(System.currentTimeMillis())
+            .setAutoCancel(true)
+            .getNotification();
+
+        NotificationManager notificationManager = (NotificationManager) mContext
+                .getSystemService(Context.NOTIFICATION_SERVICE);
+
+        notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning);
+    }
+
+    /**
+     * @return true if there is definitely no mobile data (we'll be less aggressive)
+     */
+    private boolean hasNoMobileData() {
+        if (mConnectivityManager == null) {
+            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+        }
+        NetworkInfo mobileNetInfo = mConnectivityManager.getNetworkInfo(
+                ConnectivityManager.TYPE_MOBILE);
+        if (mobileNetInfo == null || !mobileNetInfo.isAvailable()) {
+            return true;
+        }
+        return false;
+    }
+
+    class DefaultState extends State {
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_WATCHDOG_SETTINGS_CHANGE:
+                    updateSettings();
+                    if (VDBG) {
+                        Slog.d(WWSM_TAG, "Updating wifi-watchdog secure settings");
+                    }
+                    return HANDLED;
+            }
+            if (VDBG) {
+                Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " +
+                        getCurrentState().getName());
+            }
+            return HANDLED;
+        }
+    }
+
+    class WatchdogDisabledState extends State {
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_WATCHDOG_TOGGLED:
+                    if (isWatchdogEnabled())
+                        transitionTo(mNotConnectedState);
+                    return HANDLED;
+            }
+            return NOT_HANDLED;
+        }
+    }
+
+    class WatchdogEnabledState extends State {
+        @Override
+        public void enter() {
+            resetWatchdogState();
+            mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
+            Slog.i(WWSM_TAG, "WifiWatchdogService enabled");
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_WATCHDOG_TOGGLED:
+                    if (!isWatchdogEnabled())
+                        transitionTo(mWatchdogDisabledState);
+                    return HANDLED;
+                case EVENT_NETWORK_STATE_CHANGE:
+                    Intent stateChangeIntent = (Intent) msg.obj;
+                    NetworkInfo networkInfo = (NetworkInfo)
+                            stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+
+                    switch (networkInfo.getState()) {
+                        case CONNECTED:
+                            // WifiInfo wifiInfo = (WifiInfo)
+                            //         stateChangeIntent
+                            //                 .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
+                            // TODO : Replace with above code when API is changed
+                            WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+                            if (wifiInfo == null) {
+                                Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!");
+                                return HANDLED;
+                            }
+
+                            if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
+                                Slog.e(WWSM_TAG, "Received wifiInfo object with null elts: "
+                                        + wifiInfoToStr(wifiInfo));
+                                return HANDLED;
+                            }
+
+                            initConnection(wifiInfo);
+                            transitionTo(mDnsCheckingState);
+                            mNetEventCounter++;
+                            return HANDLED;
+                        case DISCONNECTED:
+                        case DISCONNECTING:
+                            mNetEventCounter++;
+                            transitionTo(mNotConnectedState);
+                            return HANDLED;
+                    }
+                    return HANDLED;
+                case EVENT_WIFI_RADIO_STATE_CHANGE:
+                    if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
+                        Slog.i(WWSM_TAG, "WifiStateDisabling -- Resetting WatchdogState");
+                        resetWatchdogState();
+                        mNetEventCounter++;
+                        transitionTo(mNotConnectedState);
+                    }
+                    return HANDLED;
+            }
+
+            return NOT_HANDLED;
+        }
+
+        /**
+         * @param wifiInfo Info object with non-null ssid and bssid
+         */
+        private void initConnection(WifiInfo wifiInfo) {
+            if (VDBG) {
+                Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) +
+                        " ==> new " + wifiInfoToStr(wifiInfo));
+            }
+
+            if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) {
+                resetWatchdogState();
+            } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) {
+                mDisableAPNextFailure = false;
+            }
+            mInitialConnInfo = wifiInfo;
+        }
+
+        @Override
+        public void exit() {
+            mContext.unregisterReceiver(mBroadcastReceiver);
+            Slog.i(WWSM_TAG, "WifiWatchdogService disabled");
+        }
+    }
+
+    class NotConnectedState extends State {
+    }
+
+    class ConnectedState extends State {
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_SCAN_RESULTS_AVAILABLE:
+                    String curSsid = mInitialConnInfo.getSSID();
+                    List<ScanResult> results = mWifiManager.getScanResults();
+                    int oldNumBssids = mBssids.size();
+
+                    if (results == null) {
+                        if (DBG) {
+                            Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
+                        }
+                        return HANDLED;
+                    }
+
+                    for (ScanResult result : results) {
+                        if (result == null || result.SSID == null) {
+                            if (VDBG) {
+                                Slog.v(WWSM_TAG, "Received invalid scan result: " + result);
+                            }
+                            continue;
+                        }
+                        if (curSsid.equals(result.SSID))
+                            mBssids.add(result.BSSID);
+                    }
+                    return HANDLED;
+                case EVENT_WATCHDOG_SETTINGS_CHANGE:
+                    // Stop current checks, but let state update
+                    transitionTo(mOnlineWatchState);
+                    return NOT_HANDLED;
+            }
+            return NOT_HANDLED;
+        }
+
+    }
+
+    class DnsCheckingState extends State {
+        int dnsCheckTries = 0;
+        int dnsCheckSuccesses = 0;
+        String dnsCheckLogStr = "";
+
+        @Override
+        public void enter() {
+            dnsCheckSuccesses = 0;
+            dnsCheckTries = 0;
+            if (DBG) {
+                Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
+                dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
+                        mDnsPinger.getDns(), mInitialConnInfo.getSSID());
+            }
+
+            sendCheckStepMessage(0);
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            if (msg.what != MESSAGE_CHECK_STEP) {
+                return NOT_HANDLED;
+            }
+            if (msg.arg1 != mNetEventCounter) {
+                Slog.d(WWSM_TAG, "Check step out of sync, ignoring...");
+                return HANDLED;
+            }
+
+            long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                    mDnsPingTimeoutMs);
+
+            dnsCheckTries++;
+            if (pingResponseTime >= 0)
+                dnsCheckSuccesses++;
+
+            if (DBG) {
+                if (pingResponseTime >= 0) {
+                    dnsCheckLogStr += "|" + pingResponseTime;
+                } else {
+                    dnsCheckLogStr += "|x";
+                }
+            }
+
+            if (VDBG) {
+                Slog.v(WWSM_TAG, dnsCheckLogStr);
+            }
+
+            /**
+             * After a full ping count, if we have more responses than this
+             * cutoff, the outcome is success; else it is 'failure'.
+             */
+
+            /**
+             * Our final success count will be at least this big, so we're
+             * guaranteed to succeed.
+             */
+            if (dnsCheckSuccesses >= mMinDnsResponses) {
+                // DNS CHECKS OK, NOW WALLED GARDEN
+                if (DBG) {
+                    Slog.d(WWSM_TAG, dnsCheckLogStr + "|  SUCCESS");
+                }
+
+                if (!shouldCheckWalledGarden()) {
+                    transitionTo(mOnlineWatchState);
+                    return HANDLED;
+                }
+
+                mLastWalledGardenCheckTime = SystemClock.elapsedRealtime();
+                if (isWalledGardenConnection()) {
+                    if (DBG)
+                        Slog.d(WWSM_TAG,
+                                "Walled garden test complete - walled garden detected");
+                    transitionTo(mWalledGardenState);
+                } else {
+                    if (DBG)
+                        Slog.d(WWSM_TAG, "Walled garden test complete - online");
+                    transitionTo(mOnlineWatchState);
+                }
+                return HANDLED;
+            }
+
+            /**
+             * Our final count will be at most the current count plus the
+             * remaining pings - we're guaranteed to fail.
+             */
+            int remainingChecks = mNumDnsPings - dnsCheckTries;
+            if (remainingChecks + dnsCheckSuccesses < mMinDnsResponses) {
+                if (DBG) {
+                    Slog.d(WWSM_TAG, dnsCheckLogStr + "|  FAILURE");
+                }
+                transitionTo(mDnsCheckFailureState);
+                return HANDLED;
+            }
+
+            // Still in dns check step
+            sendCheckStepMessage(DNS_PING_INTERVAL_MS);
+            return HANDLED;
+        }
+
+        private boolean shouldCheckWalledGarden() {
+            if (!mWalledGardenTestEnabled) {
+                if (VDBG)
+                    Slog.v(WWSM_TAG, "Skipping walled garden check - disabled");
+                return false;
+            }
+            long waitTime = waitTime(mWalledGardenIntervalMs,
+                    mLastWalledGardenCheckTime);
+            if (waitTime > 0) {
+                if (DBG) {
+                    Slog.d(WWSM_TAG, "Skipping walled garden check - wait " +
+                            waitTime + " ms.");
+                }
+                return false;
+            }
+            return true;
+        }
+
+        private void sendCheckStepMessage(long delay) {
+            sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay);
+        }
+
+    }
+
+    class OnlineWatchState extends State {
+        /**
+         * Signals a short-wait message is enqueued for the current 'guard' counter
+         */
+        boolean unstableSignalChecks = false;
+
+        /**
+         * The signal is unstable.  We should enqueue a short-wait check, if one is enqueued
+         * already
+         */
+        boolean signalUnstable = false;
+
+        /**
+         * A monotonic counter to ensure that at most one check message will be processed from any
+         * set of check messages currently enqueued.  Avoids duplicate checks when a low-signal
+         * event is observed.
+         */
+        int checkGuard = 0;
+        Long lastCheckTime = null;
+
+        @Override
+        public void enter() {
+            lastCheckTime = SystemClock.elapsedRealtime();
+            signalUnstable = false;
+            checkGuard++;
+            unstableSignalChecks = false;
+            triggerSingleDnsCheck();
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_RSSI_CHANGE:
+                    if (msg.arg1 != mNetEventCounter) {
+                        if (DBG) {
+                            Slog.d(WWSM_TAG, "Rssi change message out of sync, ignoring");
+                        }
+                        return HANDLED;
+                    }
+                    int newRssi = msg.arg2;
+                    signalUnstable = !rssiStrengthAboveCutoff(newRssi);
+                    if (VDBG) {
+                        Slog.v(WWSM_TAG, "OnlineWatchState:: new rssi " + newRssi + " --> level " +
+                                WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS));
+                    }
+
+                    if (signalUnstable && !unstableSignalChecks) {
+                        if (VDBG) {
+                            Slog.v(WWSM_TAG, "Sending triggered check msg");
+                        }
+                        triggerSingleDnsCheck();
+                    }
+                    return HANDLED;
+                case MESSAGE_SINGLE_DNS_CHECK:
+                    if (msg.arg1 != checkGuard) {
+                        if (VDBG) {
+                            Slog.v(WWSM_TAG, "Single check msg out of sync, ignoring.");
+                        }
+                        return HANDLED;
+                    }
+                    lastCheckTime = SystemClock.elapsedRealtime();
+                    long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                            mDnsPingTimeoutMs);
+                    if (responseTime >= 0) {
+                        if (VDBG) {
+                            Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: "
+                                    + responseTime);
+                        }
+
+                        checkGuard++;
+                        unstableSignalChecks = false;
+                        triggerSingleDnsCheck();
+                    } else {
+                        if (DBG) {
+                            Slog.d(WWSM_TAG, "Single dns ping failure. Starting full checks.");
+                        }
+                        transitionTo(mDnsCheckingState);
+                    }
+                    return HANDLED;
+            }
+            return NOT_HANDLED;
+        }
+
+        /**
+         * Times a dns check with an interval based on {@link #signalUnstable}
+         */
+        private void triggerSingleDnsCheck() {
+            long waitInterval;
+            if (signalUnstable) {
+                waitInterval = mDnsCheckShortIntervalMs;
+                unstableSignalChecks = true;
+            } else {
+                waitInterval = mDnsCheckLongIntervalMs;
+            }
+            sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0),
+                    waitTime(waitInterval, lastCheckTime));
+        }
+    }
+
+    class DnsCheckFailureState extends State {
+
+        @Override
+        public void enter() {
+            mNumCheckFailures++;
+            obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget();
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            if (msg.what != MESSAGE_HANDLE_BAD_AP) {
+                return NOT_HANDLED;
+            }
+
+            if (msg.arg1 != mNetEventCounter) {
+                if (VDBG) {
+                    Slog.v(WWSM_TAG, "Msg out of sync, ignoring...");
+                }
+                return HANDLED;
+            }
+
+            if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) {
+                if (hasNoMobileData()) {
+                    Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
+                            "  Going idle...");
+                    // This state should be called idle -- will be changing flow.
+                    transitionTo(mNotConnectedState);
+                    return HANDLED;
+                }
+                // TODO : Unban networks if they had low signal ?
+                Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo)
+                        + ".  " + "numCheckFailures " + mNumCheckFailures
+                        + ", numAPs " + mBssids.size());
+                mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId());
+                if (mShowDisabledNotification) {
+                    displayDisabledNetworkNotification();
+                    mShowDisabledNotification = false;
+                    putSettingsBoolean(mContentResolver,
+                            Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, false);
+                }
+                transitionTo(mNotConnectedState);
+            } else {
+                Slog.i(WWSM_TAG, "Blacklisting current BSSID.  " + wifiInfoToStr(mInitialConnInfo)
+                       + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size());
+
+                mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID());
+                mWifiManager.reassociate();
+                transitionTo(mBlacklistedApState);
+            }
+            return HANDLED;
+        }
+    }
+
+    class WalledGardenState extends State {
+        @Override
+        public void enter() {
+            obtainMessage(MESSAGE_HANDLE_WALLED_GARDEN, mNetEventCounter, 0).sendToTarget();
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            if (msg.what != MESSAGE_HANDLE_WALLED_GARDEN) {
+                return NOT_HANDLED;
+            }
+
+            if (msg.arg1 != mNetEventCounter) {
+                if (VDBG) {
+                    Slog.v(WWSM_TAG, "WalledGardenState::Msg out of sync, ignoring...");
+                }
+                return HANDLED;
+            }
+            popUpBrowser();
+            transitionTo(mOnlineWatchState);
+            return HANDLED;
+        }
+    }
+
+    class BlacklistedApState extends State {
+        @Override
+        public void enter() {
+            mDisableAPNextFailure = true;
+            sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0),
+                    mBlacklistFollowupIntervalMs);
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            if (msg.what != MESSAGE_NETWORK_FOLLOWUP) {
+                return NOT_HANDLED;
+            }
+
+            if (msg.arg1 != mNetEventCounter) {
+                if (VDBG) {
+                    Slog.v(WWSM_TAG, "BlacklistedApState::Msg out of sync, ignoring...");
+                }
+                return HANDLED;
+            }
+
+            transitionTo(mDnsCheckingState);
+            return HANDLED;
+        }
+    }
+
+
+    /**
+     * Convenience function for retrieving a single secure settings value
+     * as a string with a default value.
+     *
+     * @param cr The ContentResolver to access.
+     * @param name The name of the setting to retrieve.
+     * @param def Value to return if the setting is not defined.
+     *
+     * @return The setting's current value, or 'def' if it is not defined
+     */
+    private static String getSettingsStr(ContentResolver cr, String name, String def) {
+        String v = Settings.Secure.getString(cr, name);
+        return v != null ? v : def;
+    }
+
+    /**
+     * Convenience function for retrieving a single secure settings value
+     * as a boolean.  Note that internally setting values are always
+     * stored as strings; this function converts the string to a boolean
+     * for you.  The default value will be returned if the setting is
+     * not defined or not a valid boolean.
+     *
+     * @param cr The ContentResolver to access.
+     * @param name The name of the setting to retrieve.
+     * @param def Value to return if the setting is not defined.
+     *
+     * @return The setting's current value, or 'def' if it is not defined
+     * or not a valid boolean.
+     */
+    private static boolean getSettingsBoolean(ContentResolver cr, String name, boolean def) {
+        return Settings.Secure.getInt(cr, name, def ? 1 : 0) == 1;
+    }
+
+    /**
+     * Convenience function for updating a single settings value as an
+     * integer. This will either create a new entry in the table if the
+     * given name does not exist, or modify the value of the existing row
+     * with that name.  Note that internally setting values are always
+     * stored as strings, so this function converts the given value to a
+     * string before storing it.
+     *
+     * @param cr The ContentResolver to access.
+     * @param name The name of the setting to modify.
+     * @param value The new value for the setting.
+     * @return true if the value was set, false on database errors
+     */
+    private static boolean putSettingsBoolean(ContentResolver cr, String name, boolean value) {
+        return Settings.Secure.putInt(cr, name, value ? 1 : 0);
+    }
+
+
+}
diff --git a/wifi/java/android/net/wifi/WpsConfiguration.java b/wifi/java/android/net/wifi/WpsConfiguration.java
index 12d951f..2e7689a 100644
--- a/wifi/java/android/net/wifi/WpsConfiguration.java
+++ b/wifi/java/android/net/wifi/WpsConfiguration.java
@@ -30,13 +30,16 @@
  */
 public class WpsConfiguration implements Parcelable {
 
+    /* Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details */
     public enum Setup {
-        /* Wi-Fi protected setup push button configuration */
+        /* Push button configuration */
         PBC,
-        /* Wi-Fi protected setup pin method configuration with pin obtained from access point */
-        PIN_FROM_ACCESS_POINT,
-        /* Wi-Fi protected setup pin method configuration with pin obtained from device */
-        PIN_FROM_DEVICE,
+        /* Display pin method configuration - pin is generated and displayed on device */
+        DISPLAY,
+        /* Keypad pin method configuration - pin is entered on device */
+        KEYPAD,
+        /* Label pin method configuration - pin is obtained from a printed label */
+        LABEL,
         /* Invalid config */
         INVALID
     }
diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java
index 120b228..af089ab 100644
--- a/wifi/java/android/net/wifi/WpsStateMachine.java
+++ b/wifi/java/android/net/wifi/WpsStateMachine.java
@@ -22,7 +22,7 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.net.wifi.WifiStateMachine.StateChangeResult;
+import android.net.wifi.StateChangeResult;
 import android.net.wifi.WpsResult.Status;
 import android.os.Handler;
 import android.os.Message;
@@ -99,10 +99,10 @@
                         case PBC:
                             result = WifiConfigStore.startWpsPbc(mWpsConfig);
                             break;
-                        case PIN_FROM_ACCESS_POINT:
+                        case KEYPAD:
                             result = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig);
                             break;
-                        case PIN_FROM_DEVICE:
+                        case DISPLAY:
                             result = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig);
                             break;
                         default:
@@ -139,7 +139,7 @@
             boolean retValue = HANDLED;
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState supState = (SupplicantState) stateChangeResult.state;
                     switch (supState) {
@@ -194,7 +194,7 @@
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
                 //Ignore supplicant state changes
-                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     break;
                 default:
                     retValue = NOT_HANDLED;
diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
new file mode 100644
index 0000000..a0c7dd1
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -0,0 +1,31 @@
+/**
+ * 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.p2p;
+
+import android.os.Messenger;
+
+/**
+ * Interface that WifiP2pService implements
+ *
+ * {@hide}
+ */
+interface IWifiP2pManager
+{
+    Messenger getMessenger();
+    boolean isP2pSupported();
+}
+
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl
new file mode 100644
index 0000000..ea3b280
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pConfig;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
new file mode 100644
index 0000000..fff5ee3
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.net.wifi.WpsConfiguration;
+import android.net.wifi.WpsConfiguration.Setup;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * A class representing a Wi-Fi P2p configuration
+ * @hide
+ */
+public class WifiP2pConfig implements Parcelable {
+
+    /**
+     * Device name
+     */
+    public String deviceName;
+
+    /**
+     * Device address
+     */
+    public String deviceAddress;
+
+    /**
+     * WPS configuration
+     */
+    public WpsConfiguration wpsConfig;
+
+    /**
+     * This is an integer value between 0 and 15 where 0 indicates the least
+     * inclination to be a group owner and 15 indicates the highest inclination
+     * to be a group owner.
+     */
+    public int groupOwnerIntent;
+
+    public boolean isPersistent;
+
+    public boolean joinExistingGroup;
+
+    /**
+     * Channel frequency in MHz
+     */
+    public int channel;
+
+    public WifiP2pConfig() {
+        //set defaults
+        wpsConfig = new WpsConfiguration();
+        wpsConfig.setup = Setup.PBC;
+    }
+
+    /* P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 */
+    public WifiP2pConfig(String supplicantEvent) throws IllegalArgumentException {
+        String[] tokens = supplicantEvent.split(" ");
+
+        if (tokens.length < 2 || !tokens[0].equals("P2P-GO-NEG-REQUEST")) {
+            throw new IllegalArgumentException("Malformed supplicant event");
+        }
+
+        deviceAddress = tokens[1];
+        wpsConfig = new WpsConfiguration();
+
+        if (tokens.length > 2) {
+            String[] nameVal = tokens[2].split("=");
+            int devPasswdId;
+            try {
+                devPasswdId = Integer.parseInt(nameVal[1]);
+            } catch (NumberFormatException e) {
+                devPasswdId = 0;
+            }
+            //As defined in wps/wps_defs.h
+            switch (devPasswdId) {
+                case 0x00:
+                    wpsConfig.setup = Setup.LABEL;
+                    break;
+                case 0x01:
+                    wpsConfig.setup = Setup.KEYPAD;
+                    break;
+                case 0x04:
+                    wpsConfig.setup = Setup.PBC;
+                    break;
+                case 0x05:
+                    wpsConfig.setup = Setup.DISPLAY;
+                    break;
+                default:
+                    wpsConfig.setup = Setup.PBC;
+                    break;
+            }
+        }
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append("Device: ").append(deviceName);
+        sbuf.append("\n address: ").append(deviceAddress);
+        sbuf.append("\n wps: ").append(wpsConfig);
+        sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
+        sbuf.append("\n isPersistent: ").append(isPersistent);
+        sbuf.append("\n joinExistingGroup: ").append(joinExistingGroup);
+        sbuf.append("\n channel: ").append(channel);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    public WifiP2pConfig(WifiP2pConfig source) {
+        if (source != null) {
+            //TODO: implement
+       }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(deviceName);
+        dest.writeString(deviceAddress);
+        dest.writeParcelable(wpsConfig, flags);
+        dest.writeInt(groupOwnerIntent);
+        dest.writeInt(isPersistent ? 1 : 0);
+        dest.writeInt(joinExistingGroup ? 1 : 0);
+        dest.writeInt(channel);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pConfig> CREATOR =
+        new Creator<WifiP2pConfig>() {
+            public WifiP2pConfig createFromParcel(Parcel in) {
+                WifiP2pConfig config = new WifiP2pConfig();
+                config.deviceName = in.readString();
+                config.deviceAddress = in.readString();
+                config.wpsConfig = (WpsConfiguration) in.readParcelable(null);
+                config.groupOwnerIntent = in.readInt();
+                config.isPersistent = (in.readInt() == 1);
+                config.joinExistingGroup = (in.readInt() == 1);
+                config.channel = in.readInt();
+                return config;
+            }
+
+            public WifiP2pConfig[] newArray(int size) {
+                return new WifiP2pConfig[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl
new file mode 100644
index 0000000..8790c6f
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pDevice;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
new file mode 100644
index 0000000..83dc285
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.util.regex.Pattern;
+
+/**
+ * A class representing a Wi-Fi p2p device
+ * @hide
+ */
+public class WifiP2pDevice implements Parcelable {
+
+    private static final String TAG = "WifiP2pDevice";
+    /**
+     * Device name
+     */
+    public String deviceName;
+
+    /**
+     * Device MAC address
+     */
+    public String deviceAddress;
+
+    /**
+     * interfaceAddress
+     *
+     * This address is used during group owner negotiation as the Intended
+     * P2P Interface Address and the group interface will be created with
+     * address as the local address in case of successfully completed
+     * negotiation.
+     */
+    public String interfaceAddress;
+
+    /**
+     * Primary device type
+     */
+    public String primaryDeviceType;
+
+    /**
+     * Secondary device type
+     */
+    public String secondaryDeviceType;
+
+
+    // These definitions match the ones in wpa_supplicant
+    /* WPS config methods supported */
+    private static final int WPS_CONFIG_USBA            = 0x0001;
+    private static final int WPS_CONFIG_ETHERNET        = 0x0002;
+    private static final int WPS_CONFIG_LABEL           = 0x0004;
+    private static final int WPS_CONFIG_DISPLAY         = 0x0008;
+    private static final int WPS_CONFIG_EXT_NFC_TOKEN   = 0x0010;
+    private static final int WPS_CONFIG_INT_NFC_TOKEN   = 0x0020;
+    private static final int WPS_CONFIG_NFC_INTERFACE   = 0x0040;
+    private static final int WPS_CONFIG_PUSHBUTTON      = 0x0080;
+    private static final int WPS_CONFIG_KEYPAD          = 0x0100;
+    private static final int WPS_CONFIG_VIRT_PUSHBUTTON = 0x0280;
+    private static final int WPS_CONFIG_PHY_PUSHBUTTON  = 0x0480;
+    private static final int WPS_CONFIG_VIRT_DISPLAY    = 0x2008;
+    private static final int WPS_CONFIG_PHY_DISPLAY     = 0x4008;
+
+    /* Device Capability bitmap */
+    private static final int DEVICE_CAPAB_SERVICE_DISCOVERY         = 1;
+    private static final int DEVICE_CAPAB_CLIENT_DISCOVERABILITY    = 1<<1;
+    private static final int DEVICE_CAPAB_CONCURRENT_OPER           = 1<<2;
+    private static final int DEVICE_CAPAB_INFRA_MANAGED             = 1<<3;
+    private static final int DEVICE_CAPAB_DEVICE_LIMIT              = 1<<4;
+    private static final int DEVICE_CAPAB_INVITATION_PROCEDURE      = 1<<5;
+
+    /* Group Capability bitmap */
+    private static final int GROUP_CAPAB_GROUP_OWNER                = 1;
+    private static final int GROUP_CAPAB_PERSISTENT_GROUP           = 1<<1;
+    private static final int GROUP_CAPAB_GROUP_LIMIT                = 1<<2;
+    private static final int GROUP_CAPAB_INTRA_BSS_DIST             = 1<<3;
+    private static final int GROUP_CAPAB_CROSS_CONN                 = 1<<4;
+    private static final int GROUP_CAPAB_PERSISTENT_RECONN          = 1<<5;
+    private static final int GROUP_CAPAB_GROUP_FORMATION            = 1<<6;
+
+    /**
+     * WPS config methods supported
+     */
+    public int wpsConfigMethodsSupported;
+
+    /**
+     * Device capability
+     */
+    public int deviceCapability;
+
+    /**
+     * Group capability
+     */
+    public int groupCapability;
+
+    public enum Status {
+        CONNECTED,
+        INVITED,
+        FAILED,
+        AVAILABLE,
+        UNAVAILABLE,
+    }
+
+    public Status status = Status.UNAVAILABLE;
+
+    public WifiP2pDevice() {
+    }
+
+    /**
+     * @param string formats supported include
+     *  P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13
+     *  pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27
+     *  group_capab=0x0
+     *
+     *  P2P-DEVICE-LOST p2p_dev_addr=fa:7b:7a:42:02:13
+     *
+     *  fa:7b:7a:42:02:13
+     *
+     *  P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
+     *  pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+     *  group_capab=0x0
+     *
+     *  P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
+     *  pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+     *  group_capab=0x0
+     *
+     *  P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27
+     *  pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
+     *  group_capab=0x0
+     *
+     *  Note: The events formats can be looked up in the wpa_supplicant code
+     */
+    public WifiP2pDevice(String string) throws IllegalArgumentException {
+        String[] tokens = string.split(" ");
+
+        if (tokens.length < 1) {
+            throw new IllegalArgumentException("Malformed supplicant event");
+        }
+
+        /* Just a device address */
+        if (tokens.length == 1) {
+            deviceAddress = string;
+            return;
+        }
+
+        Pattern p = Pattern.compile("(?:[0-9a-f]{2}:){5}[0-9a-f]{2}", Pattern.CASE_INSENSITIVE);
+        if (p.matcher(tokens[1]).matches()) interfaceAddress = tokens[1];
+
+        for (String token : tokens) {
+            String[] nameValue = token.split("=");
+            if (nameValue.length != 2) continue;
+
+            if (nameValue[0].equals("p2p_dev_addr")) {
+                deviceAddress = nameValue[1];
+                continue;
+            }
+
+            if (nameValue[0].equals("pri_dev_type")) {
+                primaryDeviceType = nameValue[1];
+                continue;
+            }
+
+            if (nameValue[0].equals("name")) {
+                deviceName = trimQuotes(nameValue[1]);
+            }
+
+            if (nameValue[0].equals("config_methods")) {
+                wpsConfigMethodsSupported = parseHex(nameValue[1]);
+                continue;
+            }
+
+            if (nameValue[0].equals("dev_capab")) {
+                deviceCapability = parseHex(nameValue[1]);
+                continue;
+            }
+
+            if (nameValue[0].equals("group_capab")) {
+                groupCapability = parseHex(nameValue[1]);
+                continue;
+            }
+        }
+
+        if (tokens[0].startsWith("P2P-DEVICE-FOUND")) {
+            status = Status.AVAILABLE;
+        }
+    }
+
+    public boolean isGroupOwner() {
+        return (groupCapability & GROUP_CAPAB_GROUP_OWNER) != 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (!(obj instanceof WifiP2pDevice)) return false;
+
+        WifiP2pDevice other = (WifiP2pDevice) obj;
+        if (other == null || other.deviceAddress == null) {
+            return (deviceAddress == null);
+        }
+        //STOPSHIP: fix later
+        //return other.deviceAddress.equals(deviceAddress);
+        return other.deviceAddress.startsWith(deviceAddress.substring(0,8));
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append("Device: ").append(deviceName);
+        sbuf.append("\n deviceAddress: ").append(deviceAddress);
+        sbuf.append("\n interfaceAddress: ").append(interfaceAddress);
+        sbuf.append("\n primary type: ").append(primaryDeviceType);
+        sbuf.append("\n secondary type: ").append(secondaryDeviceType);
+        sbuf.append("\n wps: ").append(wpsConfigMethodsSupported);
+        sbuf.append("\n grpcapab: ").append(groupCapability);
+        sbuf.append("\n devcapab: ").append(deviceCapability);
+        sbuf.append("\n status: ").append(status);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    public WifiP2pDevice(WifiP2pDevice source) {
+        if (source != null) {
+            deviceName = source.deviceName;
+            deviceAddress = source.deviceAddress;
+            interfaceAddress = source.interfaceAddress;
+            primaryDeviceType = source.primaryDeviceType;
+            secondaryDeviceType = source.secondaryDeviceType;
+            wpsConfigMethodsSupported = source.wpsConfigMethodsSupported;
+            deviceCapability = source.deviceCapability;
+            groupCapability = source.groupCapability;
+            status = source.status;
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(deviceName);
+        dest.writeString(deviceAddress);
+        dest.writeString(interfaceAddress);
+        dest.writeString(primaryDeviceType);
+        dest.writeString(secondaryDeviceType);
+        dest.writeInt(wpsConfigMethodsSupported);
+        dest.writeInt(deviceCapability);
+        dest.writeInt(groupCapability);
+        dest.writeString(status.name());
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pDevice> CREATOR =
+        new Creator<WifiP2pDevice>() {
+            public WifiP2pDevice createFromParcel(Parcel in) {
+                WifiP2pDevice device = new WifiP2pDevice();
+                device.deviceName = in.readString();
+                device.deviceAddress = in.readString();
+                device.interfaceAddress = in.readString();
+                device.primaryDeviceType = in.readString();
+                device.secondaryDeviceType = in.readString();
+                device.wpsConfigMethodsSupported = in.readInt();
+                device.deviceCapability = in.readInt();
+                device.groupCapability = in.readInt();
+                device.status = Status.valueOf(in.readString());
+                return device;
+            }
+
+            public WifiP2pDevice[] newArray(int size) {
+                return new WifiP2pDevice[size];
+            }
+        };
+
+    private String trimQuotes(String str) {
+        str = str.trim();
+        if (str.startsWith("'") && str.endsWith("'")) {
+            return str.substring(1, str.length()-1);
+        }
+        return str;
+    }
+
+    //supported formats: 0x1abc, 0X1abc, 1abc
+    private int parseHex(String hexString) {
+        int num = 0;
+        if (hexString.startsWith("0x") || hexString.startsWith("0X")) {
+            hexString = hexString.substring(2);
+        }
+
+        try {
+            num = Integer.parseInt(hexString, 16);
+        } catch(NumberFormatException e) {
+            Log.e(TAG, "Failed to parse hex string " + hexString);
+        }
+        return num;
+    }
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl
new file mode 100644
index 0000000..6c79009
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pDeviceList;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
new file mode 100644
index 0000000..4ec23b8
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A class representing a Wi-Fi P2p device list
+ * @hide
+ */
+public class WifiP2pDeviceList implements Parcelable {
+
+    private Collection<WifiP2pDevice> mDevices;
+
+    public WifiP2pDeviceList() {
+        mDevices = new ArrayList<WifiP2pDevice>();
+    }
+
+    //copy constructor
+    public WifiP2pDeviceList(WifiP2pDeviceList source) {
+        if (source != null) {
+            mDevices = source.getDeviceList();
+        }
+    }
+
+    public WifiP2pDeviceList(ArrayList<WifiP2pDevice> devices) {
+        mDevices = new ArrayList<WifiP2pDevice>();
+        for (WifiP2pDevice device : devices) {
+            mDevices.add(device);
+        }
+    }
+
+    public void clear() {
+        mDevices.clear();
+    }
+
+    public void add(WifiP2pDevice device) {
+        if (device == null) return;
+        if (mDevices.contains(device)) return;
+        mDevices.add(device);
+    }
+
+    public boolean remove(WifiP2pDevice device) {
+        if (device == null) return false;
+        return mDevices.remove(device);
+    }
+
+    public Collection<WifiP2pDevice> getDeviceList() {
+        return Collections.unmodifiableCollection(mDevices);
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        for (WifiP2pDevice device : mDevices) {
+            sbuf.append("\n").append(device);
+        }
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mDevices.size());
+        for(WifiP2pDevice device : mDevices) {
+            dest.writeParcelable(device, flags);
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pDeviceList> CREATOR =
+        new Creator<WifiP2pDeviceList>() {
+            public WifiP2pDeviceList createFromParcel(Parcel in) {
+                WifiP2pDeviceList deviceList = new WifiP2pDeviceList();
+
+                int deviceCount = in.readInt();
+                for (int i = 0; i < deviceCount; i++) {
+                    deviceList.add((WifiP2pDevice)in.readParcelable(null));
+                }
+                return deviceList;
+            }
+
+            public WifiP2pDeviceList[] newArray(int size) {
+                return new WifiP2pDeviceList[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl
new file mode 100644
index 0000000..403f2b1
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pGroup;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
new file mode 100644
index 0000000..ca6e4d5
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A class representing a Wi-Fi P2p group
+ * @hide
+ */
+public class WifiP2pGroup implements Parcelable {
+
+    /** The network name */
+    private String mNetworkName;
+
+    /** The network bssid */
+    private String mNetworkBssid;
+
+    /** Group owner */
+    private WifiP2pDevice mOwner;
+
+    /** Device is group owner */
+    private boolean mIsGroupOwner;
+
+    /** Group clients */
+    private List<WifiP2pDevice> mClients = new ArrayList<WifiP2pDevice>();
+
+    private int mChannel;
+
+    /**
+     * The network passphrase
+     * <p/>
+     * The passphrase used for WPA2-PSK
+     */
+    private String mPassphrase;
+
+    /**
+     * TODO: fix
+     * Sometimes supplicant sends a psk
+     */
+    private String mPsk;
+
+    /** Indicates that the group is persistent */
+    private boolean mIsPersistent;
+
+    private String mInterface;
+
+    public WifiP2pGroup() {
+    }
+
+    /**
+     * @param string formats supported include
+     *
+     *  P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437
+     *  [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|
+     *  passphrase="fKG4jMe3"] go_dev_addr=fa:7b:7a:42:02:13
+     *
+     *  P2P-GROUP-REMOVED p2p-wlan0-0 [client|GO] reason=REQUESTED
+     *
+     *  P2P-INVITATION-RECEIVED sa=fa:7b:7a:42:02:13 go_dev_addr=f8:7b:7a:42:02:13
+     *  bssid=fa:7b:7a:42:82:13 unknown-network
+     *
+     *  Note: The events formats can be looked up in the wpa_supplicant code
+     */
+    public WifiP2pGroup(String supplicantEvent) throws IllegalArgumentException {
+
+        String[] tokens = supplicantEvent.split(" ");
+
+        if (tokens.length < 3) {
+            throw new IllegalArgumentException("Malformed supplicant event");
+        }
+
+        if (tokens[0].startsWith("P2P-GROUP")) {
+            mInterface = tokens[1];
+            mIsGroupOwner = tokens[2].equals("GO");
+
+            for (String token : tokens) {
+                String[] nameValue = token.split("=");
+                if (nameValue.length != 2) continue;
+
+                if (nameValue[0].equals("ssid")) {
+                    mNetworkName = nameValue[1];
+                    continue;
+                }
+
+                if (nameValue[0].equals("freq")) {
+                    try {
+                        mChannel = Integer.parseInt(nameValue[1]);
+                    } catch (NumberFormatException e) {
+                        mChannel = 0; //invalid
+                    }
+                    continue;
+                }
+
+                if (nameValue[0].equals("psk")) {
+                    mPsk = nameValue[1];
+                    continue;
+                }
+
+                if (nameValue[0].equals("passphrase")) {
+                    mPassphrase = nameValue[1];
+                    continue;
+                }
+
+                if (nameValue[0].equals("go_dev_addr")) {
+                    mOwner = new WifiP2pDevice(nameValue[1]);
+                }
+            }
+        } else if (tokens[0].equals("P2P-INVITATION-RECEIVED")) {
+            for (String token : tokens) {
+                String[] nameValue = token.split("=");
+                if (nameValue.length != 2) continue;
+
+                if (nameValue[0].equals("go_dev_addr")) {
+                    mOwner = new WifiP2pDevice(nameValue[1]);
+                    continue;
+                }
+
+                if (nameValue[0].equals("bssid")) {
+                    mNetworkBssid = nameValue[1];
+                }
+            }
+        } else {
+            throw new IllegalArgumentException("Malformed supplicant event");
+        }
+    }
+
+    public boolean isGroupOwner() {
+        return mIsGroupOwner;
+    }
+
+    public WifiP2pDevice getOwner() {
+        return mOwner;
+    }
+
+    public void addClient(String address) {
+        addClient(new WifiP2pDevice(address));
+    }
+
+    public void addClient(WifiP2pDevice device) {
+        for (WifiP2pDevice client : mClients) {
+            if (client.equals(device)) return;
+        }
+        mClients.add(device);
+    }
+
+    public boolean removeClient(String address) {
+        return mClients.remove(new WifiP2pDevice(address));
+    }
+
+    public boolean removeClient(WifiP2pDevice device) {
+        return mClients.remove(device);
+    }
+
+    public boolean isClientListEmpty() {
+        return mClients.size() == 0;
+    }
+
+    public Collection<WifiP2pDevice> getClientList() {
+        return Collections.unmodifiableCollection(mClients);
+    }
+
+    public String getInterface() {
+        return mInterface;
+    }
+
+    // TODO: implement
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        //sbuf.append("SSID: ").append(SSID);
+        //sbuf.append("\n passphrase: ").append(passphrase);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    // TODO: implement
+    public WifiP2pGroup(WifiP2pGroup source) {
+        if (source != null) {
+       }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    // STOPSHIP: implement
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pGroup> CREATOR =
+        new Creator<WifiP2pGroup>() {
+            public WifiP2pGroup createFromParcel(Parcel in) {
+                WifiP2pGroup group = new WifiP2pGroup();
+                return group;
+            }
+
+            public WifiP2pGroup[] newArray(int size) {
+                return new WifiP2pGroup[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
new file mode 100644
index 0000000..ea212ac
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.WorkSource;
+import android.os.Messenger;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+/**
+ * This class provides the API for managing Wi-Fi p2p
+ * connectivity. Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String)
+ * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
+ *
+ * It deals with the following:
+ * <ul>
+ * <li>Wi-Fi peer discovery and connection setup. Allows applications to initiate a discovery to
+ * find available peers and then setup a connection </li>
+ * <li>Configuration and status query. Allows applications to fetch the current list
+ * of available and connected peers and query connection status </li>
+ * <li>Intent actions that are broadcast to track operations
+ * on a p2p connection</li>
+ * </ul>
+ * @hide
+ */
+public class WifiP2pManager {
+    /**
+     * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String WIFI_P2P_STATE_CHANGED_ACTION =
+        "android.net.wifi.P2P_STATE_CHANGED";
+
+    /**
+     * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled.
+     * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
+     *
+     * @see #WIFI_P2P_STATE_DISABLED
+     * @see #WIFI_P2P_STATE_ENABLED
+     */
+    public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
+
+    /**
+     * Wi-Fi p2p is disabled.
+     *
+     * @see #WIFI_P2P_STATE_CHANGED_ACTION
+     * @see #getWifiP2pState()
+     */
+    public static final int WIFI_P2P_STATE_DISABLED = 1;
+
+    /**
+     * Wi-Fi p2p is enabled.
+     *
+     * @see #WIFI_P2P_STATE_CHANGED_ACTION
+     * @see #getWifiP2pState()
+     */
+    public static final int WIFI_P2P_STATE_ENABLED = 2;
+
+    /**
+     * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
+     * has changed. One extra provides the new state
+     * in the form of a {@link android.net.NetworkInfo} object.
+     * @see #EXTRA_NETWORK_INFO
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION =
+        "android.net.wifi.CONNECTION_STATE_CHANGE";
+
+    /**
+     * The lookup key for a {@link android.net.NetworkInfo} object associated with the
+     * Wi-Fi network. Retrieve with
+     * {@link android.content.Intent#getParcelableExtra(String)}.
+     */
+    public static final String EXTRA_NETWORK_INFO = "networkInfo";
+
+    /**
+     * Broadcast intent action indicating that the available peer list has changed
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
+        "android.net.wifi.PEERS_CHANGED";
+
+    /**
+     * Activity Action: Pick a Wi-Fi p2p network to connect to.
+     * <p>Input: Nothing.
+     * <p>Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PICK_WIFI_P2P_NETWORK =
+        "android.net.wifi.PICK_WIFI_P2P_NETWORK";
+
+    IWifiP2pManager mService;
+
+    /* For communication with WifiP2pService */
+    private AsyncChannel mAsyncChannel = new AsyncChannel();
+
+    /* AsyncChannel notifications to apps */
+    public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED;
+    public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
+
+    private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
+
+    public static final int ENABLE_P2P                              = BASE + 1;
+    public static final int ENABLE_P2P_FAILED                       = BASE + 2;
+    public static final int ENABLE_P2P_SUCCEEDED                    = BASE + 3;
+
+    /* arg1 on ENABLE_P2P_FAILED indicates a reason for failure */
+    public static final int P2P_UNSUPPORTED     = 1;
+
+    public static final int DISABLE_P2P                             = BASE + 5;
+    public static final int DISABLE_P2P_FAILED                      = BASE + 6;
+    public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 7;
+
+    public static final int START_LISTEN_MODE                       = BASE + 9;
+    public static final int START_LISTEN_FAILED                     = BASE + 10;
+    public static final int START_LISTEN_SUCCEEDED                  = BASE + 11;
+
+    public static final int DISCOVER_PEERS                          = BASE + 13;
+    public static final int DISCOVER_PEERS_FAILED                   = BASE + 14;
+    public static final int DISCOVER_PEERS_SUCCEDED                 = BASE + 15;
+
+    public static final int CANCEL_DISCOVER_PEERS                   = BASE + 17;
+    public static final int CANCEL_DISCOVER_PEERS_FAILED            = BASE + 18;
+    public static final int CANCEL_DISCOVER_PEERS_SUCCEDED          = BASE + 19;
+
+    public static final int CONNECT                                 = BASE + 21;
+    public static final int CONNECT_FAILED                          = BASE + 22;
+    public static final int CONNECT_SUCCEEDED                       = BASE + 23;
+
+    public static final int CANCEL_CONNECT                          = BASE + 25;
+    public static final int CANCEL_CONNECT_FAILED                   = BASE + 26;
+    public static final int CANCEL_CONNECT_SUCCEDED                 = BASE + 27;
+
+    public static final int REJECT                                  = BASE + 28;
+    public static final int REJECT_FAILED                           = BASE + 29;
+    public static final int REJECT_SUCCEEDED                        = BASE + 30;
+
+    public static final int CREATE_GROUP                            = BASE + 31;
+    public static final int CREATE_GROUP_FAILED                     = BASE + 32;
+    public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 33;
+
+    public static final int REMOVE_GROUP                            = BASE + 34;
+    public static final int REMOVE_GROUP_FAILED                     = BASE + 35;
+    public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 36;
+
+    public static final int REQUEST_SETTINGS                        = BASE + 37;
+    public static final int RESPONSE_SETTINGS                       = BASE + 38;
+
+    public static final int REQUEST_PEERS                           = BASE + 39;
+    public static final int RESPONSE_PEERS                          = BASE + 40;
+
+    public static final int REQUEST_CONNECTION_STATUS               = BASE + 41;
+    public static final int RESPONSE_CONNECTION_STATUS              = BASE + 42;
+
+    public static final int WPS_PBC                                 = BASE + 43;
+    public static final int WPS_PIN                                 = BASE + 44;
+    public static final int WPS_PIN_AVAILABLE                       = BASE + 45;
+
+    /**
+     * Create a new WifiP2pManager instance. Applications use
+     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
+     * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}.
+     * @param service the Binder interface
+     * @param handler target for messages
+     * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
+     * is a system private class.
+     */
+    public WifiP2pManager(IWifiP2pManager service) {
+        mService = service;
+    }
+
+    /**
+     * Registers the application handler with the Wi-Fi framework.
+     * This function must be the first to be called before any p2p control
+     * or query operations can be performed.
+     * @param srcContext is the context of the source
+     * @param srcHandler is the handler on which the source receives messages
+     * @return {@code true} if the operation succeeded
+     */
+    public boolean connectHandler(Context srcContext, Handler srcHandler) {
+        Messenger messenger = getMessenger();
+        if (messenger == null) return false;
+        return mAsyncChannel.connectSync(srcContext, srcHandler, messenger)
+                == AsyncChannel.STATUS_SUCCESSFUL;
+    }
+
+    public boolean isP2pSupported() {
+        try {
+            return mService.isP2pSupported();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Sends in a request to the system to enable p2p. This will pop up a dialog
+     * to the user and upon authorization will enable p2p.
+     */
+    public void enableP2p() {
+        mAsyncChannel.sendMessage(ENABLE_P2P);
+    }
+
+    /**
+     * Sends in a request to the system to disable p2p. This will pop up a dialog
+     * to the user and upon authorization will enable p2p.
+     */
+    public void disableP2p() {
+        mAsyncChannel.sendMessage(DISABLE_P2P);
+    }
+
+    /**
+     * Set device in listen mode. This will make the device discoverable by
+     * another peer.
+     * A dialog to the user is thrown to request his permission since it can
+     * have a significant impact on power consumption
+     */
+     public void setListenState(int timeout) {
+        mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
+     }
+
+    /**
+     * Initiates peer discovery
+     */
+    public void discoverPeers() {
+        mAsyncChannel.sendMessage(DISCOVER_PEERS);
+    }
+
+    /**
+     * Initiates peer discovery with a timeout
+     */
+    public void discoverPeers(int timeout) {
+        mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
+    }
+
+    /**
+     * Cancel any existing peer discovery operation
+     */
+    public void cancelPeerDiscovery() {
+        mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
+    }
+
+    /**
+     * Start a p2p connection
+     *
+     * @param peer Configuration described in a {@link WifiP2pConfig} object.
+     */
+    public void connect(WifiP2pConfig config) {
+        mAsyncChannel.sendMessage(CONNECT, config);
+    }
+
+    /**
+     * Cancel any ongoing negotiation or disconnect from an existing group
+     */
+    public void disconnect() {
+        mAsyncChannel.sendMessage(CANCEL_CONNECT);
+    }
+
+    /**
+     * Create a p2p group. This is essentially an access point that can accept
+     * client connections.
+     */
+    public void createGroup() {
+        mAsyncChannel.sendMessage(CREATE_GROUP);
+    }
+
+    /**
+     * Remove the current group. This also removes the p2p interface created
+     * during group formation.
+     */
+    public void removeGroup() {
+        mAsyncChannel.sendMessage(REMOVE_GROUP);
+    }
+
+    /**
+     * Request current p2p settings. This returns a RESPONSE_SETTINGS on the source
+     * handler.
+     */
+    public void requestP2pSettings() {
+        mAsyncChannel.sendMessage(REQUEST_SETTINGS);
+    }
+
+    /**
+     * Request the list of peers. This returns a RESPONSE_PEERS on the source
+     * handler.
+     */
+    public void requestPeers() {
+        mAsyncChannel.sendMessage(REQUEST_PEERS);
+    }
+
+    /**
+     * Fetch device list from a RESPONSE_PEERS message
+     */
+    public WifiP2pDeviceList peersInResponse(Message msg) {
+        return (WifiP2pDeviceList) msg.obj;
+    }
+
+    /**
+     * Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on
+     * the source handler.
+     */
+    public void requestConnectionStatus() {
+        mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
+    }
+
+
+    /**
+     * Get a reference to WifiP2pService handler. This is used to establish
+     * an AsyncChannel communication with WifiService
+     *
+     * @return Messenger pointing to the WifiP2pService handler
+     * @hide
+     */
+    public Messenger getMessenger() {
+        try {
+            return mService.getMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
new file mode 100644
index 0000000..4988f0b
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -0,0 +1,880 @@
+/*
+ * 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.server;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiMonitor;
+import android.net.wifi.WifiNative;
+import android.net.wifi.WifiStateMachine;
+import android.net.wifi.WpsConfiguration;
+import android.net.wifi.WpsConfiguration.Setup;
+import android.net.wifi.p2p.IWifiP2pManager;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDevice.Status;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.Messenger;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.EditText;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Collection;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+import com.android.internal.R;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+/**
+ * WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
+ * communicate with this service to issue device discovery and connectivity requests
+ * through the WifiP2pManager interface. The state machine communicates with the wifi
+ * driver through wpa_supplicant and handles the event responses through WifiMonitor.
+ *
+ * Note that the term Wifi when used without a p2p suffix refers to the client mode
+ * of Wifi operation
+ * @hide
+ */
+public class WifiP2pService extends IWifiP2pManager.Stub {
+    private static final String TAG = "WifiP2pService";
+    private static final boolean DBG = true;
+
+    private Context mContext;
+
+    // Tracked to notify the user about wifi client/hotspot being shut down
+    // during p2p bring up
+    private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
+    private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
+
+    private P2pStateMachine mP2pStateMachine;
+    private AsyncChannel mReplyChannel = new AsyncChannel();;
+    private AsyncChannel mWifiChannel;
+
+    private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
+
+    /* Message sent to WifiStateMachine to indicate p2p enable is pending */
+    public static final int P2P_ENABLE_PENDING              =   BASE + 1;
+    /* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
+    public static final int WIFI_ENABLE_PROCEED             =   BASE + 2;
+
+    /* User accepted to disable Wi-Fi in order to enable p2p */
+    private static final int WIFI_DISABLE_USER_ACCEPT       =   BASE + 11;
+
+    private final boolean mP2pSupported;
+
+    public WifiP2pService(Context context) {
+        mContext = context;
+
+        mP2pSupported = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifi_p2p_support);
+
+        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
+        mP2pStateMachine.start();
+
+        // broadcasts
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+        mContext.registerReceiver(new WifiStateReceiver(), filter);
+
+   }
+
+    private class WifiStateReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_DISABLED);
+            } else if (intent.getAction().equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
+                mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
+                        WifiManager.WIFI_AP_STATE_DISABLED);
+            }
+        }
+    }
+
+    private void enforceAccessPermission() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
+                "WifiP2pService");
+    }
+
+    private void enforceChangePermission() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
+                "WifiP2pService");
+    }
+
+    /**
+     * Get a reference to handler. This is used by a client to establish
+     * an AsyncChannel communication with WifiP2pService
+     */
+    public Messenger getMessenger() {
+        enforceAccessPermission();
+        enforceChangePermission();
+        return new Messenger(mP2pStateMachine.getHandler());
+    }
+
+    /**
+     * Return if p2p is supported
+     */
+    public boolean isP2pSupported() {
+        enforceAccessPermission();
+        return mP2pSupported;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+    }
+
+
+    /**
+     * Handles interaction with WifiStateMachine
+     */
+    private class P2pStateMachine extends StateMachine {
+
+        private DefaultState mDefaultState = new DefaultState();
+        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
+        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
+        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
+        private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
+        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
+        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
+        // Inactive is when p2p is enabled with no connectivity
+        private InactiveState mInactiveState = new InactiveState();
+        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
+        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
+
+        private WifiMonitor mWifiMonitor = new WifiMonitor(this);
+
+        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
+        private WifiP2pGroup mGroup;
+
+        // Saved enable request message so the state machine can send an appropriate response
+        private Message mSavedEnableRequestMessage;
+
+        // Saved WifiP2pConfig from GO negotiation request
+        private WifiP2pConfig mSavedGoNegotiationConfig;
+
+        // Saved WifiP2pConfig from connect request
+        private WifiP2pConfig mSavedConnectConfig;
+
+        // Saved WifiP2pGroup from invitation request
+        private WifiP2pGroup mSavedP2pGroup;
+
+        P2pStateMachine(String name, boolean p2pSupported) {
+            super(name);
+
+            addState(mDefaultState);
+                addState(mP2pNotSupportedState, mDefaultState);
+                addState(mP2pDisablingState, mDefaultState);
+                addState(mP2pDisabledState, mDefaultState);
+                addState(mWaitForWifiDisableState, mDefaultState);
+                addState(mP2pEnablingState, mDefaultState);
+                addState(mP2pEnabledState, mDefaultState);
+                    addState(mInactiveState, mP2pEnabledState);
+                    addState(mGroupNegotiationState, mP2pEnabledState);
+                    addState(mGroupCreatedState, mP2pEnabledState);
+
+            if (p2pSupported) {
+                setInitialState(mP2pDisabledState);
+            } else {
+                setInitialState(mP2pNotSupportedState);
+            }
+        }
+
+    // TODO: Respond to every p2p request with success/failure
+    class DefaultState extends State {
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        if (DBG) Slog.d(TAG, "Full connection with WifiStateMachine established");
+                        mWifiChannel = (AsyncChannel) message.obj;
+                    } else {
+                        Slog.e(TAG, "Full connection failure, error = " + message.arg1);
+                        mWifiChannel = null;
+                    }
+                    break;
+
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
+                        Slog.e(TAG, "Send failed, client connection lost");
+                    } else {
+                        Slog.e(TAG, "Client connection lost with reason: " + message.arg1);
+                    }
+                    mWifiChannel = null;
+                    break;
+
+                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
+                    AsyncChannel ac = new AsyncChannel();
+                    ac.connect(mContext, getHandler(), message.replyTo);
+                    break;
+                case WifiStateMachine.WIFI_ENABLE_PENDING:
+                    // Disable p2p operation before we can respond
+                    sendMessage(WifiP2pManager.DISABLE_P2P);
+                    deferMessage(message);
+                    break;
+                case WifiP2pManager.ENABLE_P2P:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
+                    break;
+                case WifiP2pManager.DISABLE_P2P:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
+                    break;
+                case WifiP2pManager.START_LISTEN_MODE:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
+                    break;
+                case WifiP2pManager.DISCOVER_PEERS:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
+                    break;
+                case WifiP2pManager.CANCEL_DISCOVER_PEERS:
+                    mReplyChannel.replyToMessage(message,
+                            WifiP2pManager.CANCEL_DISCOVER_PEERS_FAILED);
+                    break;
+                case WifiP2pManager.CONNECT:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
+                    break;
+                case WifiP2pManager.CANCEL_CONNECT:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED);
+                    break;
+                case WifiP2pManager.REJECT:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.REJECT_FAILED);
+                    break;
+                case WifiP2pManager.CREATE_GROUP:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
+                    break;
+                case WifiP2pManager.REMOVE_GROUP:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
+                    break;
+                // TODO: fix
+                case WifiP2pManager.REQUEST_SETTINGS:
+                case WifiP2pManager.REQUEST_PEERS:
+                case WifiP2pManager.REQUEST_CONNECTION_STATUS:
+                    break;
+                // Ignore
+                case WIFI_DISABLE_USER_ACCEPT:
+                    break;
+                default:
+                    Slog.e(TAG, "Unhandled message " + message);
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class P2pNotSupportedState extends State {
+        @Override
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                // Allow Wi-Fi to proceed
+                case WifiStateMachine.WIFI_ENABLE_PENDING:
+                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    break;
+                case WifiP2pManager.ENABLE_P2P:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.DISABLE_P2P:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class P2pDisablingState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+            // TODO: fix later
+            WifiNative.unloadDriver();
+            transitionTo(mP2pDisabledState);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    WifiNative.unloadDriver();
+                    transitionTo(mP2pDisabledState);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+
+    class P2pDisabledState extends State {
+       @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiP2pManager.ENABLE_P2P:
+                    mSavedEnableRequestMessage = Message.obtain(message);
+                    OnClickListener listener = new OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            if (which == DialogInterface.BUTTON_POSITIVE) {
+                                sendMessage(WIFI_DISABLE_USER_ACCEPT);
+                            } else {
+                                mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
+                                        WifiP2pManager.ENABLE_P2P_FAILED);
+                            }
+                        }
+                    };
+
+                    // Show a user request dialog if we know Wi-Fi client/hotspot is in operation
+                    if (mWifiState != WifiManager.WIFI_STATE_DISABLED ||
+                            mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) {
+                        Resources r = Resources.getSystem();
+                        AlertDialog dialog = new AlertDialog.Builder(mContext)
+                            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+                            .setMessage(r.getString(R.string.wifi_p2p_turnon_message))
+                            .setPositiveButton(r.getString(R.string.ok), listener)
+                            .setNegativeButton(r.getString(R.string.cancel), listener)
+                            .create();
+                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+                        dialog.show();
+                    } else {
+                        mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
+                        transitionTo(mWaitForWifiDisableState);
+                    }
+                    break;
+                case WIFI_DISABLE_USER_ACCEPT:
+                    mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
+                    transitionTo(mWaitForWifiDisableState);
+                    break;
+                case WifiStateMachine.WIFI_ENABLE_PENDING:
+                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class WaitForWifiDisableState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiStateMachine.P2P_ENABLE_PROCEED:
+                    // TODO: fix this for p2p
+                    if (WifiNative.loadDriver() &&
+                            WifiNative.startSupplicant()) {
+                        Slog.d(TAG, "Wi-fi Direct start successful");
+                        mWifiMonitor.startMonitoring();
+                        transitionTo(mP2pEnablingState);
+                    } else {
+                        notifyP2pEnableFailure();
+                        mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
+                                WifiP2pManager.ENABLE_P2P_FAILED);
+                        transitionTo(mP2pDisabledState);
+                    }
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class P2pEnablingState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiMonitor.SUP_CONNECTION_EVENT:
+                    mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
+                            WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+                    transitionTo(mInactiveState);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class P2pEnabledState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+            sendP2pStateChangedBroadcast(true);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiP2pManager.DISABLE_P2P:
+                    // TODO: use stopSupplicant after control channel fixed
+                    WifiNative.killSupplicant();
+                    transitionTo(mP2pDisablingState);
+                    break;
+                case WifiP2pManager.DISCOVER_PEERS:
+                    int timeout = message.arg1;
+                    WifiNative.p2pFlush();
+                    WifiNative.p2pFind(timeout);
+                   break;
+                case WifiP2pManager.REQUEST_PEERS:
+                    mReplyChannel.replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    break;
+                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
+                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
+                    mPeers.add(device);
+                    sendP2pPeersChangedBroadcast();
+                    break;
+                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
+                    device = (WifiP2pDevice) message.obj;
+                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
+                    break;
+                case WifiP2pManager.CONNECT:
+                    if (DBG) Slog.d(TAG, getName() + " sending connect");
+                    mSavedConnectConfig = (WifiP2pConfig) message.obj;
+                    String pin = WifiNative.p2pConnect(mSavedConnectConfig);
+                    try {
+                        Integer.parseInt(pin);
+                        notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
+                    } catch (NumberFormatException ignore) {
+                        // do nothing if p2pConnect did not return a pin
+                    }
+                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED);
+                    sendP2pPeersChangedBroadcast();
+                    transitionTo(mGroupNegotiationState);
+                    break;
+                case WifiP2pManager.REJECT:
+                    if (DBG) Slog.d(TAG, getName() + " sending reject");
+                    WifiNative.p2pReject((String) message.obj);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+
+        @Override
+        public void exit() {
+            sendP2pStateChangedBroadcast(false);
+        }
+    }
+
+    class InactiveState extends State {
+        @Override public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
+                    mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj;
+                    notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
+                    break;
+                case WifiP2pManager.CREATE_GROUP:
+                    WifiNative.p2pGroupAdd();
+                    transitionTo(mGroupNegotiationState);
+                    break;
+                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
+                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
+                    notifyP2pInvitationReceived(group);
+                    break;
+               default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class GroupNegotiationState extends State {
+        @Override public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                // We ignore these right now, since we get a GROUP_STARTED notification
+                // afterwards
+                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
+                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
+                    if (DBG) Slog.d(TAG, getName() + " go success");
+                    break;
+                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
+                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+                    if (DBG) Slog.d(TAG, getName() + " go failure");
+                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
+                    mSavedConnectConfig = null;
+                    transitionTo(mInactiveState);
+                    break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    mGroup = (WifiP2pGroup) message.obj;
+                    if (DBG) Slog.d(TAG, getName() + " group started");
+                    // If this device is GO, do nothing since there is a follow up
+                    // AP_STA_CONNECTED event
+                    if (!mGroup.isGroupOwner()) {
+                        WifiP2pDevice groupOwner = mGroup.getOwner();
+                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
+                        sendP2pPeersChangedBroadcast();
+                    }
+                    transitionTo(mGroupCreatedState);
+                    break;
+               case WifiP2pManager.CANCEL_CONNECT:
+                    // TODO: fix
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class GroupCreatedState extends State {
+        @Override
+        public void enter() {
+            if (DBG) Slog.d(TAG, getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Slog.d(TAG, getName() + message.toString());
+            switch (message.what) {
+                case WifiMonitor.AP_STA_CONNECTED_EVENT:
+                    String address = (String) message.obj;
+                    mGroup.addClient(address);
+                    updateDeviceStatus(address, Status.CONNECTED);
+                    if (DBG) Slog.d(TAG, getName() + " ap sta connected");
+                    sendP2pPeersChangedBroadcast();
+                    break;
+                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
+                    address = (String) message.obj;
+                    updateDeviceStatus(address, Status.AVAILABLE);
+                    if (mGroup.removeClient(address)) {
+                        if (DBG) Slog.d(TAG, "Removed client " + address);
+                        if (mGroup.isClientListEmpty()) {
+                            Slog.d(TAG, "Client list empty, killing p2p connection");
+                            sendMessage(WifiP2pManager.REMOVE_GROUP);
+                        } else {
+                            // Just send a notification
+                            sendP2pPeersChangedBroadcast();
+                        }
+                    } else {
+                        if (DBG) Slog.d(TAG, "Failed to remove client " + address);
+                        for (WifiP2pDevice c : mGroup.getClientList()) {
+                            if (DBG) Slog.d(TAG,"client " + c.deviceAddress);
+                        }
+                    }
+                    if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
+                    break;
+                // Disconnect & remove group have same effect when connected
+                case WifiP2pManager.CANCEL_CONNECT:
+                case WifiP2pManager.REMOVE_GROUP:
+                    if (DBG) Slog.e(TAG, getName() + " remove group");
+                    WifiNative.p2pFlush();
+                    WifiNative.p2pGroupRemove(mGroup.getInterface());
+                    break;
+                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
+                    if (DBG) Slog.e(TAG, getName() + " group removed");
+                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
+                    boolean changed = false;
+                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
+                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
+                            d.status = Status.AVAILABLE;
+                            changed = true;
+                        }
+                    }
+                    mGroup = null;
+                    if (changed) sendP2pPeersChangedBroadcast();
+                    transitionTo(mInactiveState);
+                    break;
+                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
+                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
+                    if (device.equals(mGroup.getOwner())) {
+                        Slog.d(TAG, "Lost the group owner, killing p2p connection");
+                        sendMessage(WifiP2pManager.REMOVE_GROUP);
+                    } else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
+                        Slog.d(TAG, "Client list empty, killing p2p connection");
+                        sendMessage(WifiP2pManager.REMOVE_GROUP);
+                    }
+                    return NOT_HANDLED; // Do the regular device lost handling
+                case WifiP2pManager.DISABLE_P2P:
+                    sendMessage(WifiP2pManager.REMOVE_GROUP);
+                    deferMessage(message);
+                    break;
+                case WifiP2pManager.DISCOVER_PEERS:
+                    int timeout = message.arg1;
+                    WifiNative.p2pFind(timeout);
+                    break;
+                case WifiP2pManager.CONNECT:
+                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
+                    Slog.d(TAG, "Inviting device : " + config.deviceAddress);
+                    WifiNative.p2pInvite(mGroup, config.deviceAddress);
+                    updateDeviceStatus(config.deviceAddress, Status.INVITED);
+                    sendP2pPeersChangedBroadcast();
+                    // TODO: figure out updating the status to declined when invitation is rejected
+                    break;
+                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
+                    Slog.d(TAG,"===> INVITATION RESULT EVENT : " + message.obj);
+                    break;
+                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
+                    notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj);
+                    break;
+                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
+                    notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
+                    break;
+                case WifiP2pManager.WPS_PBC:
+                    WifiNative.p2pWpsPbc();
+                    break;
+                case WifiP2pManager.WPS_PIN:
+                    WifiNative.p2pWpsPin((String) message.obj);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    private void sendP2pStateChangedBroadcast(boolean enabled) {
+        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        if (enabled) {
+            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
+                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
+        } else {
+            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
+                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
+        }
+        mContext.sendStickyBroadcast(intent);
+    }
+
+    private void sendP2pPeersChangedBroadcast() {
+        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mContext.sendBroadcast(intent);
+    }
+
+    private void notifyP2pEnableFailure() {
+        Resources r = Resources.getSystem();
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
+            .setPositiveButton(r.getString(R.string.ok), null)
+            .create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void notifyWpsPin(String pin, String peerAddress) {
+        Resources r = Resources.getSystem();
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setMessage(r.getString(R.string.wifi_p2p_pin_display_message, pin, peerAddress))
+            .setPositiveButton(r.getString(R.string.ok), null)
+            .create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void notifyP2pGoNegotationRequest(WifiP2pConfig config) {
+        Resources r = Resources.getSystem();
+        WpsConfiguration wpsConfig = config.wpsConfig;
+        final View textEntryView = LayoutInflater.from(mContext)
+                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
+        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
+
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setView(textEntryView)
+            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                                if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
+                                mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD;
+                                mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString();
+                                sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
+                                mSavedGoNegotiationConfig = null;
+                        }
+                    })
+            .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                                if (DBG) Slog.d(TAG, getName() + " reject");
+                                sendMessage(WifiP2pManager.REJECT,
+                                        mSavedGoNegotiationConfig.deviceAddress);
+                                mSavedGoNegotiationConfig = null;
+                        }
+                    })
+            .create();
+
+        if (wpsConfig.setup == Setup.PBC) {
+            pin.setVisibility(View.GONE);
+            dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
+                        config.deviceAddress));
+        } else {
+            dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
+                        config.deviceAddress));
+        }
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void notifyP2pProvDiscPbcRequest(WifiP2pDevice peer) {
+        Resources r = Resources.getSystem();
+        final View textEntryView = LayoutInflater.from(mContext)
+                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
+        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
+
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setView(textEntryView)
+            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                                if (DBG) Slog.d(TAG, getName() + " wps_pbc");
+                                sendMessage(WifiP2pManager.WPS_PBC);
+                        }
+                    })
+            .setNegativeButton(r.getString(R.string.cancel), null)
+            .create();
+
+        pin.setVisibility(View.GONE);
+        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
+                        peer.deviceAddress));
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void notifyP2pProvDiscPinRequest(WifiP2pDevice peer) {
+        Resources r = Resources.getSystem();
+        final View textEntryView = LayoutInflater.from(mContext)
+                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
+        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
+
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setView(textEntryView)
+            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        if (DBG) Slog.d(TAG, getName() + " wps_pin");
+                        sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString());
+                    }
+                    })
+            .setNegativeButton(r.getString(R.string.cancel), null)
+            .create();
+
+        dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
+                        peer.deviceAddress));
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void notifyP2pInvitationReceived(WifiP2pGroup group) {
+        mSavedP2pGroup = group;
+        Resources r = Resources.getSystem();
+        final View textEntryView = LayoutInflater.from(mContext)
+                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
+        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
+
+        AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
+            .setView(textEntryView)
+            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                                WifiP2pConfig config = new WifiP2pConfig();
+                                config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress;
+                                config.joinExistingGroup = true;
+                                if (DBG) Slog.d(TAG, getName() + " connect to invited group");
+                                sendMessage(WifiP2pManager.CONNECT, config);
+                                mSavedP2pGroup = null;
+                        }
+                    })
+            .setNegativeButton(r.getString(R.string.cancel), null)
+            .create();
+
+        pin.setVisibility(View.GONE);
+        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
+                        group.getOwner().deviceAddress));
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void updateDeviceStatus(String deviceAddress, Status status) {
+        for (WifiP2pDevice d : mPeers.getDeviceList()) {
+           // TODO: fix later
+           // if (d.deviceAddress.equals(deviceAddress)) {
+            if (d.deviceAddress.startsWith(deviceAddress.substring(0, 8))) {
+                d.status = status;
+            }
+        }
+    }
+    }
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
new file mode 100644
index 0000000..7bab5d3
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pStatus;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
new file mode 100644
index 0000000..1c9b76c
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * A class representing Wi-fi P2p status
+ * @hide
+ */
+public class WifiP2pStatus implements Parcelable {
+
+    //Comes from the wpa_supplicant
+    enum p2p_status_code {
+        SUCCESS,
+        FAIL_INFO_CURRENTLY_UNAVAILABLE,
+        FAIL_INCOMPATIBLE_PARAMS,
+        FAIL_LIMIT_REACHED,
+        FAIL_INVALID_PARAMS,
+        FAIL_UNABLE_TO_ACCOMMODATE,
+        FAIL_PREV_PROTOCOL_ERROR,
+        FAIL_NO_COMMON_CHANNELS,
+        FAIL_UNKNOWN_GROUP,
+        FAIL_BOTH_GO_INTENT_15,
+        FAIL_INCOMPATIBLE_PROV_METHOD,
+        FAIL_REJECTED_BY_USER
+    };
+
+    public WifiP2pStatus() {
+    }
+
+    //TODO: add support
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    //TODO: implement
+    public WifiP2pStatus(WifiP2pStatus source) {
+        if (source != null) {
+       }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    // STOPSHIP: implement
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pStatus> CREATOR =
+        new Creator<WifiP2pStatus>() {
+            public WifiP2pStatus createFromParcel(Parcel in) {
+                WifiP2pStatus status = new WifiP2pStatus();
+                return status;
+            }
+
+            public WifiP2pStatus[] newArray(int size) {
+                return new WifiP2pStatus[size];
+            }
+        };
+}