Merge "Quick settings icons updated to match ics style on tablet" into ics-mr1
diff --git a/Android.mk b/Android.mk
index a748b7b..80e681c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -329,20 +329,36 @@
 	../../external/apache-http/src/org/apache/http
 
 # These are relative to frameworks/base
-dirs_to_document := \
-	$(fwbase_dirs_to_document) \
+dirs_to_check_apis := \
+  $(fwbase_dirs_to_document) \
 	$(non_base_dirs)
 
+# These are relative to frameworks/base
+# FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
+dirs_to_document := \
+	$(dirs_to_check_apis) \
+  $(addprefix ../../, $(FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS))
+
+# These are relative to frameworks/base
 html_dirs := \
 	$(FRAMEWORKS_BASE_SUBDIRS) \
 	$(non_base_dirs)
 
+# Common sources for doc check and api check
+common_src_files := \
+	$(call find-other-html-files, $(html_dirs)) \
+	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore)) \
+	$(addprefix ../../system/media/mca/, $(call libfilterfw_to_document, $(LOCAL_PATH)/../../system/media/mca)) \
+
 # These are relative to frameworks/base
 framework_docs_LOCAL_SRC_FILES := \
 	$(call find-other-java-files, $(dirs_to_document)) \
-	$(call find-other-html-files, $(html_dirs)) \
-	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore)) \
-	$(addprefix ../../system/media/mca/, $(call libfilterfw_to_document, $(LOCAL_PATH)/../../system/media/mca))
+	$(common_src_files)
+
+# These are relative to frameworks/base
+framework_docs_LOCAL_API_CHECK_SRC_FILES := \
+	$(call find-other-java-files, $(dirs_to_check_apis)) \
+	$(common_src_files)
 
 # This is used by ide.mk as the list of source files that are
 # always included.
@@ -462,6 +478,8 @@
 		            resources/samples/TicTacToeLib "TicTacToeLib" \
 		-samplecode $(sample_dir)/TicTacToeMain \
 		            resources/samples/TicTacToeMain "TicTacToeMain" \
+		-samplecode $(sample_dir)/ToyVpn \
+		            resources/samples/ToyVpn "Toy VPN Client" \
 		-samplecode $(sample_dir)/USB \
 		            resources/samples/USB "USB" \
 		-samplecode $(sample_dir)/WeatherListWidget \
@@ -495,7 +513,7 @@
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
diff --git a/api/current.txt b/api/current.txt
index cc50ff9..ddf5baf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5334,6 +5334,7 @@
     method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
     method public T getParcelableExtra(java.lang.String);
     method public java.lang.String getScheme();
+    method public android.content.Intent getSelector();
     method public java.io.Serializable getSerializableExtra(java.lang.String);
     method public short[] getShortArrayExtra(java.lang.String);
     method public short getShortExtra(java.lang.String, short);
@@ -5346,6 +5347,7 @@
     method public boolean hasExtra(java.lang.String);
     method public boolean hasFileDescriptors();
     method public static android.content.Intent makeMainActivity(android.content.ComponentName);
+    method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
     method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
     method public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException;
@@ -5399,6 +5401,7 @@
     method public void setExtrasClassLoader(java.lang.ClassLoader);
     method public android.content.Intent setFlags(int);
     method public android.content.Intent setPackage(java.lang.String);
+    method public void setSelector(android.content.Intent);
     method public void setSourceBounds(android.graphics.Rect);
     method public android.content.Intent setType(java.lang.String);
     method public deprecated java.lang.String toURI();
@@ -5502,7 +5505,16 @@
     field public static final java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
     field public static final java.lang.String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
     field public static final java.lang.String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
+    field public static final java.lang.String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
+    field public static final java.lang.String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
+    field public static final java.lang.String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
+    field public static final java.lang.String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
+    field public static final java.lang.String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+    field public static final java.lang.String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
+    field public static final java.lang.String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
     field public static final java.lang.String CATEGORY_APP_MARKET = "android.intent.category.APP_MARKET";
+    field public static final java.lang.String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
+    field public static final java.lang.String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
     field public static final java.lang.String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";
     field public static final java.lang.String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
     field public static final java.lang.String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
@@ -5568,6 +5580,7 @@
     field public static final int FILL_IN_COMPONENT = 8; // 0x8
     field public static final int FILL_IN_DATA = 2; // 0x2
     field public static final int FILL_IN_PACKAGE = 16; // 0x10
+    field public static final int FILL_IN_SELECTOR = 64; // 0x40
     field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20
     field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000
     field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
@@ -13633,16 +13646,19 @@
     field public static final int GL_RENDERBUFFER_RED_SIZE_OES = 36176; // 0x8d50
     field public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES = 36181; // 0x8d55
     field public static final int GL_RENDERBUFFER_WIDTH_OES = 36162; // 0x8d42
+    field public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES = 36200; // 0x8d68
     field public static final int GL_RGB565_OES = 36194; // 0x8d62
     field public static final int GL_RGB5_A1_OES = 32855; // 0x8057
     field public static final int GL_RGB8_OES = 32849; // 0x8051
     field public static final int GL_RGBA4_OES = 32854; // 0x8056
     field public static final int GL_RGBA8_OES = 32856; // 0x8058
+    field public static final int GL_SAMPLER_EXTERNAL_OES = 36198; // 0x8d66
     field public static final int GL_STENCIL_ATTACHMENT_OES = 36128; // 0x8d20
     field public static final int GL_STENCIL_INDEX1_OES = 36166; // 0x8d46
     field public static final int GL_STENCIL_INDEX4_OES = 36167; // 0x8d47
     field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48
     field public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES = 34068; // 0x8514
+    field public static final int GL_TEXTURE_BINDING_EXTERNAL_OES = 36199; // 0x8d67
     field public static final int GL_TEXTURE_CROP_RECT_OES = 35741; // 0x8b9d
     field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES = 34070; // 0x8516
     field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES = 34072; // 0x8518
@@ -13651,6 +13667,7 @@
     field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES = 34069; // 0x8515
     field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES = 34071; // 0x8517
     field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES = 34073; // 0x8519
+    field public static final int GL_TEXTURE_EXTERNAL_OES = 36197; // 0x8d65
     field public static final int GL_TEXTURE_GEN_MODE_OES = 9472; // 0x2500
     field public static final int GL_TEXTURE_GEN_STR_OES = 36192; // 0x8d60
     field public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 35215; // 0x898f
@@ -14239,13 +14256,6 @@
     method public static void texSubImage2D(int, int, int, int, android.graphics.Bitmap, int, int);
   }
 
-  public abstract class ManagedEGLContext {
-    ctor public ManagedEGLContext(javax.microedition.khronos.egl.EGLContext);
-    method public javax.microedition.khronos.egl.EGLContext getContext();
-    method public abstract void onTerminate(javax.microedition.khronos.egl.EGLContext);
-    method public void terminate();
-  }
-
   public class Matrix {
     ctor public Matrix();
     method public static void frustumM(float[], int, float, float, float, float, float, float);
@@ -14781,6 +14791,7 @@
     field public static final int FLAG_ONEWAY = 1; // 0x1
     field public static final int INTERFACE_TRANSACTION = 1598968902; // 0x5f4e5446
     field public static final int LAST_CALL_TRANSACTION = 16777215; // 0xffffff
+    field public static final int LIKE_TRANSACTION = 1598835019; // 0x5f4c494b
     field public static final int PING_TRANSACTION = 1599098439; // 0x5f504e47
     field public static final int TWEET_TRANSACTION = 1599362900; // 0x5f545754
   }
@@ -17059,7 +17070,7 @@
     field public static final java.lang.String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
     field public static final java.lang.String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH = "android.media.action.MEDIA_PLAY_FROM_SEARCH";
     field public static final java.lang.String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
-    field public static final java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
+    field public static final deprecated java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
     field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
     field public static final java.lang.String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
     field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
@@ -17422,6 +17433,7 @@
     method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
     method public static final void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
+    field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
     field public static final java.lang.String ADB_ENABLED = "adb_enabled";
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
@@ -18428,14 +18440,14 @@
     ctor public RSSurfaceView(android.content.Context);
     ctor public RSSurfaceView(android.content.Context, android.util.AttributeSet);
     method public android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
-    method public synchronized void destroyRenderScriptGL();
+    method public void destroyRenderScriptGL();
     method public android.renderscript.RenderScriptGL getRenderScriptGL();
     method public void pause();
     method public void resume();
     method public void setRenderScriptGL(android.renderscript.RenderScriptGL);
-    method public synchronized void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
     method public void surfaceCreated(android.view.SurfaceHolder);
-    method public synchronized void surfaceDestroyed(android.view.SurfaceHolder);
+    method public void surfaceDestroyed(android.view.SurfaceHolder);
   }
 
   public class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
@@ -22218,6 +22230,8 @@
     field public static final int KEYCODE_BUTTON_Y = 100; // 0x64
     field public static final int KEYCODE_BUTTON_Z = 101; // 0x65
     field public static final int KEYCODE_C = 31; // 0x1f
+    field public static final int KEYCODE_CALCULATOR = 210; // 0xd2
+    field public static final int KEYCODE_CALENDAR = 208; // 0xd0
     field public static final int KEYCODE_CALL = 5; // 0x5
     field public static final int KEYCODE_CAMERA = 27; // 0x1b
     field public static final int KEYCODE_CAPS_LOCK = 115; // 0x73
@@ -22226,6 +22240,7 @@
     field public static final int KEYCODE_CHANNEL_UP = 166; // 0xa6
     field public static final int KEYCODE_CLEAR = 28; // 0x1c
     field public static final int KEYCODE_COMMA = 55; // 0x37
+    field public static final int KEYCODE_CONTACTS = 207; // 0xcf
     field public static final int KEYCODE_CTRL_LEFT = 113; // 0x71
     field public static final int KEYCODE_CTRL_RIGHT = 114; // 0x72
     field public static final int KEYCODE_D = 32; // 0x20
@@ -22293,6 +22308,7 @@
     field public static final int KEYCODE_MINUS = 69; // 0x45
     field public static final int KEYCODE_MOVE_END = 123; // 0x7b
     field public static final int KEYCODE_MOVE_HOME = 122; // 0x7a
+    field public static final int KEYCODE_MUSIC = 209; // 0xd1
     field public static final int KEYCODE_MUTE = 91; // 0x5b
     field public static final int KEYCODE_N = 42; // 0x2a
     field public static final int KEYCODE_NOTIFICATION = 83; // 0x53
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 140222e..fddb429 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -131,6 +131,10 @@
             runScreenCompat();
         } else if (op.equals("display-size")) {
             runDisplaySize();
+        } else if (op.equals("to-uri")) {
+            runToUri(false);
+        } else if (op.equals("to-intent-uri")) {
+            runToUri(true);
         } else {
             throw new IllegalArgumentException("Unknown command: " + op);
         }
@@ -138,6 +142,7 @@
 
     private Intent makeIntent() throws URISyntaxException {
         Intent intent = new Intent();
+        Intent baseIntent = intent;
         boolean hasIntentInfo = false;
 
         mDebugOption = false;
@@ -152,35 +157,39 @@
         while ((opt=nextOption()) != null) {
             if (opt.equals("-a")) {
                 intent.setAction(nextArgRequired());
-                hasIntentInfo = true;
+                if (intent == baseIntent) {
+                    hasIntentInfo = true;
+                }
             } else if (opt.equals("-d")) {
                 data = Uri.parse(nextArgRequired());
-                hasIntentInfo = true;
+                if (intent == baseIntent) {
+                    hasIntentInfo = true;
+                }
             } else if (opt.equals("-t")) {
                 type = nextArgRequired();
-                hasIntentInfo = true;
+                if (intent == baseIntent) {
+                    hasIntentInfo = true;
+                }
             } else if (opt.equals("-c")) {
                 intent.addCategory(nextArgRequired());
-                hasIntentInfo = true;
+                if (intent == baseIntent) {
+                    hasIntentInfo = true;
+                }
             } else if (opt.equals("-e") || opt.equals("--es")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, value);
-                hasIntentInfo = true;
             } else if (opt.equals("--esn")) {
                 String key = nextArgRequired();
                 intent.putExtra(key, (String) null);
-                hasIntentInfo = true;
             } else if (opt.equals("--ei")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Integer.valueOf(value));
-                hasIntentInfo = true;
             } else if (opt.equals("--eu")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Uri.parse(value));
-                hasIntentInfo = true;
             } else if (opt.equals("--eia")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -190,12 +199,10 @@
                     list[i] = Integer.valueOf(strings[i]);
                 }
                 intent.putExtra(key, list);
-                hasIntentInfo = true;
             } else if (opt.equals("--el")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Long.valueOf(value));
-                hasIntentInfo = true;
             } else if (opt.equals("--ela")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -205,18 +212,18 @@
                     list[i] = Long.valueOf(strings[i]);
                 }
                 intent.putExtra(key, list);
-                hasIntentInfo = true;
             } else if (opt.equals("--ez")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Boolean.valueOf(value));
-                hasIntentInfo = true;
             } else if (opt.equals("-n")) {
                 String str = nextArgRequired();
                 ComponentName cn = ComponentName.unflattenFromString(str);
                 if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
                 intent.setComponent(cn);
-                hasIntentInfo = true;
+                if (intent == baseIntent) {
+                    hasIntentInfo = true;
+                }
             } else if (opt.equals("-f")) {
                 String str = nextArgRequired();
                 intent.setFlags(Integer.decode(str).intValue());
@@ -264,6 +271,9 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             } else if (opt.equals("--receiver-replace-pending")) {
                 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            } else if (opt.equals("--selector")) {
+                intent.setDataAndType(data, type);
+                intent = new Intent();
             } else if (opt.equals("-D")) {
                 mDebugOption = true;
             } else if (opt.equals("-W")) {
@@ -286,25 +296,42 @@
         }
         intent.setDataAndType(data, type);
 
+        final boolean hasSelector = intent != baseIntent;
+        if (hasSelector) {
+            // A selector was specified; fix up.
+            baseIntent.setSelector(intent);
+            intent = baseIntent;
+        }
+
         String arg = nextArg();
-        if (arg != null) {
-            Intent baseIntent;
-            if (arg.indexOf(':') >= 0) {
-                // The argument is a URI.  Fully parse it, and use that result
-                // to fill in any data not specified so far.
-                baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
-            } else if (arg.indexOf('/') >= 0) {
-                // The argument is a component name.  Build an Intent to launch
-                // it.
+        baseIntent = null;
+        if (arg == null) {
+            if (hasSelector) {
+                // If a selector has been specified, and no arguments
+                // have been supplied for the main Intent, then we can
+                // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
+                // need to have a component name specified yet, the
+                // selector will take care of that.
                 baseIntent = new Intent(Intent.ACTION_MAIN);
                 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-                baseIntent.setComponent(ComponentName.unflattenFromString(arg));
-            } else {
-                // Assume the argument is a package name.
-                baseIntent = new Intent(Intent.ACTION_MAIN);
-                baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-                baseIntent.setPackage(arg);
             }
+        } else if (arg.indexOf(':') >= 0) {
+            // The argument is a URI.  Fully parse it, and use that result
+            // to fill in any data not specified so far.
+            baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
+        } else if (arg.indexOf('/') >= 0) {
+            // The argument is a component name.  Build an Intent to launch
+            // it.
+            baseIntent = new Intent(Intent.ACTION_MAIN);
+            baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+            baseIntent.setComponent(ComponentName.unflattenFromString(arg));
+        } else {
+            // Assume the argument is a package name.
+            baseIntent = new Intent(Intent.ACTION_MAIN);
+            baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+            baseIntent.setPackage(arg);
+        }
+        if (baseIntent != null) {
             Bundle extras = intent.getExtras();
             intent.replaceExtras((Bundle)null);
             Bundle uriExtras = baseIntent.getExtras();
@@ -315,7 +342,7 @@
                     baseIntent.removeCategory(c);
                 }
             }
-            intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT);
+            intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
             if (extras == null) {
                 extras = uriExtras;
             } else if (uriExtras != null) {
@@ -1064,6 +1091,11 @@
         }
     }
 
+    private void runToUri(boolean intentScheme) throws Exception {
+        Intent intent = makeIntent();
+        System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0));
+    }
+
     private class IntentReceiver extends IIntentReceiver.Stub {
         private boolean mFinished = false;
 
@@ -1233,6 +1265,8 @@
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
                 "       am display-size [reset|MxN]\n" +
+                "       am to-uri [INTENT]\n" +
+                "       am to-intent-uri [INTENT]\n" +
                 "\n" +
                 "am start: start an Activity.  Options are:\n" +
                 "    -D: enable debugging\n" +
@@ -1284,6 +1318,10 @@
                 "\n" +
                 "am display-size: override display size.\n" +
                 "\n" +
+                "am to-uri: print the given Intent specification as a URI.\n" +
+                "\n" +
+                "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
+                "\n" +
                 "<INTENT> specifications include these flags and arguments:\n" +
                 "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
                 "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
@@ -1308,6 +1346,7 @@
                 "    [--activity-single-top] [--activity-clear-task]\n" +
                 "    [--activity-task-on-home]\n" +
                 "    [--receiver-registered-only] [--receiver-replace-pending]\n" +
+                "    [--selector]\n" +
                 "    [<URI> | <PACKAGE> | <COMPONENT>]\n"
                 );
     }
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index fe81d2b..395c28b 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -120,6 +120,12 @@
 
     dump_file("NETWORK ROUTES", "/proc/net/route");
     dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
+    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
+    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
+    run_command("ROUTE TABLE 60", 10, "ip", "route", "show", "table", "60", NULL);
+    run_command("ROUTE TABLE 61 v6", 10, "ip", "-6", "route", "show", "table", "60", NULL);
+    run_command("ROUTE TABLE 61", 10, "ip", "route", "show", "table", "61", NULL);
+    run_command("ROUTE TABLE 61 v6", 10, "ip", "-6", "route", "show", "table", "61", NULL);
     dump_file("ARP CACHE", "/proc/net/arp");
     run_command("IPTABLES", 10, "su", "root", "iptables", "-L", "-nvx", NULL);
     run_command("IP6TABLES", 10, "su", "root", "ip6tables", "-L", "-nvx", NULL);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 26b9113..4ede33f 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -184,6 +184,7 @@
     DIR *d;
     struct dirent *de;
     int64_t avail;
+    char datadir[PKG_PATH_MAX];
 
     avail = disk_free();
     if (avail < 0) return -1;
@@ -191,9 +192,14 @@
     LOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
     if (avail >= free_size) return 0;
 
-    d = opendir(android_data_dir.path);
+    if (create_persona_path(datadir, 0)) {
+        LOGE("couldn't get directory for persona 0");
+        return -1;
+    }
+
+    d = opendir(datadir);
     if (d == NULL) {
-        LOGE("cannot open %s: %s\n", android_data_dir.path, strerror(errno));
+        LOGE("cannot open %s: %s\n", datadir, strerror(errno));
         return -1;
     }
     dfd = dirfd(d);
@@ -578,19 +584,6 @@
     return -1;
 }
 
-int create_move_path(char path[PKG_PATH_MAX],
-    const char* pkgname,
-    const char* leaf,
-    uid_t persona)
-{
-    if ((android_data_dir.len + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) {
-        return -1;
-    }
-    
-    sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
-    return 0;
-}
-
 void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
         struct stat* statbuf)
 {
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index c5872b8..173cabf 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -105,6 +105,11 @@
 int create_persona_path(char path[PKG_PATH_MAX],
                     uid_t persona);
 
+int create_move_path(char path[PKG_PATH_MAX],
+                     const char* pkgname,
+                     const char* leaf,
+                     uid_t persona);
+
 int is_valid_package_name(const char* pkgname);
 
 int create_cache_path(char path[PKG_PATH_MAX], const char *src);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 1128fce..7cb9b37 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -34,6 +34,16 @@
 #define TEST_SYSTEM_DIR1 "/system/app/"
 #define TEST_SYSTEM_DIR2 "/vendor/app/"
 
+#define REALLY_LONG_APP_NAME "com.example." \
+        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
+        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
+        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
+
 namespace android {
 
 class UtilsTest : public testing::Test {
@@ -210,7 +220,7 @@
 
 TEST_F(UtilsTest, GetPathFromString_NullPathFail) {
     dir_rec_t test1;
-    EXPECT_EQ(-1, get_path_from_string(&test1, NULL))
+    EXPECT_EQ(-1, get_path_from_string(&test1, (const char *) NULL))
             << "Should not allow NULL as a path.";
 }
 
@@ -327,6 +337,50 @@
             << "Package path should be in /data/app-private/";
 }
 
+TEST_F(UtilsTest, CreatePersonaPath_Primary) {
+    char path[PKG_PATH_MAX];
+
+    EXPECT_EQ(0, create_persona_path(path, 0))
+            << "Should successfully build primary user path.";
+
+    EXPECT_STREQ("/data/data/", path)
+            << "Primary user should have correct path";
+}
+
+TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
+    char path[PKG_PATH_MAX];
+
+    EXPECT_EQ(0, create_persona_path(path, 1))
+            << "Should successfully build primary user path.";
+
+    EXPECT_STREQ("/data/user/1/", path)
+            << "Primary user should have correct path";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Primary) {
+    char path[PKG_PATH_MAX];
+
+    EXPECT_EQ(0, create_move_path(path, "com.android.test", "shared_prefs", 0))
+            << "Should be able to create move path for primary user";
+
+    EXPECT_STREQ("/data/data/com.android.test/shared_prefs", path)
+            << "Primary user package directory should be created correctly";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
+    char path[PKG_PATH_MAX];
+
+    EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
+            << "Should fail to create move path for primary user";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
+    char path[PKG_PATH_MAX];
+
+    EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
+            << "Should fail to create move path for primary user";
+}
+
 TEST_F(UtilsTest, CopyAndAppend_Normal) {
     //int copy_and_append(dir_rec_t* dst, dir_rec_t* src, char* suffix)
     dir_rec_t dst;
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 3099b83..a53a93c 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -109,7 +109,7 @@
         uid_len = 0;
     } else {
         persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d", persona);
+        uid_len = snprintf(NULL, 0, "%d/", persona);
     }
 
     char *dst = path;
@@ -126,7 +126,7 @@
             LOGE("Error building user path");
             return -1;
         }
-        int ret = snprintf(dst, dst_size, "%d", persona);
+        int ret = snprintf(dst, dst_size, "%d/", persona);
         if (ret < 0 || (size_t) ret != uid_len) {
             LOGE("Error appending persona id to path");
             return -1;
@@ -135,6 +135,20 @@
     return 0;
 }
 
+int create_move_path(char path[PKG_PATH_MAX],
+    const char* pkgname,
+    const char* leaf,
+    uid_t persona)
+{
+    if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
+            >= PKG_PATH_MAX) {
+        return -1;
+    }
+
+    sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
+    return 0;
+}
+
 /**
  * Checks whether the package name is valid. Returns -1 on error and
  * 0 on success.
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 64a2755..211be52 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,8 +16,6 @@
 
 package android.accessibilityservice;
 
-import com.android.internal.os.HandlerCaller;
-
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -25,8 +23,11 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.os.HandlerCaller;
+
 /**
  * An accessibility service runs in the background and receives callbacks by the system
  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
@@ -219,7 +220,7 @@
 
     private AccessibilityServiceInfo mInfo;
 
-    IAccessibilityServiceConnection mConnection;
+    private int mConnectionId;
 
     /**
      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
@@ -264,9 +265,11 @@
      * AccessibilityManagerService.
      */
     private void sendServiceInfo() {
-        if (mInfo != null && mConnection != null) {
+        IAccessibilityServiceConnection connection =
+            AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+        if (mInfo != null && connection != null) {
             try {
-                mConnection.setServiceInfo(mInfo);
+                connection.setServiceInfo(mInfo);
             } catch (RemoteException re) {
                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
             }
@@ -302,8 +305,9 @@
             mCaller = new HandlerCaller(context, this);
         }
 
-        public void setConnection(IAccessibilityServiceConnection connection) {
-            Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection);
+        public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
+            Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
+                    connection);
             mCaller.sendMessage(message);
         }
 
@@ -330,8 +334,19 @@
                     mTarget.onInterrupt();
                     return;
                 case DO_SET_SET_CONNECTION :
-                    mConnection = ((IAccessibilityServiceConnection) message.obj);
-                    mTarget.onServiceConnected();
+                    final int connectionId = message.arg1;
+                    IAccessibilityServiceConnection connection =
+                        (IAccessibilityServiceConnection) message.obj;
+                    if (connection != null) {
+                        AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+                                connection);
+                        mConnectionId = connectionId;
+                        mTarget.onServiceConnected();
+                    } else {
+                        AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+                        mConnectionId = AccessibilityInteractionClient.NO_ID;
+                        // TODO: Do we need a onServiceDisconnected callback?
+                    }
                     return;
                 default :
                     Log.w(LOG_TAG, "Unknown message type " + message.what);
diff --git a/core/java/android/accessibilityservice/IEventListener.aidl b/core/java/android/accessibilityservice/IEventListener.aidl
index 5b849f1..5536b3c 100644
--- a/core/java/android/accessibilityservice/IEventListener.aidl
+++ b/core/java/android/accessibilityservice/IEventListener.aidl
@@ -26,7 +26,7 @@
  */
  oneway interface IEventListener {
 
-    void setConnection(in IAccessibilityServiceConnection connection);
+    void setConnection(in IAccessibilityServiceConnection connection, int connectionId);
 
     void onAccessibilityEvent(in AccessibilityEvent event);
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 303f81b..0c761fc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -175,11 +175,11 @@
     // These can be accessed by multiple threads; mPackages is the lock.
     // XXX For now we keep around information about all packages we have
     // seen, not removing entries from this map.
-    // NOTE: The activity manager in its process needs to call in to
+    // NOTE: The activity and window managers need to call in to
     // ActivityThread to do things like update resource configurations,
-    // which means this lock gets held while the activity manager holds its
-    // own lock.  Thus you MUST NEVER call back into the activity manager
-    // or anything that depends on it while holding this lock.
+    // which means this lock gets held while the activity and window managers
+    // holds their own lock.  Thus you MUST NEVER call back into the activity manager
+    // or window manager or anything that depends on them while holding this lock.
     final HashMap<String, WeakReference<LoadedApk>> mPackages
             = new HashMap<String, WeakReference<LoadedApk>>();
     final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 8ed7481..180a442 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -625,7 +625,7 @@
             return info.activityInfo.loadIcon(this);
         }
 
-        throw new NameNotFoundException(intent.toURI());
+        throw new NameNotFoundException(intent.toUri(0));
     }
 
     @Override public Drawable getDefaultActivityIcon() {
@@ -728,15 +728,22 @@
 
     private Drawable getCachedIcon(ResourceName name) {
         synchronized (sSync) {
-            WeakReference<Drawable> wr = sIconCache.get(name);
+            WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
             if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
                                    + name + ": " + wr);
             if (wr != null) {   // we have the activity
-                Drawable dr = wr.get();
-                if (dr != null) {
-                    if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
-                                           + name + ": " + dr);
-                    return dr;
+                Drawable.ConstantState state = wr.get();
+                if (state != null) {
+                    if (DEBUG_ICONS) {
+                        Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
+                    }
+                    // Note: It's okay here to not use the newDrawable(Resources) variant
+                    //       of the API. The ConstantState comes from a drawable that was
+                    //       originally created by passing the proper app Resources instance
+                    //       which means the state should already contain the proper
+                    //       resources specific information (like density.) See
+                    //       BitmapDrawable.BitmapState for instance.
+                    return state.newDrawable();
                 }
                 // our entry has been purged
                 sIconCache.remove(name);
@@ -747,14 +754,12 @@
 
     private void putCachedIcon(ResourceName name, Drawable dr) {
         synchronized (sSync) {
-            sIconCache.put(name, new WeakReference<Drawable>(dr));
-            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
-                                   + name + ": " + dr);
+            sIconCache.put(name, new WeakReference<Drawable.ConstantState>(dr.getConstantState()));
+            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr);
         }
     }
 
-    static final void handlePackageBroadcast(int cmd, String[] pkgList,
-                                             boolean hasPkgInfo) {
+    static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) {
         boolean immediateGc = false;
         if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
             immediateGc = true;
@@ -1226,8 +1231,8 @@
     private final IPackageManager mPM;
 
     private static final Object sSync = new Object();
-    private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
-            = new HashMap<ResourceName, WeakReference<Drawable> >();
-    private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
-            = new HashMap<ResourceName, WeakReference<CharSequence> >();
+    private static HashMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache
+            = new HashMap<ResourceName, WeakReference<Drawable.ConstantState>>();
+    private static HashMap<ResourceName, WeakReference<CharSequence>> sStringCache
+            = new HashMap<ResourceName, WeakReference<CharSequence>>();
 }
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 8b70370..bf8fde0 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -91,13 +91,14 @@
 
         mCallBack = callBack;
 
-        setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
-        setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
+        Context themeContext = getContext();
+        setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+        setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel), (OnClickListener) null);
         setIcon(0);
         setTitle(R.string.date_picker_dialog_title);
 
         LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.date_picker_dialog, null);
         setView(view);
         mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index a990ee9..353b415 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -92,16 +92,16 @@
         mInitialMinute = minute;
         mIs24HourView = is24HourView;
 
-        setCanceledOnTouchOutside(false);
         setIcon(0);
         setTitle(R.string.time_picker_dialog_title);
 
-        setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
-        setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel),
+        Context themeContext = getContext();
+        setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_set), this);
+        setButton(BUTTON_NEGATIVE, themeContext.getText(R.string.cancel),
                 (OnClickListener) null);
 
         LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.time_picker_dialog, null);
         setView(view);
         mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 96f3290..7300107 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -129,6 +129,10 @@
         }
     }
 
+    /*package*/ void close() {
+        mServiceListener = null;
+    }
+
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d971652..5f5ba50 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1180,11 +1180,29 @@
      * @param proxy Profile proxy object
      */
     public void closeProfileProxy(int profile, BluetoothProfile proxy) {
-        if (profile == BluetoothProfile.HEADSET) {
-            BluetoothHeadset headset = (BluetoothHeadset)proxy;
-            if (headset != null) {
+        if (proxy == null) return;
+
+        switch (profile) {
+            case BluetoothProfile.HEADSET:
+                BluetoothHeadset headset = (BluetoothHeadset)proxy;
                 headset.close();
-            }
+                break;
+            case BluetoothProfile.A2DP:
+                BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
+                a2dp.close();
+                break;
+            case BluetoothProfile.INPUT_DEVICE:
+                BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
+                iDev.close();
+                break;
+            case BluetoothProfile.PAN:
+                BluetoothPan pan = (BluetoothPan)proxy;
+                pan.close();
+                break;
+            case BluetoothProfile.HEALTH:
+                BluetoothHealth health = (BluetoothHealth)proxy;
+                health.close();
+                break;
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index b1d0070..c9603bf 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -109,6 +109,8 @@
     private BluetoothA2dpService mA2dpService;
     private BluetoothHeadset  mHeadsetService;
     private BluetoothPbap     mPbapService;
+    private PbapServiceListener mPbap;
+    private BluetoothAdapter mAdapter;
     private boolean mPbapServiceConnected;
     private boolean mAutoConnectionPending;
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
@@ -249,11 +251,11 @@
 
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
                                 BluetoothProfile.HEADSET);
         // TODO(): Convert PBAP to the new Profile APIs.
-        PbapServiceListener p = new PbapServiceListener();
+        mPbap = new PbapServiceListener();
 
         mIncomingConnections = mService.getIncomingState(address);
         mIncomingRejectTimer = readTimerValue();
@@ -414,6 +416,26 @@
                 case TRANSITION_TO_STABLE:
                     // ignore.
                     break;
+                case SM_QUIT_CMD:
+                    mContext.unregisterReceiver(mBroadcastReceiver);
+                    mBroadcastReceiver = null;
+                    mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService);
+                    mBluetoothProfileServiceListener = null;
+                    mOutgoingHandsfree = null;
+                    mPbap = null;
+                    mPbapService.close();
+                    mPbapService = null;
+                    mIncomingHid = null;
+                    mOutgoingHid = null;
+                    mIncomingHandsfree = null;
+                    mOutgoingHandsfree = null;
+                    mIncomingA2dp = null;
+                    mOutgoingA2dp = null;
+                    mBondedDevice = null;
+                    // There is a problem in the State Machine code
+                    // where things are not cleaned up properly, when quit message
+                    // is handled so return NOT_HANDLED as a workaround.
+                    return NOT_HANDLED;
                 default:
                     return NOT_HANDLED;
             }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 8f2b3d8..2bbf008 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -245,6 +245,7 @@
             mContext.unbindService(mConnection);
             mConnection = null;
         }
+        mServiceListener = null;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 9b2b8ca..f850c02 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -452,6 +452,10 @@
         }
     }
 
+    /*package*/ void close() {
+        mServiceListener = null;
+    }
+
     private boolean isEnabled() {
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
 
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 282b70a..1a9e011 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -118,6 +118,10 @@
         }
     }
 
+    /*package*/ void close() {
+        mServiceListener = null;
+    }
+
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 7490f9e..5d9d8be 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -139,6 +139,10 @@
         }
     }
 
+    /*package*/ void close() {
+        mServiceListener = null;
+    }
+
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
@@ -299,4 +303,4 @@
     private static void log(String msg) {
       Log.d(TAG, msg);
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 4be077c..2683bef 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -69,7 +69,7 @@
 
     private IBluetoothPbap mService;
     private final Context mContext;
-    private final ServiceListener mServiceListener;
+    private ServiceListener mServiceListener;
 
     /** There was an error trying to obtain the state */
     public static final int STATE_ERROR        = -1;
@@ -138,6 +138,7 @@
             mContext.unbindService(mConnection);
             mConnection = null;
         }
+        mServiceListener = null;
     }
 
     /**
diff --git a/core/java/android/content/ContentUris.java b/core/java/android/content/ContentUris.java
index aa7603470b..dbe8a7c 100644
--- a/core/java/android/content/ContentUris.java
+++ b/core/java/android/content/ContentUris.java
@@ -19,9 +19,54 @@
 import android.net.Uri;
 
 /**
- * Utility methods useful for working with content {@link android.net.Uri}s,
- * those with a "content" scheme.
- */
+* Utility methods useful for working with {@link android.net.Uri} objects
+* that use the &quot;content&quot; (content://) scheme.
+*
+*<p>
+*   Content URIs have the syntax
+*</p>
+*<p>
+*   <code>content://<em>authority</em>/<em>path</em>/<em>id</em></code>
+*</p>
+*<dl>
+*   <dt>
+*       <code>content:</code>
+*   </dt>
+*   <dd>
+*       The scheme portion of the URI. This is always set to {@link
+*       android.content.ContentResolver#SCHEME_CONTENT ContentResolver.SCHEME_CONTENT} (value
+*       <code>content://</code>).
+*   </dd>
+*   <dt>
+*       <em>authority</em>
+*   </dt>
+*   <dd>
+*       A string that identifies the entire content provider. All the content URIs for the provider
+*       start with this string. To guarantee a unique authority, providers should consider
+*       using an authority that is the same as the provider class' package identifier.
+*   </dd>
+*   <dt>
+*       <em>path</em>
+*   </dt>
+*   <dd>
+*       Zero or more segments, separated by a forward slash (<code>/</code>), that identify
+*       some subset of the provider's data. Most providers use the path part to identify
+*       individual tables. Individual segments in the path are often called
+*       &quot;directories&quot; although they do not refer to file directories. The right-most
+*       segment in a path is often called a &quot;twig&quot;
+*   </dd>
+*   <dt>
+*       <em>id</em>
+*   </dt>
+*   <dd>
+*       A unique numeric identifier for a single row in the subset of data identified by the
+*       preceding path part. Most providers recognize content URIs that contain an id part
+*       and give them special handling. A table that contains a column named <code>_ID</code>
+*       often expects the id part to be a particular value for that column.
+*   </dd>
+*</dl>
+*
+*/
 public class ContentUris {
 
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 45a42e4..4e5598b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2310,6 +2310,120 @@
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
+    // Application launch intent categories (see addCategory()).
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the browser application.
+     * The activity should be able to browse the Internet.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the calculator application.
+     * The activity should be able to perform standard arithmetic operations.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the calendar application.
+     * The activity should be able to view and manipulate calendar entries.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the contacts application.
+     * The activity should be able to view and manipulate address book entries.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the email application.
+     * The activity should be able to send and receive email.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the gallery application.
+     * The activity should be able to view and manipulate image and video files
+     * stored on the device.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the maps application.
+     * The activity should be able to show the user's current location and surroundings.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the messaging application.
+     * The activity should be able to send and receive text messages.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
+
+    /**
+     * Used with {@link #ACTION_MAIN} to launch the music application.
+     * The activity should be able to play, browse, or manipulate music files
+     * stored on the device.
+     * <p>NOTE: This should not be used as the primary key of an Intent,
+     * since it will not result in the app launching with the correct
+     * action and category.  Instead, use this with
+     * {@link #makeMainSelectorActivity(String, String) to generate a main
+     * Intent with this category in the selector.</p>
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
+
+    // ---------------------------------------------------------------------
+    // ---------------------------------------------------------------------
     // Standard extra data keys.
 
     /**
@@ -2895,6 +3009,7 @@
     private HashSet<String> mCategories;
     private Bundle mExtras;
     private Rect mSourceBounds;
+    private Intent mSelector;
 
     // ---------------------------------------------------------------------
 
@@ -2923,6 +3038,9 @@
         if (o.mSourceBounds != null) {
             this.mSourceBounds = new Rect(o.mSourceBounds);
         }
+        if (o.mSelector != null) {
+            this.mSelector = new Intent(o.mSelector);
+        }
     }
 
     @Override
@@ -3063,6 +3181,39 @@
     }
 
     /**
+     * Make an Intent for the main activity of an application, without
+     * specifying a specific activity to run but giving a selector to find
+     * the activity.  This results in a final Intent that is structured
+     * the same as when the application is launched from
+     * Home.  For anything else that wants to launch an application in the
+     * same way, it is important that they use an Intent structured the same
+     * way, and can use this function to ensure this is the case.
+     *
+     * <p>The returned Intent has {@link #ACTION_MAIN} as its action, and includes the
+     * category {@link #CATEGORY_LAUNCHER}.  This does <em>not</em> have
+     * {@link #FLAG_ACTIVITY_NEW_TASK} set, though typically you will want
+     * to do that through {@link #addFlags(int)} on the returned Intent.
+     *
+     * @param selectorAction The action name of the Intent's selector.
+     * @param selectorCategory The name of a category to add to the Intent's
+     * selector.
+     * @return Returns a newly created Intent that can be used to launch the
+     * activity as a main application entry.
+     *
+     * @see #setSelector(Intent)
+     */
+    public static Intent makeMainSelectorActivity(String selectorAction,
+            String selectorCategory) {
+        Intent intent = new Intent(ACTION_MAIN);
+        intent.addCategory(CATEGORY_LAUNCHER);
+        Intent selector = new Intent();
+        selector.setAction(selectorAction);
+        selector.addCategory(selectorCategory);
+        intent.setSelector(selector);
+        return intent;
+    }
+
+    /**
      * Make an Intent that can be used to re-launch an application's task
      * in its base state.  This is like {@link #makeMainActivity(ComponentName)},
      * but also sets the flags {@link #FLAG_ACTIVITY_NEW_TASK} and
@@ -3137,6 +3288,7 @@
 
             // new format
             Intent intent = new Intent(ACTION_VIEW);
+            Intent baseIntent = intent;
 
             // fetch data part, if present
             String data = i >= 0 ? uri.substring(0, i) : null;
@@ -3146,8 +3298,9 @@
             // loop over contents of Intent, all name=value;
             while (!uri.startsWith("end", i)) {
                 int eq = uri.indexOf('=', i);
-                int semi = uri.indexOf(';', eq);
-                String value = Uri.decode(uri.substring(eq + 1, semi));
+                if (eq < 0) eq = i-1;
+                int semi = uri.indexOf(';', i);
+                String value = eq < semi ? Uri.decode(uri.substring(eq + 1, semi)) : "";
 
                 // action
                 if (uri.startsWith("action=", i)) {
@@ -3189,6 +3342,11 @@
                     intent.mSourceBounds = Rect.unflattenFromString(value);
                 }
 
+                // selector
+                else if (semi == (i+3) && uri.startsWith("SEL", i)) {
+                    intent = new Intent();
+                }
+
                 // extra
                 else {
                     String key = Uri.decode(uri.substring(i + 2, eq));
@@ -3212,6 +3370,12 @@
                 i = semi + 1;
             }
 
+            if (intent != baseIntent) {
+                // The Intent had a selector; fix it up.
+                baseIntent.setSelector(intent);
+                intent = baseIntent;
+            }
+
             if (data != null) {
                 if (data.startsWith("intent:")) {
                     data = data.substring(7);
@@ -3537,7 +3701,7 @@
      * Return the set of all categories in the intent.  If there are no categories,
      * returns NULL.
      *
-     * @return Set The set of categories you can examine.  Do not modify!
+     * @return The set of categories you can examine.  Do not modify!
      *
      * @see #hasCategory
      * @see #addCategory
@@ -3547,6 +3711,16 @@
     }
 
     /**
+     * Return the specific selector associated with this Intent.  If there is
+     * none, returns null.  See {@link #setSelector} for more information.
+     *
+     * @see #setSelector
+     */
+    public Intent getSelector() {
+        return mSelector;
+    }
+
+    /**
      * Sets the ClassLoader that will be used when unmarshalling
      * any Parcelable values from the extras of this Intent.
      *
@@ -4365,6 +4539,49 @@
     }
 
     /**
+     * Set a selector for this Intent.  This is a modification to the kinds of
+     * things the Intent will match.  If the selector is set, it will be used
+     * when trying to find entities that can handle the Intent, instead of the
+     * main contents of the Intent.  This allows you build an Intent containing
+     * a generic protocol while targeting it more specifically.
+     *
+     * <p>An example of where this may be used is with things like
+     * {@link #CATEGORY_APP_BROWSER}.  This category allows you to build an
+     * Intent that will launch the Browser application.  However, the correct
+     * main entry point of an application is actually {@link #ACTION_MAIN}
+     * {@link #CATEGORY_LAUNCHER} with {@link #setComponent(ComponentName)}
+     * used to specify the actual Activity to launch.  If you launch the browser
+     * with something different, undesired behavior may happen if the user has
+     * previously or later launches it the normal way, since they do not match.
+     * Instead, you can build an Intent with the MAIN action (but no ComponentName
+     * yet specified) and set a selector with {@link #ACTION_MAIN} and
+     * {@link #CATEGORY_APP_BROWSER} to point it specifically to the browser activity.
+     *
+     * <p>Setting a selector does not impact the behavior of
+     * {@link #filterEquals(Intent)} and {@link #filterHashCode()}.  This is part of the
+     * desired behavior of a selector -- it does not impact the base meaning
+     * of the Intent, just what kinds of things will be matched against it
+     * when determining who can handle it.</p>
+     *
+     * <p>You can not use both a selector and {@link #setPackage(String)} on
+     * the same base Intent.</p>
+     *
+     * @param selector The desired selector Intent; set to null to not use
+     * a special selector.
+     */
+    public void setSelector(Intent selector) {
+        if (selector == this) {
+            throw new IllegalArgumentException(
+                    "Intent being set as a selector of itself");
+        }
+        if (selector != null && mPackage != null) {
+            throw new IllegalArgumentException(
+                    "Can't set selector when package name is already set");
+        }
+        mSelector = selector;
+    }
+
+    /**
      * Add extended data to the intent.  The name must include a package
      * prefix, for example the app com.android.contacts would use names
      * like "com.android.contacts.ShowAll".
@@ -5191,6 +5408,10 @@
      * @see #resolveActivity
      */
     public Intent setPackage(String packageName) {
+        if (packageName != null && mSelector != null) {
+            throw new IllegalArgumentException(
+                    "Can't set package name when selector is already set");
+        }
         mPackage = packageName;
         return this;
     }
@@ -5326,12 +5547,18 @@
     public static final int FILL_IN_PACKAGE = 1<<4;
 
     /**
-     * Use with {@link #fillIn} to allow the current package value to be
+     * Use with {@link #fillIn} to allow the current bounds rectangle to be
      * overwritten, even if it is already set.
      */
     public static final int FILL_IN_SOURCE_BOUNDS = 1<<5;
 
     /**
+     * Use with {@link #fillIn} to allow the current selector to be
+     * overwritten, even if it is already set.
+     */
+    public static final int FILL_IN_SELECTOR = 1<<6;
+
+    /**
      * Copy the contents of <var>other</var> in to this object, but only
      * where fields are not defined by this object.  For purposes of a field
      * being defined, the following pieces of data in the Intent are
@@ -5351,11 +5578,13 @@
      *
      * <p>In addition, you can use the {@link #FILL_IN_ACTION},
      * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
-     * and {@link #FILL_IN_COMPONENT} to override the restriction where the
+     * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and
+     * {@link #FILL_IN_SELECTOR} to override the restriction where the
      * corresponding field will not be replaced if it is already set.
      *
      * <p>Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} is explicitly
-     * specified.
+     * specified.  The selector will only be copied if {@link #FILL_IN_SELECTOR} is
+     * explicitly specified.
      *
      * <p>For example, consider Intent A with {data="foo", categories="bar"}
      * and Intent B with {action="gotit", data-type="some/thing",
@@ -5371,7 +5600,8 @@
      *
      * @return Returns a bit mask of {@link #FILL_IN_ACTION},
      * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
-     * and {@link #FILL_IN_COMPONENT} indicating which fields were changed.
+     * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and
+     * {@link #FILL_IN_SELECTOR} indicating which fields were changed.
      */
     public int fillIn(Intent other, int flags) {
         int changes = 0;
@@ -5396,8 +5626,20 @@
         }
         if (other.mPackage != null
                 && (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) {
-            mPackage = other.mPackage;
-            changes |= FILL_IN_PACKAGE;
+            // Only do this if mSelector is not set.
+            if (mSelector == null) {
+                mPackage = other.mPackage;
+                changes |= FILL_IN_PACKAGE;
+            }
+        }
+        // Selector is special: it can only be set if explicitly allowed,
+        // for the same reason as the component name.
+        if (other.mSelector != null && (flags&FILL_IN_SELECTOR) != 0) {
+            if (mPackage == null) {
+                mSelector = new Intent(other.mSelector);
+                mPackage = null;
+                changes |= FILL_IN_SELECTOR;
+            }
         }
         // Component is special: it can -only- be set if explicitly allowed,
         // since otherwise the sender could force the intent somewhere the
@@ -5695,6 +5937,11 @@
             first = false;
             b.append("(has extras)");
         }
+        if (mSelector != null) {
+            b.append(" sel={");
+            mSelector.toShortString(b, secure, comp, extras);
+            b.append("}");
+        }
     }
 
     /**
@@ -5755,6 +6002,21 @@
 
         uri.append("#Intent;");
 
+        toUriInner(uri, scheme, flags);
+        if (mSelector != null) {
+            uri.append("SEL;");
+            // Note that for now we are not going to try to handle the
+            // data part; not clear how to represent this as a URI, and
+            // not much utility in it.
+            mSelector.toUriInner(uri, null, flags);
+        }
+
+        uri.append("end");
+
+        return uri.toString();
+    }
+
+    private void toUriInner(StringBuilder uri, String scheme, int flags) {
         if (scheme != null) {
             uri.append("scheme=").append(scheme).append(';');
         }
@@ -5809,10 +6071,6 @@
                 }
             }
         }
-
-        uri.append("end");
-
-        return uri.toString();
     }
 
     public int describeContents() {
@@ -5843,6 +6101,13 @@
             out.writeInt(0);
         }
 
+        if (mSelector != null) {
+            out.writeInt(1);
+            mSelector.writeToParcel(out, flags);
+        } else {
+            out.writeInt(0);
+        }
+
         out.writeBundle(mExtras);
     }
 
@@ -5884,6 +6149,10 @@
             mCategories = null;
         }
 
+        if (in.readInt() != 0) {
+            mSelector = new Intent(in);
+        }
+
         mExtras = in.readBundle();
     }
 
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index b2909b3..3c4e545 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -24,6 +24,7 @@
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.OnAccountsUpdateListener;
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -86,8 +87,13 @@
     private static final long MAX_TIME_PER_SYNC;
 
     static {
-        MAX_SIMULTANEOUS_INITIALIZATION_SYNCS = SystemProperties.getInt("sync.max_init_syncs", 5);
-        MAX_SIMULTANEOUS_REGULAR_SYNCS = SystemProperties.getInt("sync.max_regular_syncs", 2);
+        final boolean isLargeRAM = ActivityManager.isLargeRAM();
+        int defaultMaxInitSyncs = isLargeRAM ? 5 : 2;
+        int defaultMaxRegularSyncs = isLargeRAM ? 2 : 1;
+        MAX_SIMULTANEOUS_INITIALIZATION_SYNCS =
+                SystemProperties.getInt("sync.max_init_syncs", defaultMaxInitSyncs);
+        MAX_SIMULTANEOUS_REGULAR_SYNCS =
+                SystemProperties.getInt("sync.max_regular_syncs", defaultMaxRegularSyncs);
         LOCAL_SYNC_DELAY =
                 SystemProperties.getLong("sync.local_sync_delay", 30 * 1000 /* 30 seconds */);
         MAX_TIME_PER_SYNC =
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c2a757f..7ca6155 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -22,12 +22,9 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceHolder;
@@ -157,7 +154,6 @@
     private boolean mOneShot;
     private boolean mWithBuffer;
     private boolean mFaceDetectionRunning = false;
-    private boolean mReleased = false;
 
     /**
      * Broadcast Action:  A new picture is taken by the camera, and the entry of
@@ -322,15 +318,6 @@
     public final void release() {
         native_release();
         mFaceDetectionRunning = false;
-        if (mCameraSoundPlayers != null) {
-            for (CameraSoundPlayer csp: mCameraSoundPlayers) {
-                if (csp != null) {
-                    csp.release();
-                }
-            }
-            mCameraSoundPlayers = null;
-        }
-        mReleased = true;
     }
 
     /**
@@ -2512,13 +2499,16 @@
 
         /**
          * Sets the white balance. Changing the setting will release the
-         * auto-white balance lock.
+         * auto-white balance lock. It is recommended not to change white
+         * balance and AWB lock at the same time.
          *
          * @param value new white balance.
          * @see #getWhiteBalance()
          * @see #setAutoWhiteBalanceLock(boolean)
          */
         public void setWhiteBalance(String value) {
+            String oldValue = get(KEY_WHITE_BALANCE);
+            if (same(value, oldValue)) return;
             set(KEY_WHITE_BALANCE, value);
             set(KEY_AUTO_WHITEBALANCE_LOCK, FALSE);
         }
@@ -3493,195 +3483,11 @@
 
             return result;
         }
+
+        private boolean same(String s1, String s2) {
+            if (s1 == null && s2 == null) return true;
+            if (s1 != null && s1.equals(s2)) return true;
+            return false;
+        }
     };
-
-    /**
-     * <p>The set of default system sounds for camera actions. Use this with
-     * {@link #playSound} to play an appropriate sound when implementing a
-     * custom still or video recording mechanism through the preview
-     * callbacks.</p>
-     *
-     * <p>There is no need to play sounds when using {@link #takePicture} or
-     * {@link android.media.MediaRecorder} for still images or video,
-     * respectively, as these play their own sounds when needed.</p>
-     *
-     * @see #playSound
-     * @hide
-     */
-    public static class Sound {
-        /**
-         * The sound used by {@link android.hardware.Camera#takePicture} to
-         * indicate still image capture.
-         */
-        public static final int SHUTTER_CLICK         = 0;
-
-        /**
-         * A sound to indicate that focusing has completed. Because deciding
-         * when this occurs is application-dependent, this sound is not used by
-         * any methods in the Camera class.
-         */
-        public static final int FOCUS_COMPLETE        = 1;
-
-        /**
-         * The sound used by {@link android.media.MediaRecorder#start} to
-         * indicate the start of video recording.
-         */
-        public static final int START_VIDEO_RECORDING = 2;
-
-        /**
-         * The sound used by {@link android.media.MediaRecorder#stop} to
-         * indicate the end of video recording.
-         */
-        public static final int STOP_VIDEO_RECORDING  = 3;
-
-        private static final int NUM_SOUNDS           = 4;
-    };
-
-    /**
-     * <p>Play one of the predefined platform sounds for camera actions.</p>
-     *
-     * <p>Use this method to play a platform-specific sound for various camera
-     * actions. The sound playing is done asynchronously, with the same behavior
-     * and content as the sounds played by {@link #takePicture takePicture},
-     * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
-     * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
-     *
-     * <p>Using this method makes it easy to match the default device sounds
-     * when recording or capturing data through the preview callbacks
-     * ({@link #setPreviewCallback setPreviewCallback},
-     * {@link #setPreviewTexture setPreviewTexture}).</p>
-     *
-     * @param soundId The type of sound to play, selected from the options in
-     *   {@link android.hardware.Camera.Sound}
-     * @see android.hardware.Camera.Sound
-     * @see #takePicture
-     * @see android.media.MediaRecorder
-     * @hide
-     */
-    public void playSound(int soundId) {
-        if (mReleased) return;
-        if (mCameraSoundPlayers == null) {
-            mCameraSoundPlayers = new CameraSoundPlayer[Sound.NUM_SOUNDS];
-        }
-        if (mCameraSoundPlayers[soundId] == null) {
-            mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
-        }
-        mCameraSoundPlayers[soundId].play();
-    }
-
-    private CameraSoundPlayer[] mCameraSoundPlayers;
-
-    private static class CameraSoundPlayer implements Runnable {
-        private int mSoundId;
-        private int mAudioStreamType;
-        private MediaPlayer mPlayer;
-        private Thread mThread;
-        private boolean mExit;
-        private int mPlayCount;
-
-        private static final String mShutterSound    =
-                "/system/media/audio/ui/camera_click.ogg";
-        private static final String mFocusSound      =
-                "/system/media/audio/ui/camera_focus.ogg";
-        private static final String mVideoStartSound =
-                "/system/media/audio/ui/VideoRecord.ogg";
-        private static final String mVideoStopSound  =
-                "/system/media/audio/ui/VideoRecord.ogg";
-
-        @Override
-        public void run() {
-            String soundFilePath;
-            switch (mSoundId) {
-                case Sound.SHUTTER_CLICK:
-                    soundFilePath = mShutterSound;
-                    break;
-                case Sound.FOCUS_COMPLETE:
-                    soundFilePath = mFocusSound;
-                    break;
-                case Sound.START_VIDEO_RECORDING:
-                    soundFilePath = mVideoStartSound;
-                    break;
-                case Sound.STOP_VIDEO_RECORDING:
-                    soundFilePath = mVideoStopSound;
-                    break;
-                default:
-                    Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
-                    return;
-            }
-            mPlayer = new MediaPlayer();
-            try {
-                mPlayer.setAudioStreamType(mAudioStreamType);
-                mPlayer.setDataSource(soundFilePath);
-                mPlayer.setLooping(false);
-                mPlayer.prepare();
-            } catch(IOException e) {
-                Log.e(TAG, "Error setting up sound " + mSoundId, e);
-                return;
-            }
-
-            while(true) {
-                try {
-                    synchronized (this) {
-                        while(true) {
-                            if (mExit) {
-                                return;
-                            } else if (mPlayCount <= 0) {
-                                wait();
-                            } else {
-                                mPlayCount--;
-                                break;
-                            }
-                        }
-                    }
-                    mPlayer.start();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error playing sound " + mSoundId, e);
-                }
-            }
-        }
-
-        public CameraSoundPlayer(int soundId) {
-            mSoundId = soundId;
-            if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
-                mAudioStreamType = AudioManager.STREAM_MUSIC;
-            } else {
-                mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
-            }
-        }
-
-        public void play() {
-            if (mThread == null) {
-                mThread = new Thread(this);
-                mThread.start();
-            }
-            synchronized (this) {
-                mPlayCount++;
-                notifyAll();
-            }
-        }
-
-        public void release() {
-            if (mThread != null) {
-                synchronized (this) {
-                    mExit = true;
-                    notifyAll();
-                }
-                try {
-                    mThread.join();
-                } catch (InterruptedException e) {
-                }
-                mThread = null;
-            }
-            if (mPlayer != null) {
-                mPlayer.release();
-                mPlayer = null;
-            }
-        }
-
-        @Override
-        protected void finalize() {
-            release();
-        }
-    }
-
 }
diff --git a/core/java/android/hardware/CameraSound.java b/core/java/android/hardware/CameraSound.java
new file mode 100644
index 0000000..32de0cd
--- /dev/null
+++ b/core/java/android/hardware/CameraSound.java
@@ -0,0 +1,223 @@
+/*
+ * 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.hardware;
+
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * <p>Use this class to play an appropriate sound when implementing a custom
+ * still or video recording mechanism through the preview callbacks.</p>
+ *
+ * <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
+ * or {@link android.media.MediaRecorder} for still images or video,
+ * respectively, as these play their own sounds when needed.</p>
+ *
+ * @hide
+ */
+public class CameraSound {
+    private static final String TAG = "CameraSound";
+    /**
+     * The sound used by {@link android.hardware.Camera#takePicture} to
+     * indicate still image capture.
+     */
+    public static final int SHUTTER_CLICK         = 0;
+
+    /**
+     * A sound to indicate that focusing has completed. Because deciding
+     * when this occurs is application-dependent, this sound is not used by
+     * any methods in the Camera class.
+     */
+    public static final int FOCUS_COMPLETE        = 1;
+
+    /**
+     * The sound used by {@link android.media.MediaRecorder#start} to
+     * indicate the start of video recording.
+     */
+    public static final int START_VIDEO_RECORDING = 2;
+
+    /**
+     * The sound used by {@link android.media.MediaRecorder#stop} to
+     * indicate the end of video recording.
+     */
+    public static final int STOP_VIDEO_RECORDING  = 3;
+
+    private static final int NUM_SOUNDS           = 4;
+    private CameraSoundPlayer[] mCameraSoundPlayers;
+
+    public CameraSound() {
+    }
+
+    /**
+     * <p>Play one of the predefined platform sounds for camera actions.</p>
+     *
+     * <p>Use this method to play a platform-specific sound for various camera
+     * actions. The sound playing is done asynchronously, with the same behavior
+     * and content as the sounds played by {@link #takePicture takePicture},
+     * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
+     * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
+     *
+     * <p>Using this method makes it easy to match the default device sounds
+     * when recording or capturing data through the preview callbacks.</p>
+     *
+     * @param soundId The type of sound to play, selected from SHUTTER_CLICK,
+     *         FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
+     * @see android.hardware#takePicture
+     * @see android.media.MediaRecorder
+     * @see #SHUTTER_CLICK
+     * @see #FOCUS_COMPLETE
+     * @see #START_VIDEO_RECORDING
+     * @see #STOP_VIDEO_RECORDING
+     */
+    public void playSound(int soundId) {
+        if (mCameraSoundPlayers == null) {
+            mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
+        }
+        if (mCameraSoundPlayers[soundId] == null) {
+            mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
+        }
+        mCameraSoundPlayers[soundId].play();
+    }
+
+    public void release() {
+        if (mCameraSoundPlayers != null) {
+            for (CameraSoundPlayer csp: mCameraSoundPlayers) {
+                if (csp != null) {
+                    csp.release();
+                }
+            }
+            mCameraSoundPlayers = null;
+        }
+    }
+
+    private static class CameraSoundPlayer implements Runnable {
+        private int mSoundId;
+        private int mAudioStreamType;
+        private MediaPlayer mPlayer;
+        private Thread mThread;
+        private boolean mExit;
+        private int mPlayCount;
+
+        private static final String mShutterSound    =
+                "/system/media/audio/ui/camera_click.ogg";
+        private static final String mFocusSound      =
+                "/system/media/audio/ui/camera_focus.ogg";
+        private static final String mVideoStartSound =
+                "/system/media/audio/ui/VideoRecord.ogg";
+        private static final String mVideoStopSound  =
+                "/system/media/audio/ui/VideoRecord.ogg";
+
+        @Override
+        public void run() {
+            String soundFilePath;
+            switch (mSoundId) {
+                case SHUTTER_CLICK:
+                    soundFilePath = mShutterSound;
+                    break;
+                case FOCUS_COMPLETE:
+                    soundFilePath = mFocusSound;
+                    break;
+                case START_VIDEO_RECORDING:
+                    soundFilePath = mVideoStartSound;
+                    break;
+                case STOP_VIDEO_RECORDING:
+                    soundFilePath = mVideoStopSound;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
+                    return;
+            }
+            mPlayer = new MediaPlayer();
+            try {
+                mPlayer.setAudioStreamType(mAudioStreamType);
+                mPlayer.setDataSource(soundFilePath);
+                mPlayer.setLooping(false);
+                mPlayer.prepare();
+            } catch(IOException e) {
+                Log.e(TAG, "Error setting up sound " + mSoundId, e);
+                return;
+            }
+
+            while(true) {
+                try {
+                    synchronized (this) {
+                        while(true) {
+                            if (mExit) {
+                                return;
+                            } else if (mPlayCount <= 0) {
+                                wait();
+                            } else {
+                                mPlayCount--;
+                                break;
+                            }
+                        }
+                    }
+                    mPlayer.start();
+                } catch (Exception e) {
+                    Log.e(TAG, "Error playing sound " + mSoundId, e);
+                }
+            }
+        }
+
+        public CameraSoundPlayer(int soundId) {
+            mSoundId = soundId;
+            if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
+                mAudioStreamType = AudioManager.STREAM_MUSIC;
+            } else {
+                mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
+            }
+        }
+
+        public void play() {
+            if (mThread == null) {
+                mThread = new Thread(this);
+                mThread.start();
+            }
+            synchronized (this) {
+                mPlayCount++;
+                notifyAll();
+            }
+        }
+
+        public void release() {
+            if (mThread != null) {
+                synchronized (this) {
+                    mExit = true;
+                    notifyAll();
+                }
+                try {
+                    mThread.join();
+                } catch (InterruptedException e) {
+                }
+                mThread = null;
+            }
+            if (mPlayer != null) {
+                mPlayer.release();
+                mPlayer = null;
+            }
+        }
+
+        @Override
+        protected void finalize() {
+            release();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 4fc63ed..10c1195 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -156,4 +156,48 @@
             mIME.onViewClicked(false);
         }
     }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @Override
+    protected void deleteText_internal(int start, int end) {
+        // Do not call the super method.
+        // This will change the source TextView instead, which will update the ExtractTextView.
+        mIME.onExtractedDeleteText(start, end);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @Override
+    protected void replaceText_internal(int start, int end, CharSequence text) {
+        // Do not call the super method.
+        // This will change the source TextView instead, which will update the ExtractTextView.
+        mIME.onExtractedReplaceText(start, end, text);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @Override
+    protected void setSpan_internal(Object span, int start, int end, int flags) {
+        // Do not call the super method.
+        // This will change the source TextView instead, which will update the ExtractTextView.
+        mIME.onExtractedSetSpan(span, start, end, flags);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @Override
+    protected void setCursorPosition_internal(int start, int end) {
+        // Do not call the super method.
+        // This will change the source TextView instead, which will update the ExtractTextView.
+        mIME.onExtractedSelectionChanged(start, end);
+    }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 60188ea..53cdf21 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1982,7 +1982,45 @@
             conn.setSelection(start, end);
         }
     }
-    
+
+    /**
+     * @hide
+     */
+    public void onExtractedDeleteText(int start, int end) {
+        InputConnection conn = getCurrentInputConnection();
+        if (conn != null) {
+            conn.setSelection(start, start);
+            conn.deleteSurroundingText(0, end-start);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onExtractedReplaceText(int start, int end, CharSequence text) {
+        InputConnection conn = getCurrentInputConnection();
+        if (conn != null) {
+            conn.setComposingRegion(start, end);
+            conn.commitText(text, 1);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onExtractedSetSpan(Object span, int start, int end, int flags) {
+        InputConnection conn = getCurrentInputConnection();
+        if (conn != null) {
+            if (!conn.setSelection(start, end)) return;
+            CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
+            if (text instanceof Spannable) {
+                ((Spannable) text).setSpan(span, 0, text.length(), flags);
+                conn.setComposingRegion(start, end);
+                conn.commitText(text, 1);
+            }
+        }
+    }
+
     /**
      * This is called when the user has clicked on the extracted text view,
      * when running in fullscreen mode.  The default implementation hides
@@ -1998,7 +2036,7 @@
             setCandidatesViewShown(false);
         }
     }
-    
+
     /**
      * This is called when the user has performed a cursor movement in the
      * extracted text view, when it is running in fullscreen mode.  The default
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 5143f7f..7257521 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -31,6 +31,7 @@
 import android.media.AudioManager;
 import android.os.Handler;
 import android.os.Message;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.GestureDetector;
@@ -967,8 +968,13 @@
             AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
             onInitializeAccessibilityEvent(event);
             String text = null;
-            // Add text only if headset is used to avoid leaking passwords.
-            if (mAudioManager.isBluetoothA2dpOn() || mAudioManager.isWiredHeadsetOn()) {
+            // This is very efficient since the properties are cached.
+            final boolean speakPassword = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0;
+            // Add text only if password announcement is enabled or if headset is
+            // used to avoid leaking passwords.
+            if (speakPassword || mAudioManager.isBluetoothA2dpOn()
+                    || mAudioManager.isWiredHeadsetOn()) {
                 switch (code) {
                     case Keyboard.KEYCODE_ALT:
                         text = mContext.getString(R.string.keyboardview_keycode_alt);
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index e289fc1..d39e741 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -250,4 +250,32 @@
         }
         return result;
     }
+
+    /**
+     * Trim leading zeros from IPv4 address strings
+     * Our base libraries will interpret that as octel..
+     * Must leave non v4 addresses and host names alone.
+     * For example, 192.168.000.010 -> 192.168.0.10
+     * TODO - fix base libraries and remove this function
+     * @param addr a string representing an ip addr
+     * @return a string propertly trimmed
+     */
+    public static String trimV4AddrZeros(String addr) {
+        if (addr == null) return null;
+        String[] octets = addr.split("\\.");
+        if (octets.length != 4) return addr;
+        StringBuilder builder = new StringBuilder(16);
+        String result = null;
+        for (int i = 0; i < 4; i++) {
+            try {
+                if (octets[i].length() > 3) return addr;
+                builder.append(Integer.parseInt(octets[i]));
+            } catch (NumberFormatException e) {
+                return addr;
+            }
+            if (i < 3) builder.append('.');
+        }
+        result = builder.toString();
+        return result;
+    }
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 7d034940..88fea91 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -311,7 +311,7 @@
         public static final int ICE_CREAM_SANDWICH = 14;
 
         /**
-         * Android 4.1.
+         * Android 4.0.3.
          */
         public static final int ICE_CREAM_SANDWICH_MR1 = 15;
     }
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 81defd6..0586d9e 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -128,6 +128,19 @@
     int TWEET_TRANSACTION   = ('_'<<24)|('T'<<16)|('W'<<8)|'T';
 
     /**
+     * IBinder protocol transaction code: tell an app asynchronously that the
+     * caller likes it.  The app is responsible for incrementing and maintaining
+     * its own like counter, and may display this value to the user to indicate the
+     * quality of the app.  This is an optional command that applications do not
+     * need to handle, so the default implementation is to do nothing.
+     * 
+     * <p>There is no response returned and nothing about the
+     * system will be functionally affected by it, but it will improve the
+     * app's self-esteem.
+     */
+    int LIKE_TRANSACTION   = ('_'<<24)|('L'<<16)|('I'<<8)|'K';
+
+    /**
      * Flag to {@link #transact}: this is a one-way call, meaning that the
      * caller returns immediately, without waiting for a result from the
      * callee. Applies only if the caller and callee are in different
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 3362575..e1bc275 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -101,7 +101,7 @@
      * Defines the UID/GID for the NFC service process.
      * @hide
      */
-    public static final int NFC_UID = 1025;
+    public static final int NFC_UID = 1027;
 
     /**
      * Defines the GID for the group that allows write access to the internal media storage.
diff --git a/core/java/android/os/storage/package.html b/core/java/android/os/storage/package.html
new file mode 100644
index 0000000..a5f1e1c
--- /dev/null
+++ b/core/java/android/os/storage/package.html
@@ -0,0 +1,8 @@
+<HTML>
+<BODY>
+<p>
+Contains classes for the system storage service, which manages binary asset filesystems
+known as Opaque Binary Blobs (OBBs).
+</p>
+</BODY>
+</HTML>
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 5f111eb..4e01672 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,8 +40,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.text.Collator;
 
 /**
  * The Media provider contains meta data for all available media on both internal
@@ -66,7 +64,10 @@
     /**
      * Activity Action: Launch a music player.
      * The activity should be able to play, browse, or manipulate music files stored on the device.
+     *
+     * @deprecated Use {@link android.content.Intent#CATEGORY_APP_MUSIC} instead.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b032169..65b4e7e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2754,6 +2754,11 @@
             "enabled_accessibility_services";
 
         /**
+         * Whether to speak passwords while in accessibility mode.
+         */
+        public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
+
+        /**
          * If injection of accessibility enhancing JavaScript scripts
          * is enabled.
          * <p>
@@ -3107,6 +3112,14 @@
                 "wifi_watchdog_blacklist_followup_interval_ms";
 
         /**
+         * Setting to turn off poor network avoidance on Wi-Fi. Feature is disabled by default and
+         * the setting needs to be set to 1 to enable it.
+         * @hide
+         */
+        public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
+                "wifi_watchdog_poor_network_test_enabled";
+
+        /**
          * 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
@@ -4019,23 +4032,6 @@
         public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
                 "setup_prepaid_detection_redir_host";
 
-        /**
-         * The user's preferred "dream" (interactive screensaver) component.
-         *
-         * This component will be launched by the PhoneWindowManager after the user's chosen idle
-         * timeout (specified by {@link #DREAM_TIMEOUT}).
-         * @hide
-         */
-        public static final String DREAM_COMPONENT =
-                "dream_component";
-
-        /**
-         * The delay before a "dream" is started (set to 0 to disable).
-         * @hide
-         */
-        public static final String DREAM_TIMEOUT =
-                "dream_timeout";
-
         /** {@hide} */
         public static final String NETSTATS_ENABLED = "netstats_enabled";
         /** {@hide} */
@@ -4096,6 +4092,7 @@
             ENABLED_ACCESSIBILITY_SERVICES,
             TOUCH_EXPLORATION_ENABLED,
             ACCESSIBILITY_ENABLED,
+            ACCESSIBILITY_SPEAK_PASSWORD,
             TTS_USE_DEFAULTS,
             TTS_DEFAULT_RATE,
             TTS_DEFAULT_PITCH,
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
index da7c489..f3f4174 100644
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -175,8 +175,8 @@
             switch(message.what) {
                 case USER_TURN_ON:
                     // starts turning on BT module, broadcast this out
-                    transitionTo(mWarmUp);
                     broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                    transitionTo(mWarmUp);
                     if (prepareBluetooth()) {
                         // this is user request, save the setting
                         if ((Boolean) message.obj) {
@@ -198,8 +198,8 @@
                 case AIRPLANE_MODE_OFF:
                     if (getBluetoothPersistedSetting()) {
                         // starts turning on BT module, broadcast this out
-                        transitionTo(mWarmUp);
                         broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+                        transitionTo(mWarmUp);
                         if (prepareBluetooth()) {
                             // We will continue turn the BT on all the way to the BluetoothOn state
                             deferMessage(obtainMessage(TURN_ON_CONTINUE));
@@ -355,9 +355,9 @@
                     // let it fall to TURN_ON_CONTINUE:
                     //$FALL-THROUGH$
                 case TURN_ON_CONTINUE:
+                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                     mBluetoothService.switchConnectable(true);
                     transitionTo(mSwitching);
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                     break;
                 case AIRPLANE_MODE_ON:
                 case TURN_COLD:
@@ -367,9 +367,9 @@
                     break;
                 case AIRPLANE_MODE_OFF:
                     if (getBluetoothPersistedSetting()) {
+                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                         transitionTo(mSwitching);
                         mBluetoothService.switchConnectable(true);
-                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                     }
                     break;
                 case PER_PROCESS_TURN_ON:
@@ -515,8 +515,8 @@
                     }
                     //$FALL-THROUGH$ to AIRPLANE_MODE_ON
                 case AIRPLANE_MODE_ON:
-                    transitionTo(mSwitching);
                     broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+                    transitionTo(mSwitching);
                     if (mBluetoothService.getAdapterConnectionState() !=
                         BluetoothAdapter.STATE_DISCONNECTED) {
                         mBluetoothService.disconnectDevices();
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 28e231e..94fbbc8 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -145,7 +145,12 @@
     private final ArrayList<String> mUuidIntentTracker;
     private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
 
-    private final HashMap<Integer, Pair<Integer, IBinder>> mServiceRecordToPid;
+    private static class ServiceRecordClient {
+        int pid;
+        IBinder binder;
+        IBinder.DeathRecipient death;
+    }
+    private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid;
 
     private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
     private final BluetoothProfileState mA2dpProfileState;
@@ -221,7 +226,7 @@
         mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
         mUuidIntentTracker = new ArrayList<String>();
         mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
-        mServiceRecordToPid = new HashMap<Integer, Pair<Integer, IBinder>>();
+        mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();
         mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
         mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
         mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
@@ -1528,11 +1533,17 @@
             return -1;
         }
 
-        int pid = Binder.getCallingPid();
-        mServiceRecordToPid.put(new Integer(handle), new Pair<Integer, IBinder>(pid, b));
+        ServiceRecordClient client = new ServiceRecordClient();
+        client.pid = Binder.getCallingPid();
+        client.binder = b;
+        client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER);
+        mServiceRecordToPid.put(new Integer(handle), client);
         try {
-            b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            b.linkToDeath(client.death, 0);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            client.death = null;
+        }
         return handle;
     }
 
@@ -1547,10 +1558,15 @@
     }
 
     private synchronized void checkAndRemoveRecord(int handle, int pid) {
-        Pair<Integer, IBinder> pidPair = mServiceRecordToPid.get(handle);
-        if (pidPair != null && pid == pidPair.first) {
+        ServiceRecordClient client = mServiceRecordToPid.get(handle);
+        if (client != null && pid == client.pid) {
             if (DBG) Log.d(TAG, "Removing service record " +
                 Integer.toHexString(handle) + " for pid " + pid);
+
+            if (client.death != null) {
+                client.binder.unlinkToDeath(client.death, 0);
+            }
+
             mServiceRecordToPid.remove(handle);
             removeServiceRecordNative(handle);
         }
@@ -1880,7 +1896,7 @@
     private void dumpApplicationServiceRecords(PrintWriter pw) {
         pw.println("\n--Application Service Records--");
         for (Integer handle : mServiceRecordToPid.keySet()) {
-            Integer pid = mServiceRecordToPid.get(handle).first;
+            Integer pid = mServiceRecordToPid.get(handle).pid;
             pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
         }
     }
@@ -2374,16 +2390,18 @@
     }
 
     BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) {
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) return state;
-
-        state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
+        BluetoothDeviceProfileState state =
+            new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
         mDeviceProfileState.put(address, state);
         state.start();
         return state;
     }
 
     void removeProfileState(String address) {
+        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
+        if (state == null) return;
+
+        state.quit();
         mDeviceProfileState.remove(address);
     }
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a9a628a..18167b6 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -608,7 +608,7 @@
 
                     final int relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
-                            View.VISIBLE, false, mWinFrame, mContentInsets,
+                            View.VISIBLE, 0, mWinFrame, mContentInsets,
                             mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
 
                     if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
@@ -654,7 +654,7 @@
                         }
 
                         redrawNeeded |= creating
-                                || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0;
+                                || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
 
                         if (forceReport || creating || surfaceCreating
                                 || formatChanged || sizeChanged) {
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 0194240..46a78dc 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -118,12 +118,26 @@
         if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
             stop(current);
         }
+
+        final MessageParams lastSynthesis = mLastSynthesisRequest;
+
+        if (lastSynthesis != null && lastSynthesis != current &&
+                TextUtils.equals(callingApp, lastSynthesis.getCallingApp())) {
+            stop(lastSynthesis);
+        }
     }
 
     synchronized public void removeAllItems() {
         if (DBG_THREADING) Log.d(TAG, "Removing all items");
         removeAllMessages();
-        stop(getCurrentParams());
+
+        final MessageParams current = getCurrentParams();
+        final MessageParams lastSynthesis = mLastSynthesisRequest;
+        stop(current);
+
+        if (lastSynthesis != null && lastSynthesis != current) {
+            stop(lastSynthesis);
+        }
     }
 
     /**
@@ -350,7 +364,7 @@
         // extra trouble to clean the data to prevent the AudioTrack resources
         // from being leaked.
         if (mLastSynthesisRequest != null) {
-            Log.w(TAG, "Error : Missing call to done() for request : " +
+            Log.e(TAG, "Error : Missing call to done() for request : " +
                     mLastSynthesisRequest);
             handleSynthesisDone(mLastSynthesisRequest);
         }
@@ -414,7 +428,8 @@
         final AudioTrack audioTrack = params.getAudioTrack();
 
         if (audioTrack == null) {
-            params.getDispatcher().dispatchOnError();
+            // There was already a call to handleSynthesisDone for
+            // this token.
             return;
         }
 
@@ -443,7 +458,11 @@
             audioTrack.release();
             params.setAudioTrack(null);
         }
-        params.getDispatcher().dispatchOnDone();
+        if (params.isError()) {
+            params.getDispatcher().dispatchOnError();
+        } else {
+            params.getDispatcher().dispatchOnDone();
+        }
         mLastSynthesisRequest = null;
         params.mLogger.onWriteData();
     }
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index ce3522b..91a3452 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -80,27 +80,23 @@
 
     @Override
     void stop() {
+        stopImpl(false);
+    }
+
+    void stopImpl(boolean wasError) {
         if (DBG) Log.d(TAG, "stop()");
 
         // Note that mLogger.mError might be true too at this point.
         mLogger.onStopped();
 
-        SynthesisMessageParams token = null;
+        SynthesisMessageParams token;
         synchronized (mStateLock) {
             if (mStopped) {
                 Log.w(TAG, "stop() called twice");
                 return;
             }
 
-            // mToken will be null if the engine encounters
-            // an error before it called start().
-            if (mToken == null) {
-                // In all other cases, mAudioTrackHandler.stop() will
-                // result in onComplete being called.
-                mLogger.onWriteData();
-            } else {
-                token = mToken;
-            }
+            token = mToken;
             mStopped = true;
         }
 
@@ -109,7 +105,24 @@
             // point it will write an additional buffer to the token - but we
             // won't worry about that because the audio playback queue will be cleared
             // soon after (see SynthHandler#stop(String).
+            token.setIsError(wasError);
             token.clearBuffers();
+            if (wasError) {
+                // Also clean up the audio track if an error occurs.
+                mAudioTrackHandler.enqueueSynthesisDone(token);
+            }
+        } else {
+            // This happens when stop() or error() were called before start() was.
+
+            // In all other cases, mAudioTrackHandler.stop() will
+            // result in onSynthesisDone being called, and we will
+            // write data there.
+            mLogger.onWriteData();
+
+            if (wasError) {
+                // We have to dispatch the error ourselves.
+                mDispatcher.dispatchOnError();
+            }
         }
     }
 
@@ -219,7 +232,7 @@
         // Currently, this call will not be logged if error( ) is called
         // before start.
         mLogger.onError();
-        stop();
+        stopImpl(true);
     }
 
 }
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index 0c0f033..ed66420 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -51,6 +51,7 @@
     int mAudioBufferSize;
     // Always synchronized on "this".
     int mUnconsumedBytes;
+    volatile boolean mIsError;
 
     private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
 
@@ -74,6 +75,7 @@
         mAudioTrack = null;
         mBytesWritten = 0;
         mAudioBufferSize = 0;
+        mIsError = false;
     }
 
     @Override
@@ -120,6 +122,14 @@
         return mAudioTrack;
     }
 
+    void setIsError(boolean isError) {
+        mIsError = isError;
+    }
+
+    boolean isError() {
+        return mIsError;
+    }
+
     // Must be called synchronized on this.
     private long getUnconsumedAudioLengthMs() {
         final int unconsumedFrames = mUnconsumedBytes / mBytesPerFrame;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 38699ea..a220615 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -490,6 +490,7 @@
     private final Map<String, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
+    private final String mPackageName;
     private volatile String mCurrentEngine = null;
 
     /**
@@ -518,19 +519,36 @@
      * @param engine Package name of the TTS engine to use.
      */
     public TextToSpeech(Context context, OnInitListener listener, String engine) {
+        this(context, listener, engine, null);
+    }
+
+    /**
+     * Used by the framework to instantiate TextToSpeech objects with a supplied
+     * package name, instead of using {@link android.content.Context#getPackageName()}
+     *
+     * @hide
+     */
+    public TextToSpeech(Context context, OnInitListener listener, String engine,
+            String packageName) {
         mContext = context;
         mInitListener = listener;
         mRequestedEngine = engine;
 
         mEarcons = new HashMap<String, Uri>();
         mUtterances = new HashMap<String, Uri>();
+        mUtteranceProgressListener = null;
 
         mEnginesHelper = new TtsEngines(mContext);
+        if (packageName != null) {
+            mPackageName = packageName;
+        } else {
+            mPackageName = mContext.getPackageName();
+        }
         initTts();
     }
 
     private String getPackageName() {
-        return mContext.getPackageName();
+        return mPackageName;
     }
 
     private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 39922da..aee678a 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -450,7 +450,7 @@
         @Override
         public void dispatchOnDone() {
             final String utteranceId = getUtteranceId();
-            if (!TextUtils.isEmpty(utteranceId)) {
+            if (utteranceId != null) {
                 mCallbacks.dispatchOnDone(getCallingApp(), utteranceId);
             }
         }
@@ -458,7 +458,7 @@
         @Override
         public void dispatchOnStart() {
             final String utteranceId = getUtteranceId();
-            if (!TextUtils.isEmpty(utteranceId)) {
+            if (utteranceId != null) {
                 mCallbacks.dispatchOnStart(getCallingApp(), utteranceId);
             }
         }
@@ -466,7 +466,7 @@
         @Override
         public void dispatchOnError() {
             final String utteranceId = getUtteranceId();
-            if (!TextUtils.isEmpty(utteranceId)) {
+            if (utteranceId != null) {
                 mCallbacks.dispatchOnError(getCallingApp(), utteranceId);
             }
         }
@@ -509,6 +509,7 @@
     }
 
     class SynthesisSpeechItem extends SpeechItem {
+        // Never null.
         private final String mText;
         private final SynthesisRequest mSynthesisRequest;
         private final String[] mDefaultLocale;
@@ -532,8 +533,8 @@
 
         @Override
         public boolean isValid() {
-            if (TextUtils.isEmpty(mText)) {
-                Log.w(TAG, "Got empty text");
+            if (mText == null) {
+                Log.wtf(TAG, "Got null text");
                 return false;
             }
             if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index a04458a..cf0d22c 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -57,12 +57,16 @@
                 listener.onUtteranceCompleted(utteranceId);
             }
 
-            // The following methods are left unimplemented.
             @Override
-            public void onStart(String utteranceId) { }
+            public void onError(String utteranceId) {
+                listener.onUtteranceCompleted(utteranceId);
+            }
 
             @Override
-            public void onError(String utteranceId) { }
+            public void onStart(String utteranceId) {
+                // Left unimplemented, has no equivalent in the old
+                // API.
+            }
         };
     }
 }
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 231f913..b708750 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -863,6 +863,17 @@
         return new String(buf);
     }
 
+    /**
+     * Return a String containing a copy of the chars in this buffer, limited to the
+     * [start, end[ range.
+     * @hide
+     */
+    public String substring(int start, int end) {
+        char[] buf = new char[end - start];
+        getChars(start, end, buf, 0);
+        return new String(buf);
+    }
+
     private TextWatcher[] sendTextWillChange(int start, int before, int after) {
         TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class);
         int n = recip.length;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 68fea19..b3df8ff 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -59,6 +59,12 @@
     private boolean mCharsValid;
     private Spanned mSpanned;
     private final TextPaint mWorkPaint = new TextPaint();
+    private final SpanSet<MetricAffectingSpan> mMetricAffectingSpanSpanSet =
+            new SpanSet<MetricAffectingSpan>(MetricAffectingSpan.class);
+    private final SpanSet<CharacterStyle> mCharacterStyleSpanSet =
+            new SpanSet<CharacterStyle>(CharacterStyle.class);
+    private final SpanSet<ReplacementSpan> mReplacementSpanSpanSet =
+            new SpanSet<ReplacementSpan>(ReplacementSpan.class);
 
     private static final TextLine[] sCached = new TextLine[3];
 
@@ -136,9 +142,8 @@
         boolean hasReplacement = false;
         if (text instanceof Spanned) {
             mSpanned = (Spanned) text;
-            ReplacementSpan[] spans = mSpanned.getSpans(start, limit, ReplacementSpan.class);
-            spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
-            hasReplacement = spans.length > 0;
+            mReplacementSpanSpanSet.init(mSpanned, start, limit);
+            hasReplacement = mReplacementSpanSpanSet.numberOfSpans > 0;
         }
 
         mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
@@ -156,10 +161,8 @@
                 // zero-width characters.
                 char[] chars = mChars;
                 for (int i = start, inext; i < limit; i = inext) {
-                    inext = mSpanned.nextSpanTransition(i, limit, ReplacementSpan.class);
-                    ReplacementSpan[] spans = mSpanned.getSpans(i, inext, ReplacementSpan.class);
-                    spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
-                    if (spans.length > 0) {
+                    inext = mReplacementSpanSpanSet.getNextTransition(i, limit);
+                    if (mReplacementSpanSpanSet.hasSpansIntersecting(i, inext)) {
                         // transition into a span
                         chars[i - start] = '\ufffc';
                         for (int j = i - start + 1, e = inext - start; j < e; ++j) {
@@ -853,21 +856,30 @@
     }
 
     private static class SpanSet<E> {
-        final int numberOfSpans;
-        final E[] spans;
-        final int[] spanStarts;
-        final int[] spanEnds;
-        final int[] spanFlags;
+        int numberOfSpans;
+        E[] spans;
+        int[] spanStarts;
+        int[] spanEnds;
+        int[] spanFlags;
+        final Class<? extends E> classType;
+
+        SpanSet(Class<? extends E> type) {
+            classType = type;
+            numberOfSpans = 0;
+        }
 
         @SuppressWarnings("unchecked")
-        SpanSet(Spanned spanned, int start, int limit, Class<? extends E> type) {
-            final E[] allSpans = spanned.getSpans(start, limit, type);
+        public void init(Spanned spanned, int start, int limit) {
+            final E[] allSpans = spanned.getSpans(start, limit, classType);
             final int length = allSpans.length;
-            // These arrays may end up being too large because of empty spans
-            spans = (E[]) Array.newInstance(type, length);
-            spanStarts = new int[length];
-            spanEnds = new int[length];
-            spanFlags = new int[length];
+
+            if (length > 0 && (spans == null || spans.length < length)) {
+                // These arrays may end up being too large because of empty spans
+                spans = (E[]) Array.newInstance(classType, length);
+                spanStarts = new int[length];
+                spanEnds = new int[length];
+                spanFlags = new int[length];
+            }
 
             int count = 0;
             for (int i = 0; i < length; i++) {
@@ -878,36 +890,26 @@
                 if (spanStart == spanEnd) continue;
 
                 final int spanFlag = spanned.getSpanFlags(span);
-                final int priority = spanFlag & Spanned.SPAN_PRIORITY;
-                if (priority != 0 && count != 0) {
-                    int j;
 
-                    for (j = 0; j < count; j++) {
-                        final int otherPriority = spanFlags[j] & Spanned.SPAN_PRIORITY;
-                        if (priority > otherPriority) break;
-                    }
-
-                    System.arraycopy(spans, j, spans, j + 1, count - j);
-                    System.arraycopy(spanStarts, j, spanStarts, j + 1, count - j);
-                    System.arraycopy(spanEnds, j, spanEnds, j + 1, count - j);
-                    System.arraycopy(spanFlags, j, spanFlags, j + 1, count - j);
-
-                    spans[j] = span;
-                    spanStarts[j] = spanStart;
-                    spanEnds[j] = spanEnd;
-                    spanFlags[j] = spanFlag;
-                } else {
-                    spans[i] = span;
-                    spanStarts[i] = spanStart;
-                    spanEnds[i] = spanEnd;
-                    spanFlags[i] = spanFlag;
-                }
+                spans[i] = span;
+                spanStarts[i] = spanStart;
+                spanEnds[i] = spanEnd;
+                spanFlags[i] = spanFlag;
 
                 count++;
             }
             numberOfSpans = count;
         }
 
+        public boolean hasSpansIntersecting(int start, int end) {
+            for (int i = 0; i < numberOfSpans; i++) {
+                // equal test is valid since both intervals are not empty by construction
+                if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
+                return true;
+            }
+            return false;
+        }
+
         int getNextTransition(int start, int limit) {
             for (int i = 0; i < numberOfSpans; i++) {
                 final int spanStart = spanStarts[i];
@@ -960,10 +962,8 @@
                     y, bottom, fmi, needWidth || mlimit < measureLimit);
         }
 
-        final SpanSet<MetricAffectingSpan> metricAffectingSpans = new SpanSet<MetricAffectingSpan>(
-                mSpanned, mStart + start, mStart + limit, MetricAffectingSpan.class);
-        final SpanSet<CharacterStyle> characterStyleSpans = new SpanSet<CharacterStyle>(
-                    mSpanned, mStart + start, mStart + limit, CharacterStyle.class);
+        mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
+        mCharacterStyleSpanSet.init(mSpanned, mStart + start, mStart + limit);
 
         // Shaping needs to take into account context up to metric boundaries,
         // but rendering needs to take into account character style boundaries.
@@ -975,17 +975,18 @@
             TextPaint wp = mWorkPaint;
             wp.set(mPaint);
 
-            inext = metricAffectingSpans.getNextTransition(mStart + i, mStart + limit) - mStart;
+            inext = mMetricAffectingSpanSpanSet.getNextTransition(mStart + i, mStart + limit) -
+                    mStart;
             int mlimit = Math.min(inext, measureLimit);
 
             ReplacementSpan replacement = null;
 
-            for (int j = 0; j < metricAffectingSpans.numberOfSpans; j++) {
+            for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {
                 // Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT
                 // empty by construction. This special case in getSpans() explains the >= & <= tests
-                if ((metricAffectingSpans.spanStarts[j] >= mStart + mlimit) ||
-                        (metricAffectingSpans.spanEnds[j] <= mStart + i)) continue;
-                MetricAffectingSpan span = metricAffectingSpans.spans[j];
+                if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) ||
+                        (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i)) continue;
+                MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];
                 if (span instanceof ReplacementSpan) {
                     replacement = (ReplacementSpan)span;
                 } else {
@@ -1006,16 +1007,16 @@
                         y, bottom, fmi, needWidth || mlimit < measureLimit);
             } else {
                 for (int j = i, jnext; j < mlimit; j = jnext) {
-                    jnext = characterStyleSpans.getNextTransition(mStart + j, mStart + mlimit) -
+                    jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
                             mStart;
 
                     wp.set(mPaint);
-                    for (int k = 0; k < characterStyleSpans.numberOfSpans; k++) {
+                    for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
                         // Intentionally using >= and <= as explained above
-                        if ((characterStyleSpans.spanStarts[k] >= mStart + jnext) ||
-                                (characterStyleSpans.spanEnds[k] <= mStart + j)) continue;
+                        if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+                                (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
 
-                        CharacterStyle span = characterStyleSpans.spans[k];
+                        CharacterStyle span = mCharacterStyleSpanSet.spans[k];
                         span.updateDrawState(wp);
                     }
 
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 353b628..7f8af7a 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -1415,7 +1415,7 @@
             }
         }
 
-        if (noMonthDay && startMonthNum == endMonthNum) {
+        if (noMonthDay && startMonthNum == endMonthNum && startYear == endYear) {
             // Example: "January, 2008"
             return formatter.format("%s", startDate.format(defaultDateFormat));
         }
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 5ae65df..121c6f2 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -21,7 +21,7 @@
 
 /**
  * Utility class to aid in formatting common values that are not covered
- * by {@link java.util.Formatter}
+ * by the {@link java.util.Formatter} class in {@link java.util}
  */
 public final class Formatter {
 
diff --git a/core/java/android/text/format/package.html b/core/java/android/text/format/package.html
new file mode 100644
index 0000000..b9e6a44
--- /dev/null
+++ b/core/java/android/text/format/package.html
@@ -0,0 +1,7 @@
+<HTML>
+<BODY>
+This package contains alternative classes for some text formatting classes
+defined in {@link java.util} and {@link java.text}. It also contains additional text formatting
+classes for situations not covered by {@link java.util} or {@link java.text}.
+</BODY>
+</HTML>
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 106a801..3dfd44d 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -35,22 +35,30 @@
      * Y position.
      */
     public static void scrollTo(TextView widget, Layout layout, int x, int y) {
-        final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
-        final int top = layout.getLineForVertical(y);
-        final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+        final int horizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
+        final int availableWidth = widget.getWidth() - horizontalPadding;
 
-        int left = Integer.MAX_VALUE;
-        int right = 0;
+        final int top = layout.getLineForVertical(y);
         Alignment a = layout.getParagraphAlignment(top);
         boolean ltr = layout.getParagraphDirection(top) > 0;
 
-        for (int i = top; i <= bottom; i++) {
-            left = (int) Math.min(left, layout.getLineLeft(i));
-            right = (int) Math.max(right, layout.getLineRight(i));
+        int left, right;
+        if (widget.getHorizontallyScrolling()) {
+            final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
+            final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+
+            left = Integer.MAX_VALUE;
+            right = 0;
+
+            for (int i = top; i <= bottom; i++) {
+                left = (int) Math.min(left, layout.getLineLeft(i));
+                right = (int) Math.max(right, layout.getLineRight(i));
+            }
+        } else {
+            left = 0;
+            right = availableWidth;
         }
 
-        final int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
-        final int availableWidth = widget.getWidth() - hoizontalPadding;
         final int actualWidth = right - left;
 
         if (actualWidth < availableWidth) {
@@ -166,16 +174,24 @@
         return false;
     }
 
+    /**
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     */
     public static int getInitialScrollX(TextView widget, Spannable buffer) {
         DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
         return ds.length > 0 ? ds[0].mScrollX : -1;
     }
-    
+
+    /**
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     */
     public static int getInitialScrollY(TextView widget, Spannable buffer) {
         DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
         return ds.length > 0 ? ds[0].mScrollY : -1;
     }
-    
+
     private static class DragState implements NoCopySpan {
         public float mX;
         public float mY;
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 239d9e8..11226a9 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -18,6 +18,7 @@
 package android.text.method;
 
 import android.text.Selection;
+import android.text.SpannableStringBuilder;
 
 import java.text.BreakIterator;
 import java.util.Locale;
@@ -58,7 +59,11 @@
         mOffsetShift = Math.max(0, start - WINDOW_WIDTH);
         final int windowEnd = Math.min(charSequence.length(), end + WINDOW_WIDTH);
 
-        mString = charSequence.toString().substring(mOffsetShift, windowEnd);
+        if (charSequence instanceof SpannableStringBuilder) {
+            mString = ((SpannableStringBuilder) charSequence).substring(mOffsetShift, windowEnd);
+        } else {
+            mString = charSequence.subSequence(mOffsetShift, windowEnd).toString();
+        }
         mIterator.setText(mString);
     }
 
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index ed2af10..0f26a34 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -92,11 +92,6 @@
     private float mAutoCorrectionUnderlineThickness;
     private int mAutoCorrectionUnderlineColor;
 
-    /*
-     * TODO: If switching IME is required, needs to add parameters for ids of InputMethodInfo
-     * and InputMethodSubtype.
-     */
-
     /**
      * @param context Context for the application
      * @param suggestions Suggestions for the string under the span
@@ -146,6 +141,16 @@
     }
 
     private void initStyle(Context context) {
+        if (context == null) {
+            mMisspelledUnderlineThickness = 0;
+            mEasyCorrectUnderlineThickness = 0;
+            mAutoCorrectionUnderlineThickness = 0;
+            mMisspelledUnderlineColor = Color.BLACK;
+            mEasyCorrectUnderlineColor = Color.BLACK;
+            mAutoCorrectionUnderlineColor = Color.BLACK;
+            return;
+        }
+
         int defStyle = com.android.internal.R.attr.textAppearanceMisspelledSuggestion;
         TypedArray typedArray = context.obtainStyledAttributes(
                 null, com.android.internal.R.styleable.SuggestionSpan, defStyle, 0);
@@ -169,7 +174,6 @@
                 com.android.internal.R.styleable.SuggestionSpan_textUnderlineThickness, 0);
         mAutoCorrectionUnderlineColor = typedArray.getColor(
                 com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
-
     }
 
     public SuggestionSpan(Parcel src) {
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7cf4579..366abd3 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -134,6 +134,7 @@
                 if (i != o) {
                     keys[o] = keys[i];
                     values[o] = val;
+                    values[i] = null;
                 }
 
                 o++;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d948ec2..4ca299f 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -737,8 +737,21 @@
         // Shaders are ignored when drawing bitmaps
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         final int nativePaint = paint == null ? 0 : paint.mNativePaint;
-        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, src.left, src.top, src.right,
-                src.bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint);
+
+        float left, top, right, bottom;
+        if (src == null) {
+            left = top = 0;
+            right = bitmap.getWidth();
+            bottom = bitmap.getHeight();
+        } else {
+            left = src.left;
+            right = src.right;
+            top = src.top;
+            bottom = src.bottom;
+        }
+
+        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
         if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
     }
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 8e39d6e..ccb6489 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -162,13 +162,21 @@
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
-     * Destoys the layers used by the specified view hierarchy.
+     * Destroys the layers used by the specified view hierarchy.
      * 
      * @param view The root of the view hierarchy
      */
     abstract void destroyLayers(View view);
 
     /**
+     * Destroys all hardware rendering resources associated with the specified
+     * view hierarchy.
+     * 
+     * @param view The root of the view hierarchy
+     */
+    abstract void destroyHardwareResources(View view);
+    
+    /**
      * This method should be invoked whenever the current hardware renderer
      * context should be reset.
      * 
@@ -211,6 +219,13 @@
     abstract int getHeight();
 
     /**
+     * Gets the current canvas associated with this HardwareRenderer.
+     *
+     * @return the current HardwareCanvas
+     */
+    abstract HardwareCanvas getCanvas();
+
+    /**
      * Sets the directory to use as a persistent storage for hardware rendering
      * resources.
      * 
@@ -348,15 +363,6 @@
     }
 
     /**
-     * Invoke this method when the system needs to clean up all resources
-     * associated with hardware rendering.
-     */
-    static void terminate() {
-        Log.d(LOG_TAG, "Terminating hardware rendering");
-        Gl20Renderer.terminate();
-    }    
-    
-    /**
      * Indicates whether hardware acceleration is currently enabled.
      * 
      * @return True if hardware acceleration is in use, false otherwise.
@@ -412,8 +418,8 @@
         static final Object[] sEglLock = new Object[0];
         int mWidth = -1, mHeight = -1;
 
-        static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage
-                = new ThreadLocal<Gl20Renderer.MyEGLContext>();
+        static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
+                = new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
 
         EGLContext mEglContext;
         Thread mEglThread;
@@ -565,13 +571,13 @@
                 }
             }
 
-            Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
+            Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get();
             mEglContext = managedContext != null ? managedContext.getContext() : null;
             mEglThread = Thread.currentThread();
 
             if (mEglContext == null) {
                 mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
-                sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext));
+                sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext));
             }
         }
 
@@ -784,6 +790,11 @@
             return mHeight;
         }
 
+        @Override
+        HardwareCanvas getCanvas() {
+            return mCanvas;
+        }
+
         boolean canDraw() {
             return mGl != null && mCanvas != null;
         }        
@@ -909,10 +920,10 @@
         private static EGLSurface sPbuffer;
         private static final Object[] sPbufferLock = new Object[0];
 
-        static class MyEGLContext extends ManagedEGLContext {
+        static class Gl20RendererEglContext extends ManagedEGLContext {
             final Handler mHandler = new Handler();
 
-            public MyEGLContext(EGLContext context) {
+            public Gl20RendererEglContext(EGLContext context) {
                 super(context);
             }
 
@@ -939,7 +950,8 @@
                         sEglContextStorage.remove();
 
                         sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
-                        sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+                        sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+                                EGL_NO_SURFACE, EGL_NO_CONTEXT);
 
                         sEgl.eglReleaseThread();
                         sEgl.eglTerminate(sEglDisplay);
@@ -1046,10 +1058,9 @@
             }
         }
 
-        private void destroyHardwareLayer(View view) {
-            if (view.destroyLayer()) {
-                view.invalidate(true);
-            }
+        private static void destroyHardwareLayer(View view) {
+            view.destroyLayer();
+
             if (view instanceof ViewGroup) {
                 ViewGroup group = (ViewGroup) view;
 
@@ -1059,6 +1070,36 @@
                 }
             }
         }
+        
+        @Override
+        void destroyHardwareResources(View view) {
+            if (view != null) {
+                boolean needsContext = true;
+                if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+
+                if (needsContext) {
+                    Gl20RendererEglContext managedContext = sEglContextStorage.get();
+                    if (managedContext == null) return;
+                    usePbufferSurface(managedContext.getContext());
+                }
+
+                destroyResources(view);
+                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+            }
+        }
+        
+        private static void destroyResources(View view) {
+            view.destroyHardwareResources();
+
+            if (view instanceof ViewGroup) {
+                ViewGroup group = (ViewGroup) view;
+
+                int count = group.getChildCount();
+                for (int i = 0; i < count; i++) {
+                    destroyResources(group.getChildAt(i));
+                }
+            }
+        }
 
         static HardwareRenderer create(boolean translucent) {
             if (GLES20Canvas.isAvailable()) {
@@ -1070,7 +1111,7 @@
         static void trimMemory(int level) {
             if (sEgl == null || sEglConfig == null) return;
 
-            Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
+            Gl20RendererEglContext managedContext = sEglContextStorage.get();
             // We do not have OpenGL objects
             if (managedContext == null) {
                 return;
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 282d7be..53d6e1f 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -54,9 +54,8 @@
      * @param requestedWidth The width the window wants to be.
      * @param requestedHeight The height the window wants to be.
      * @param viewVisibility Window root view's visibility.
-     * @param insetsPending Set to true if the client will be later giving
-     * internal insets; as a result, the window will not impact other window
-     * layouts until the insets are given.
+     * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING},
+     * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}.
      * @param outFrame Rect in which is placed the new position/size on
      * screen.
      * @param outContentInsets Rect in which is placed the offsets from
@@ -80,11 +79,17 @@
      */
     int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewVisibility,
-            boolean insetsPending, out Rect outFrame, out Rect outContentInsets,
+            int flags, out Rect outFrame, out Rect outContentInsets,
             out Rect outVisibleInsets, out Configuration outConfig,
             out Surface outSurface);
 
     /**
+     * If a call to relayout() asked to have the surface destroy deferred,
+     * it must call this once it is okay to destroy that surface.
+     */
+    void performDeferredDestroy(IWindow window);
+
+    /**
      * Called by a client to report that it ran out of graphics memory.
      */
     boolean outOfMemory(IWindow window);
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 6c3d387..f53e42c 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -579,8 +579,20 @@
     /** Key code constant: 3D Mode key.
      * Toggles the display between 2D and 3D mode. */
     public static final int KEYCODE_3D_MODE         = 206;
+    /** Key code constant: Contacts special function key.
+     * Used to launch an address book application. */
+    public static final int KEYCODE_CONTACTS        = 207;
+    /** Key code constant: Calendar special function key.
+     * Used to launch a calendar application. */
+    public static final int KEYCODE_CALENDAR        = 208;
+    /** Key code constant: Music special function key.
+     * Used to launch a music player application. */
+    public static final int KEYCODE_MUSIC           = 209;
+    /** Key code constant: Calculator special function key.
+     * Used to launch a calculator application. */
+    public static final int KEYCODE_CALCULATOR      = 210;
 
-    private static final int LAST_KEYCODE           = KEYCODE_BUTTON_16;
+    private static final int LAST_KEYCODE           = KEYCODE_CALCULATOR;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -589,6 +601,8 @@
     //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
     //  frameworks/base/core/res/res/values/attrs.xml
     //  emulator?
+    //  LAST_KEYCODE
+    //  KEYCODE_SYMBOLIC_NAMES
     //
     //  Also Android currently does not reserve code ranges for vendor-
     //  specific key codes.  If you have new key codes to have, you
@@ -807,6 +821,10 @@
         names.append(KEYCODE_LANGUAGE_SWITCH, "KEYCODE_LANGUAGE_SWITCH");
         names.append(KEYCODE_MANNER_MODE, "KEYCODE_MANNER_MODE");
         names.append(KEYCODE_3D_MODE, "KEYCODE_3D_MODE");
+        names.append(KEYCODE_CONTACTS, "KEYCODE_CONTACTS");
+        names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR");
+        names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC");
+        names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR");
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 2b254af..edaa262 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -282,10 +282,24 @@
     /**
      * Copy another surface to this one.  This surface now holds a reference
      * to the same data as the original surface, and is -not- the owner.
+     * This is for use by the window manager when returning a window surface
+     * back from a client, converting it from the representation being managed
+     * by the window manager to the representation the client uses to draw
+     * in to it.
      * @hide
      */
     public native void copyFrom(Surface o);
-    
+
+    /**
+     * Transfer the native state from 'o' to this surface, releasing it
+     * from 'o'.  This is for use in the client side for drawing into a
+     * surface; not guaranteed to work on the window manager side.
+     * This is for use by the client to move the underlying surface from
+     * one Surface object to another, in particular in SurfaceFlinger.
+     * @hide.
+     */
+    public native void transferFrom(Surface o);
+
     /** @hide */
     public int getGenerationId() {
         return mSurfaceGenerationId;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9a57ea0..6726c56e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import android.util.DisplayMetrics;
 import com.android.internal.view.BaseIWindow;
 
 import android.content.Context;
@@ -82,7 +81,6 @@
 public class SurfaceView extends View {
     static private final String TAG = "SurfaceView";
     static private final boolean DEBUG = false;
-    static private final boolean localLOGV = DEBUG ? true : false;
 
     final ArrayList<SurfaceHolder.Callback> mCallbacks
             = new ArrayList<SurfaceHolder.Callback>();
@@ -90,7 +88,8 @@
     final int[] mLocation = new int[2];
     
     final ReentrantLock mSurfaceLock = new ReentrantLock();
-    final Surface mSurface = new Surface();
+    final Surface mSurface = new Surface();       // Current surface in use
+    final Surface mNewSurface = new Surface();    // New surface we are switching to
     boolean mDrawingStopped = true;
 
     final WindowManager.LayoutParams mLayout
@@ -145,8 +144,7 @@
     int mRequestedFormat = PixelFormat.RGB_565;
 
     boolean mHaveFrame = false;
-    boolean mDestroyReportNeeded = false;
-    boolean mNewSurfaceNeeded = false;
+    boolean mSurfaceCreated = false;
     long mLastLockTime = 0;
     
     boolean mVisible = false;
@@ -236,46 +234,6 @@
         updateWindow(false, false);
     }
 
-    /**
-     * This method is not intended for general use. It was created
-     * temporarily to improve performance of 3D layers in Launcher
-     * and should be removed and fixed properly.
-     * 
-     * Do not call this method. Ever.
-     * 
-     * @hide
-     */
-    protected void showSurface() {
-        if (mSession != null) {
-            updateWindow(true, false);
-        }
-    }
-
-    /**
-     * This method is not intended for general use. It was created
-     * temporarily to improve performance of 3D layers in Launcher
-     * and should be removed and fixed properly.
-     * 
-     * Do not call this method. Ever.
-     * 
-     * @hide
-     */
-    protected void hideSurface() {
-        if (mSession != null && mWindow != null) {
-            mSurfaceLock.lock();
-            try {
-                DisplayMetrics metrics = getResources().getDisplayMetrics();
-                mLayout.x = metrics.widthPixels * 3;
-                mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, VISIBLE, false,
-                        mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mSurface);
-            } catch (RemoteException e) {
-                // Ignore
-            } finally {
-                mSurfaceLock.unlock();
-            }
-        }
-    }
-    
     @Override
     protected void onDetachedFromWindow() {
         if (mGlobalListenersAdded) {
@@ -444,14 +402,13 @@
         final boolean creating = mWindow == null;
         final boolean formatChanged = mFormat != mRequestedFormat;
         final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
-        final boolean visibleChanged = mVisible != mRequestedVisible
-                || mNewSurfaceNeeded;
+        final boolean visibleChanged = mVisible != mRequestedVisible;
 
         if (force || creating || formatChanged || sizeChanged || visibleChanged
             || mLeft != mLocation[0] || mTop != mLocation[1]
             || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
 
-            if (localLOGV) Log.i(TAG, "Changes: creating=" + creating
+            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                     + " format=" + formatChanged + " size=" + sizeChanged
                     + " visible=" + visibleChanged
                     + " left=" + (mLeft != mLocation[0])
@@ -496,15 +453,11 @@
                             mVisible ? VISIBLE : GONE, mContentInsets);
                 }
                 
-                if (visibleChanged && (!visible || mNewSurfaceNeeded)) {
-                    reportSurfaceDestroyed();
-                }
-
-                mNewSurfaceNeeded = false;
-                
                 boolean realSizeChanged;
                 boolean reportDrawNeeded;
-                
+
+                int relayoutResult;
+
                 mSurfaceLock.lock();
                 try {
                     mUpdateWindowNeeded = false;
@@ -512,17 +465,21 @@
                     mReportDrawNeeded = false;
                     mDrawingStopped = !visible;
     
-                    final int relayoutResult = mSession.relayout(
+                    if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
+
+                    relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
-                            visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
-                            mVisibleInsets, mConfiguration, mSurface);
-                    if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+                            visible ? VISIBLE : GONE,
+                            WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+                            mWinFrame, mContentInsets,
+                            mVisibleInsets, mConfiguration, mNewSurface);
+                    if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
                         mReportDrawNeeded = true;
                     }
-                    
-                    if (localLOGV) Log.i(TAG, "New surface: " + mSurface
+
+                    if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
                             + ", vis=" + visible + ", frame=" + mWinFrame);
-                    
+
                     mSurfaceFrame.left = 0;
                     mSurfaceFrame.top = 0;
                     if (mTranslator == null) {
@@ -547,28 +504,51 @@
                 try {
                     redrawNeeded |= creating | reportDrawNeeded;
 
-                    if (visible) {
-                        mDestroyReportNeeded = true;
+                    SurfaceHolder.Callback callbacks[] = null;
 
-                        SurfaceHolder.Callback callbacks[];
-                        synchronized (mCallbacks) {
-                            callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
-                            mCallbacks.toArray(callbacks);
+                    final boolean surfaceChanged =
+                            (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+                    if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
+                        mSurfaceCreated = false;
+                        if (mSurface.isValid()) {
+                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
+                            callbacks = getSurfaceCallbacks();
+                            for (SurfaceHolder.Callback c : callbacks) {
+                                c.surfaceDestroyed(mSurfaceHolder);
+                            }
                         }
+                    }
 
-                        if (visibleChanged) {
+                    mSurface.transferFrom(mNewSurface);
+
+                    if (visible) {
+                        if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
+                            mSurfaceCreated = true;
                             mIsCreating = true;
+                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
+                            if (callbacks == null) {
+                                callbacks = getSurfaceCallbacks();
+                            }
                             for (SurfaceHolder.Callback c : callbacks) {
                                 c.surfaceCreated(mSurfaceHolder);
                             }
                         }
                         if (creating || formatChanged || sizeChanged
                                 || visibleChanged || realSizeChanged) {
+                            if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
+                                    + " w=" + myWidth + " h=" + myHeight);
+                            if (callbacks == null) {
+                                callbacks = getSurfaceCallbacks();
+                            }
                             for (SurfaceHolder.Callback c : callbacks) {
                                 c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
                             }
                         }
                         if (redrawNeeded) {
+                            if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
+                            if (callbacks == null) {
+                                callbacks = getSurfaceCallbacks();
+                            }
                             for (SurfaceHolder.Callback c : callbacks) {
                                 if (c instanceof SurfaceHolder.Callback2) {
                                     ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
@@ -576,41 +556,34 @@
                                 }
                             }
                         }
-                    } else {
-                        mSurface.release();
                     }
                 } finally {
                     mIsCreating = false;
                     if (redrawNeeded) {
+                        if (DEBUG) Log.i(TAG, "finishedDrawing");
                         mSession.finishDrawing(mWindow);
                     }
+                    mSession.performDeferredDestroy(mWindow);
                 }
             } catch (RemoteException ex) {
             }
-            if (localLOGV) Log.v(
+            if (DEBUG) Log.v(
                 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                 " w=" + mLayout.width + " h=" + mLayout.height +
                 ", frame=" + mSurfaceFrame);
         }
     }
 
-    private void reportSurfaceDestroyed() {
-        if (mDestroyReportNeeded) {
-            mDestroyReportNeeded = false;
-            SurfaceHolder.Callback callbacks[];
-            synchronized (mCallbacks) {
-                callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
-                mCallbacks.toArray(callbacks);
-            }            
-            for (SurfaceHolder.Callback c : callbacks) {
-                c.surfaceDestroyed(mSurfaceHolder);
-            }
+    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
+        SurfaceHolder.Callback callbacks[];
+        synchronized (mCallbacks) {
+            callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
+            mCallbacks.toArray(callbacks);
         }
-        super.onDetachedFromWindow();
+        return callbacks;
     }
 
     void handleGetNewSurface() {
-        mNewSurfaceNeeded = true;
         updateWindow(false, false);
     }
 
@@ -636,7 +609,7 @@
                 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
             SurfaceView surfaceView = mSurfaceView.get();
             if (surfaceView != null) {
-                if (localLOGV) Log.v(
+                if (DEBUG) Log.v(
                         "SurfaceView", surfaceView + " got resized: w=" +
                                 w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                 surfaceView.mSurfaceLock.lock();
@@ -754,7 +727,7 @@
         private final Canvas internalLockCanvas(Rect dirty) {
             mSurfaceLock.lock();
 
-            if (localLOGV) Log.i(TAG, "Locking canvas... stopped="
+            if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
                     + mDrawingStopped + ", win=" + mWindow);
 
             Canvas c = null;
@@ -774,7 +747,7 @@
                 }
             }
 
-            if (localLOGV) Log.i(TAG, "Returned canvas: " + c);
+            if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
             if (c != null) {
                 mLastLockTime = SystemClock.uptimeMillis();
                 return c;
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 1697382..74916f0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -203,7 +203,10 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        destroySurface();
+    }
 
+    private void destroySurface() {
         if (mLayer != null) {
             boolean shouldRelease = true;
             if (mListener != null) {
@@ -300,6 +303,17 @@
         return false;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    protected void destroyHardwareResources() {
+        super.destroyHardwareResources();
+        destroySurface();
+        invalidateParentCaches();
+        invalidate(true);
+    }
+
     @Override
     HardwareLayer getHardwareLayer() {
         if (mLayer == null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index dc46d42..54bb056 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1487,7 +1487,8 @@
             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
-            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;
+            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
+            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
 
     /**
      * Temporary Rect currently for use in setBackground().  This will probably
@@ -8058,9 +8059,9 @@
     /**
      * If some part of this view is not clipped by any of its parents, then
      * return that area in r in global (root) coordinates. To convert r to local
-     * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
-     * -globalOffset.y)) If the view is completely clipped or translated out,
-     * return false.
+     * coordinates (without taking possible View rotations into account), offset
+     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
+     * If the view is completely clipped or translated out, return false.
      *
      * @param r If true is returned, r holds the global coordinates of the
      *        visible portion of this view.
@@ -10072,7 +10073,7 @@
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
                 destroyLayer();
-                // fall through - unaccelerated views may use software layer mechanism instead
+                // fall through - non-accelerated views may use software layer mechanism instead
             case LAYER_TYPE_SOFTWARE:
                 destroyDrawingCache();
                 break;
@@ -10139,7 +10140,11 @@
 
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
-                getHardwareLayer();
+                if (mAttachInfo.mHardwareRenderer != null &&
+                        mAttachInfo.mHardwareRenderer.isEnabled() &&
+                        mAttachInfo.mHardwareRenderer.validate()) {
+                    getHardwareLayer();
+                }
                 break;
             case LAYER_TYPE_SOFTWARE:
                 buildDrawingCache(true);
@@ -10234,12 +10239,31 @@
         if (mHardwareLayer != null) {
             mHardwareLayer.destroy();
             mHardwareLayer = null;
+
+            invalidate(true);
+            invalidateParentCaches();
+
             return true;
         }
         return false;
     }
 
     /**
+     * Destroys all hardware rendering resources. This method is invoked
+     * when the system needs to reclaim resources. Upon execution of this
+     * method, you should free any OpenGL resources created by the view.
+     * 
+     * Note: you <strong>must</strong> call
+     * <code>super.destroyHardwareResources()</code> when overriding
+     * this method.
+     * 
+     * @hide
+     */
+    protected void destroyHardwareResources() {
+        destroyLayer();
+    }
+
+    /**
      * <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
      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
@@ -12128,35 +12152,48 @@
      * @param location an array of two integers in which to hold the coordinates
      */
     public void getLocationInWindow(int[] location) {
+        // When the view is not attached to a window, this method does not make sense
+        if (mAttachInfo == null) return;
+
         if (location == null || location.length < 2) {
-            throw new IllegalArgumentException("location must be an array of "
-                    + "two integers");
+            throw new IllegalArgumentException("location must be an array of two integers");
         }
 
-        location[0] = mLeft;
-        location[1] = mTop;
-        if (mTransformationInfo != null) {
-            location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f);
-            location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f);
+        float[] position = mAttachInfo.mTmpTransformLocation;
+        position[0] = position[1] = 0.0f;
+
+        if (!hasIdentityMatrix()) {
+            getMatrix().mapPoints(position);
         }
 
+        position[0] += mLeft;
+        position[1] += mTop;
+
         ViewParent viewParent = mParent;
         while (viewParent instanceof View) {
-            final View view = (View)viewParent;
-            location[0] += view.mLeft - view.mScrollX;
-            location[1] += view.mTop - view.mScrollY;
-            if (view.mTransformationInfo != null) {
-                location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f);
-                location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f);
+            final View view = (View) viewParent;
+
+            position[0] -= view.mScrollX;
+            position[1] -= view.mScrollY;
+
+            if (!view.hasIdentityMatrix()) {
+                view.getMatrix().mapPoints(position);
             }
+
+            position[0] += view.mLeft;
+            position[1] += view.mTop;
+
             viewParent = view.mParent;
         }
 
         if (viewParent instanceof ViewRootImpl) {
             // *cough*
-            final ViewRootImpl vr = (ViewRootImpl)viewParent;
-            location[1] -= vr.mCurScrollY;
+            final ViewRootImpl vr = (ViewRootImpl) viewParent;
+            position[1] -= vr.mCurScrollY;
         }
+
+        location[0] = (int) (position[0] + 0.5f);
+        location[1] = (int) (position[1] + 0.5f);
     }
 
     /**
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 3441f7e..9bd42ef 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -139,13 +139,29 @@
     private static final int EDGE_SLOP = 12;
     
     /**
-     * Distance a touch can wander before we think the user is scrolling in pixels
+     * Distance a touch can wander before we think the user is scrolling in dips.
+     * Note that this value defined here is only used as a fallback by legacy/misbehaving
+     * applications that do not provide a Context for determining density/configuration-dependent
+     * values.
+     *
+     * To alter this value, see the configuration resource config_viewConfigurationTouchSlop
+     * in frameworks/base/core/res/res/values/config.xml or the appropriate device resource overlay.
+     * It may be appropriate to tweak this on a device-specific basis in an overlay based on
+     * the characteristics of the touch panel and firmware.
      */
-    private static final int TOUCH_SLOP = 16;
+    private static final int TOUCH_SLOP = 8;
     
     /**
      * Distance a touch can wander before we think the user is attempting a paged scroll
      * (in dips)
+     *
+     * Note that this value defined here is only used as a fallback by legacy/misbehaving
+     * applications that do not provide a Context for determining density/configuration-dependent
+     * values.
+     *
+     * See the note above on {@link #TOUCH_SLOP} regarding the dimen resource
+     * config_viewConfigurationTouchSlop. ViewConfiguration will report a paging touch slop of
+     * config_viewConfigurationTouchSlop * 2 when provided with a Context.
      */
     private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
     
@@ -277,8 +293,6 @@
         mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f);
         mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f);
         mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
-        mTouchSlop = (int) (sizeAndDensity * TOUCH_SLOP + 0.5f);
-        mPagingTouchSlop = (int) (sizeAndDensity * PAGING_TOUCH_SLOP + 0.5f);
         mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
         mScaledTouchExplorationTapSlop = (int) (density * TOUCH_EXPLORATION_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
@@ -301,6 +315,9 @@
 
         mFadingMarqueeEnabled = res.getBoolean(
                 com.android.internal.R.bool.config_ui_enableFadingMarquee);
+        mTouchSlop = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_viewConfigurationTouchSlop);
+        mPagingTouchSlop = mTouchSlop * 2;
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e366e72..600bfe6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -79,7 +79,7 @@
 public abstract class ViewGroup extends View implements ViewParent, ViewManager {
 
     private static final boolean DBG = false;
-    
+
     /**
      * Views which have been hidden or removed which need to be animated on
      * their way out.
@@ -2719,13 +2719,6 @@
             return more;
         }
 
-        float alpha = child.getAlpha();
-        // Bail out early if the view does not need to be drawn
-        if (alpha <= ViewConfiguration.ALPHA_THRESHOLD && (child.mPrivateFlags & ALPHA_SET) == 0 &&
-                !(child instanceof SurfaceView)) {
-            return more;
-        }
-
         if (hardwareAccelerated) {
             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
             // retain the flag's value temporarily in the mRecreateDisplayList flag
@@ -2779,6 +2772,7 @@
             }
         }
 
+        float alpha = child.getAlpha();
         if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
             if (transformToApply != null || !childHasIdentityMatrix) {
                 int transX = 0;
@@ -4182,15 +4176,42 @@
      * {@inheritDoc}
      */
     public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
+        // The View is not attached to a window, 'visible' does not make sense, return false
+        if (mAttachInfo == null) return false;
+
+        final RectF rect = mAttachInfo.mTmpTransformRect;
+        rect.set(r);
+
+        if (!child.hasIdentityMatrix()) {
+           child.getMatrix().mapRect(rect);
+        }
+
         int dx = child.mLeft - mScrollX;
         int dy = child.mTop - mScrollY;
+
+        rect.offset(dx, dy);
+
         if (offset != null) {
+            if (!child.hasIdentityMatrix()) {
+                float[] position = mAttachInfo.mTmpTransformLocation;
+                position[0] = offset.x;
+                position[1] = offset.y;
+                child.getMatrix().mapPoints(position);
+                offset.x = (int) (position[0] + 0.5f);
+                offset.y = (int) (position[1] + 0.5f);
+            }
             offset.x += dx;
             offset.y += dy;
         }
-        r.offset(dx, dy);
-        return r.intersect(0, 0, mRight - mLeft, mBottom - mTop) &&
-               (mParent == null || mParent.getChildVisibleRect(this, r, offset));
+
+        if (rect.intersect(0, 0, mRight - mLeft, mBottom - mTop)) {
+            if (mParent == null) return true;
+            r.set((int) (rect.left + 0.5f), (int) (rect.top + 0.5f),
+                    (int) (rect.right + 0.5f), (int) (rect.bottom + 0.5f));
+            return mParent.getChildVisibleRect(this, r, offset);
+        }
+
+        return false;
     }
 
     /**
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 655df39..873d4bb 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -63,16 +63,16 @@
     /**
      * All or part of a child is dirty and needs to be redrawn.
      *
-     * The location array is an array of two int values which respectively
-     * define the left and the top position of the dirty child.
+     * <p>The location array is an array of two int values which respectively
+     * define the left and the top position of the dirty child.</p>
      *
-     * This method must return the parent of this ViewParent if the specified
+     * <p>This method must return the parent of this ViewParent if the specified
      * rectangle must be invalidated in the parent. If the specified rectangle
      * does not require invalidation in the parent or if the parent does not
-     * exist, this method must return null.
+     * exist, this method must return null.</p>
      *
-     * When this method returns a non-null value, the location array must
-     * have been updated with the left and top coordinates of this ViewParent.
+     * <p>When this method returns a non-null value, the location array must
+     * have been updated with the left and top coordinates of this ViewParent.</p>
      *
      * @param location An array of 2 ints containing the left and top
      *        coordinates of the child to invalidate
@@ -115,6 +115,26 @@
      */
     public void clearChildFocus(View child);
 
+    /**
+     * Compute the visible part of a rectangular region defined in terms of a child view's
+     * coordinates.
+     *
+     * <p>Returns the clipped visible part of the rectangle <code>r</code>, defined in the
+     * <code>child</code>'s local coordinate system. <code>r</code> is modified by this method to
+     * contain the result, expressed in the global (root) coordinate system.</p>
+     *
+     * <p>The resulting rectangle is always axis aligned. If a rotation is applied to a node in the
+     * View hierarchy, the result is the axis-aligned bounding box of the visible rectangle.</p>
+     *
+     * @param child A child View, whose rectangular visible region we want to compute
+     * @param r The input rectangle, defined in the child coordinate system. Will be overwritten to
+     * contain the resulting visible rectangle, expressed in global (root) coordinates
+     * @param offset The input coordinates of a point, defined in the child coordinate system.
+     * As with the <code>r</code> parameter, this will be overwritten to contain the global (root)
+     * coordinates of that point.
+     * A <code>null</code> value is valid (in case you are not interested in this result)
+     * @return true if the resulting rectangle is not empty, false otherwise
+     */
     public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset);
 
     /**
@@ -143,11 +163,11 @@
 
     /**
      * Bring up a context menu for the specified view or its ancestors.
-     * <p>
-     * In most cases, a subclass does not need to override this.  However, if
+     *
+     * <p>In most cases, a subclass does not need to override this.  However, if
      * the subclass is added directly to the window manager (for example,
      * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
-     * then it should override this and show the context menu.
+     * then it should override this and show the context menu.</p>
      * 
      * @param originalView The source view where the context menu was first invoked
      * @return true if a context menu was displayed
@@ -164,11 +184,11 @@
 
     /**
      * Start an action mode for the specified view.
-     * <p>
-     * In most cases, a subclass does not need to override this. However, if the
+     *
+     * <p>In most cases, a subclass does not need to override this. However, if the
      * subclass is added directly to the window manager (for example,
      * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
-     * then it should override this and start the action mode.
+     * then it should override this and start the action mode.</p>
      *
      * @param originalView The source view where the action mode was first invoked
      * @param callback The callback that will handle lifecycle events for the action mode
@@ -188,10 +208,10 @@
      * Called when a child does not want this parent and its ancestors to
      * intercept touch events with
      * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
-     * <p>
-     * This parent should pass this call onto its parents. This parent must obey
+     *
+     * <p>This parent should pass this call onto its parents. This parent must obey
      * this request for the duration of the touch (that is, only clear the flag
-     * after this parent has received an up or a cancel.
+     * after this parent has received an up or a cancel.</p>
      * 
      * @param disallowIntercept True if the child does not want the parent to
      *            intercept touch events.
@@ -234,7 +254,7 @@
      *       the sending. The parent can optionally add a record for itself before
      *       dispatching the request to its parent. A parent can also choose not to
      *       respect the request for sending the event. The accessibility event is sent
-     *       by the topmost view in the view tree.
+     *       by the topmost view in the view tree.</p>
      *
      * @param child The child which requests sending the event.
      * @param event The event to be sent.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b15b155..6c982eb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -576,6 +576,13 @@
         }
     }
 
+    void terminateHardwareResources() {
+        if (mAttachInfo.mHardwareRenderer != null) {
+            mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
+            mAttachInfo.mHardwareRenderer.destroy(false);
+        }
+    }
+
     void destroyHardwareLayers() {
         if (mThread != Thread.currentThread()) {
             if (mAttachInfo.mHardwareRenderer != null &&
@@ -1209,7 +1216,8 @@
                         disposeResizeBuffer();
 
                         boolean completed = false;
-                        HardwareCanvas canvas = null;
+                        HardwareCanvas hwRendererCanvas = mAttachInfo.mHardwareRenderer.getCanvas();
+                        HardwareCanvas layerCanvas = null;
                         try {
                             if (mResizeBuffer == null) {
                                 mResizeBuffer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
@@ -1218,12 +1226,12 @@
                                     mResizeBuffer.getHeight() != mHeight) {
                                 mResizeBuffer.resize(mWidth, mHeight);
                             }
-                            canvas = mResizeBuffer.start(mAttachInfo.mHardwareCanvas);
-                            canvas.setViewport(mWidth, mHeight);
-                            canvas.onPreDraw(null);
-                            final int restoreCount = canvas.save();
+                            layerCanvas = mResizeBuffer.start(hwRendererCanvas);
+                            layerCanvas.setViewport(mWidth, mHeight);
+                            layerCanvas.onPreDraw(null);
+                            final int restoreCount = layerCanvas.save();
                             
-                            canvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
+                            layerCanvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
 
                             int yoff;
                             final boolean scrolling = mScroller != null
@@ -1235,27 +1243,27 @@
                                 yoff = mScrollY;
                             }
 
-                            canvas.translate(0, -yoff);
+                            layerCanvas.translate(0, -yoff);
                             if (mTranslator != null) {
-                                mTranslator.translateCanvas(canvas);
+                                mTranslator.translateCanvas(layerCanvas);
                             }
 
-                            mView.draw(canvas);
+                            mView.draw(layerCanvas);
 
                             mResizeBufferStartTime = SystemClock.uptimeMillis();
                             mResizeBufferDuration = mView.getResources().getInteger(
                                     com.android.internal.R.integer.config_mediumAnimTime);
                             completed = true;
 
-                            canvas.restoreToCount(restoreCount);
+                            layerCanvas.restoreToCount(restoreCount);
                         } catch (OutOfMemoryError e) {
                             Log.w(TAG, "Not enough memory for content change anim buffer", e);
                         } finally {
-                            if (canvas != null) {
-                                canvas.onPostDraw();
+                            if (layerCanvas != null) {
+                                layerCanvas.onPostDraw();
                             }
                             if (mResizeBuffer != null) {
-                                mResizeBuffer.end(mAttachInfo.mHardwareCanvas);
+                                mResizeBuffer.end(hwRendererCanvas);
                                 if (!completed) {
                                     mResizeBuffer.destroy();
                                     mResizeBuffer = null;
@@ -1418,7 +1426,7 @@
 
             if (!mStopped) {
                 boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
-                        (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
+                        (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
                 if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                         || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
                     childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1629,7 +1637,7 @@
                 mLastDrawDurationNanos = System.nanoTime() - drawStartTime;
             }
 
-            if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0
+            if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0
                     || mReportNextDraw) {
                 if (LOCAL_LOGV) {
                     Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
@@ -1662,7 +1670,7 @@
             }
             // We were supposed to report when we are done drawing. Since we canceled the
             // draw, remember it here.
-            if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+            if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
                 mReportNextDraw = true;
             }
             if (fullRedrawNeeded) {
@@ -3322,8 +3330,9 @@
         }
 
         // If the Control modifier is held, try to interpret the key as a shortcut.
-        if (event.getAction() == KeyEvent.ACTION_UP
+        if (event.getAction() == KeyEvent.ACTION_DOWN
                 && event.isCtrlPressed()
+                && event.getRepeatCount() == 0
                 && !KeyEvent.isModifierKey(event.getKeyCode())) {
             if (mView.dispatchKeyShortcutEvent(event)) {
                 finishKeyEvent(event, sendDone, true);
@@ -3578,8 +3587,8 @@
                 mWindow, mSeq, params,
                 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                 (int) (mView.getMeasuredHeight() * appScale + 0.5f),
-                viewVisibility, insetsPending, mWinFrame,
-                mPendingContentInsets, mPendingVisibleInsets,
+                viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
+                mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingConfiguration, mSurface);
         //Log.d(TAG, "<<<<<< BACK FROM relayout");
         if (restore) {
@@ -3709,7 +3718,7 @@
                     // animation info.
                     try {
                         if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
-                                & WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+                                & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
                             sWindowSession.finishDrawing(mWindow);
                         }
                     } catch (RemoteException e) {
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index b657204..48fe0df 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -278,10 +278,6 @@
     }
 
     private void createSliders() {
-        final int silentableStreams = System.getInt(mContext.getContentResolver(),
-                System.MODE_RINGER_STREAMS_AFFECTED,
-                ((1 << AudioSystem.STREAM_NOTIFICATION) | (1 << AudioSystem.STREAM_RING)));
-
         LayoutInflater inflater = (LayoutInflater) mContext
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length);
@@ -297,9 +293,6 @@
             sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
             sc.group.setTag(sc);
             sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon);
-            if ((silentableStreams & (1 << sc.streamType)) != 0) {
-                sc.icon.setOnClickListener(this);
-            }
             sc.icon.setTag(sc);
             sc.icon.setContentDescription(res.getString(streamRes.descRes));
             sc.iconRes = streamRes.iconRes;
@@ -356,7 +349,6 @@
                 && mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
             sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate);
         }
-        sc.seekbarView.setEnabled(!muted);
     }
 
     private boolean isExpanded() {
@@ -436,8 +428,6 @@
                 mAudioService.getLastAudibleStreamVolume(streamType)
                 : mAudioService.getStreamVolume(streamType);
 
-//        int message = UNKNOWN_VOLUME_TEXT;
-//        int additionalMessage = 0;
         mRingIsSilent = false;
 
         if (LOGD) {
@@ -697,18 +687,6 @@
     public void onClick(View v) {
         if (v == mMoreButton) {
             expand();
-        } else if (v.getTag() instanceof StreamControl) {
-            StreamControl sc = (StreamControl) v.getTag();
-            boolean vibeInSilent = Settings.System.getInt(mContext.getContentResolver(),
-                    System.VIBRATE_IN_SILENT, 1) == 1;
-            int newMode = mAudioManager.isSilentMode()
-                    ? AudioManager.RINGER_MODE_NORMAL
-                    : (vibeInSilent
-                            ? AudioManager.RINGER_MODE_VIBRATE 
-                            : AudioManager.RINGER_MODE_SILENT);
-            mAudioManager.setRingerMode(newMode);
-            // Expand the dialog if it hasn't been expanded yet.
-            if (mShowCombinedVolumes && !isExpanded()) expand();
         }
         resetTimeout();
     }
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 660e3f4..d7113374 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -63,15 +63,34 @@
      * The user is navigating with keys (not the touch screen), so
      * navigational focus should be shown.
      */
-    public static final int RELAYOUT_IN_TOUCH_MODE = 0x1;
+    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
     /**
      * This is the first time the window is being drawn,
      * so the client must call drawingFinished() when done
      */
-    public static final int RELAYOUT_FIRST_TIME = 0x2;
-    
+    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+    /**
+     * The window manager has changed the surface from the last call.
+     */
+    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+    /**
+     * Flag for relayout: the client will be later giving
+     * internal insets; as a result, the window will not impact other window
+     * layouts until the insets are given.
+     */
+    public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+    /**
+     * Flag for relayout: the client may be currently using the current surface,
+     * so if it is to be destroyed as a part of the relayout the destroy must
+     * be deferred until later.  The client will call performDeferredDestroy()
+     * when it is okay.
+     */
+    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
     public static final int ADD_FLAG_APP_VISIBLE = 0x2;
-    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_IN_TOUCH_MODE;
+    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
     
     public static final int ADD_OKAY = 0;
     public static final int ADD_BAD_APP_TOKEN = -1;
@@ -425,7 +444,7 @@
                             if (mViews == null) return;
                             int count = mViews.length;
                             for (int i = 0; i < count; i++) {
-                                mRoots[i].destroyHardwareResources();
+                                mRoots[i].terminateHardwareResources();
                             }
                         }
                         // Terminate the hardware renderer to free all resources
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 86dd9df..91dcac8 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -16,7 +16,6 @@
 
 package android.view.accessibility;
 
-import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -220,15 +219,6 @@
  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
  * </ul>
- * <em>Note:</em> This event type is not dispatched to descendants though
- * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
- * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
- * source {@link android.view.View} and the sub-tree rooted at it will not receive
- * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
- * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
- * text content to such events is by setting the
- * {@link android.R.styleable#View_contentDescription contentDescription} of the source
- * view.</br>
  * </p>
  * <p>
  * <b>View scrolled</b> - represents the event of scrolling a view. If
@@ -599,24 +589,6 @@
     }
 
     /**
-     * Sets the connection for interacting with the AccessibilityManagerService.
-     *
-     * @param connection The connection.
-     *
-     * @hide
-     */
-    @Override
-    public void setConnection(IAccessibilityServiceConnection connection) {
-        super.setConnection(connection);
-        List<AccessibilityRecord> records = mRecords;
-        final int recordCount = records.size();
-        for (int i = 0; i < recordCount; i++) {
-            AccessibilityRecord record = records.get(i);
-            record.setConnection(connection);
-        }
-    }
-
-    /**
      * Sets if this instance is sealed.
      *
      * @param sealed Whether is sealed.
@@ -830,23 +802,19 @@
      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
      */
     public void initFromParcel(Parcel parcel) {
-        if (parcel.readInt() == 1) {
-            mConnection = IAccessibilityServiceConnection.Stub.asInterface(
-                    parcel.readStrongBinder());
-        }
-        setSealed(parcel.readInt() == 1);
+        mSealed = (parcel.readInt() == 1);
         mEventType = parcel.readInt();
         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
         mEventTime = parcel.readLong();
+        mConnectionId = parcel.readInt();
         readAccessibilityRecordFromParcel(this, parcel);
 
         // Read the records.
         final int recordCount = parcel.readInt();
         for (int i = 0; i < recordCount; i++) {
             AccessibilityRecord record = AccessibilityRecord.obtain();
-            // Do this to write the connection only once.
-            record.setConnection(mConnection);
             readAccessibilityRecordFromParcel(record, parcel);
+            record.mConnectionId = mConnectionId;
             mRecords.add(record);
         }
     }
@@ -884,16 +852,11 @@
      * {@inheritDoc}
      */
     public void writeToParcel(Parcel parcel, int flags) {
-        if (mConnection == null) {
-            parcel.writeInt(0);
-        } else {
-            parcel.writeInt(1);
-            parcel.writeStrongBinder(mConnection.asBinder());
-        }
         parcel.writeInt(isSealed() ? 1 : 0);
         parcel.writeInt(mEventType);
         TextUtils.writeToParcel(mPackageName, parcel, 0);
         parcel.writeLong(mEventTime);
+        parcel.writeInt(mConnectionId);
         writeAccessibilityRecordToParcel(this, parcel, flags);
 
         // Write the records.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 25b980b..96653e5 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -21,6 +21,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
 
 import java.util.Collections;
 import java.util.List;
@@ -61,6 +63,12 @@
 public final class AccessibilityInteractionClient
         extends IAccessibilityInteractionConnectionCallback.Stub {
 
+    public static final int NO_ID = -1;
+
+    private static final String LOG_TAG = "AccessibilityInteractionClient";
+
+    private static final boolean DEBUG = false;
+
     private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
 
     private static final Object sStaticLock = new Object();
@@ -83,6 +91,10 @@
 
     private final Rect mTempBounds = new Rect();
 
+    // The connection cache is shared between all interrogating threads.
+    private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
+        new SparseArray<IAccessibilityServiceConnection>();
+
     /**
      * @return The singleton of this class.
      */
@@ -111,28 +123,37 @@
     /**
      * Finds an {@link AccessibilityNodeInfo} by accessibility id.
      *
-     * @param connection A connection for interacting with the system.
+     * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id.
      * @param accessibilityViewId A unique View accessibility id.
      * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
      */
-    public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
-            IAccessibilityServiceConnection connection, int accessibilityWindowId,
-            int accessibilityViewId) {
+    public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
+            int accessibilityWindowId, int accessibilityViewId) {
         try {
-            final int interactionId = mInteractionIdCounter.getAndIncrement();
-            final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
-                    accessibilityWindowId, accessibilityViewId, interactionId, this,
-                    Thread.currentThread().getId());
-            // If the scale is zero the call has failed.
-            if (windowScale > 0) {
-                AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
-                        interactionId);
-                finalizeAccessibilityNodeInfo(info, connection, windowScale);
-                return info;
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
+                        accessibilityWindowId, accessibilityViewId, interactionId, this,
+                        Thread.currentThread().getId());
+                // If the scale is zero the call has failed.
+                if (windowScale > 0) {
+                    AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+                            interactionId);
+                    finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+                    return info;
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
             }
         } catch (RemoteException re) {
-            /* ignore */
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Error while calling remote"
+                        + " findAccessibilityNodeInfoByAccessibilityId", re);
+            }
         }
         return null;
     }
@@ -141,25 +162,36 @@
      * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
      * in the currently active window and starts from the root View in the window.
      *
-     * @param connection A connection for interacting with the system.
+     * @param connectionId The id of a connection for interacting with the system.
      * @param viewId The id of the view.
      * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
      */
-    public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(
-            IAccessibilityServiceConnection connection, int viewId) {
+    public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int connectionId,
+            int viewId) {
         try {
-            final int interactionId = mInteractionIdCounter.getAndIncrement();
-            final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(
-                    viewId, interactionId, this, Thread.currentThread().getId());
-            // If the scale is zero the call has failed.
-            if (windowScale > 0) {
-                AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
-                        interactionId);
-                finalizeAccessibilityNodeInfo(info, connection, windowScale);
-                return info;
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final float windowScale =
+                    connection.findAccessibilityNodeInfoByViewIdInActiveWindow(viewId,
+                            interactionId, this, Thread.currentThread().getId());
+                // If the scale is zero the call has failed.
+                if (windowScale > 0) {
+                    AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+                            interactionId);
+                    finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
+                    return info;
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
             }
         } catch (RemoteException re) {
-            /* ignore */
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Error while calling remote"
+                        + " findAccessibilityNodeInfoByViewIdInActiveWindow", re);
+            }
         }
         return null;
     }
@@ -169,25 +201,36 @@
      * insensitive containment. The search is performed in the currently
      * active window and starts from the root View in the window.
      *
-     * @param connection A connection for interacting with the system.
+     * @param connectionId The id of a connection for interacting with the system.
      * @param text The searched text.
      * @return A list of found {@link AccessibilityNodeInfo}s.
      */
     public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
-            IAccessibilityServiceConnection connection, String text) {
+            int connectionId, String text) {
         try {
-            final int interactionId = mInteractionIdCounter.getAndIncrement();
-            final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(
-                    text, interactionId, this, Thread.currentThread().getId());
-            // If the scale is zero the call has failed.
-            if (windowScale > 0) {
-                List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
-                        interactionId);
-                finalizeAccessibilityNodeInfos(infos, connection, windowScale);
-                return infos;
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final float windowScale =
+                    connection.findAccessibilityNodeInfosByViewTextInActiveWindow(text,
+                            interactionId, this, Thread.currentThread().getId());
+                // If the scale is zero the call has failed.
+                if (windowScale > 0) {
+                    List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+                            interactionId);
+                    finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+                    return infos;
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
             }
         } catch (RemoteException re) {
-            /* ignore */
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Error while calling remote"
+                        + " findAccessibilityNodeInfosByViewTextInActiveWindow", re);
+            }
         }
         return null;
     }
@@ -198,30 +241,39 @@
      * id is specified and starts from the View whose accessibility id is
      * specified.
      *
-     * @param connection A connection for interacting with the system.
+     * @param connectionId The id of a connection for interacting with the system.
      * @param text The searched text.
      * @param accessibilityWindowId A unique window id.
      * @param accessibilityViewId A unique View accessibility id from where to start the search.
      *        Use {@link android.view.View#NO_ID} to start from the root.
      * @return A list of found {@link AccessibilityNodeInfo}s.
      */
-    public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(
-            IAccessibilityServiceConnection connection, String text, int accessibilityWindowId,
-            int accessibilityViewId) {
+    public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(int connectionId,
+            String text, int accessibilityWindowId, int accessibilityViewId) {
         try {
-            final int interactionId = mInteractionIdCounter.getAndIncrement();
-            final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
-                    accessibilityWindowId, accessibilityViewId, interactionId, this,
-                    Thread.currentThread().getId());
-            // If the scale is zero the call has failed.
-            if (windowScale > 0) {
-                List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
-                        interactionId);
-                finalizeAccessibilityNodeInfos(infos, connection, windowScale);
-                return infos;
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
+                        accessibilityWindowId, accessibilityViewId, interactionId, this,
+                        Thread.currentThread().getId());
+                // If the scale is zero the call has failed.
+                if (windowScale > 0) {
+                    List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+                            interactionId);
+                    finalizeAccessibilityNodeInfos(infos, connectionId, windowScale);
+                    return infos;
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
             }
         } catch (RemoteException re) {
-            /* ignore */
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Error while calling remote"
+                        + " findAccessibilityNodeInfosByViewText", re);
+            }
         }
         return Collections.emptyList();
     }
@@ -229,24 +281,33 @@
     /**
      * Performs an accessibility action on an {@link AccessibilityNodeInfo}.
      *
-     * @param connection A connection for interacting with the system.
+     * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId The id of the window.
      * @param accessibilityViewId A unique View accessibility id.
      * @param action The action to perform.
      * @return Whether the action was performed.
      */
-    public boolean performAccessibilityAction(IAccessibilityServiceConnection connection,
-            int accessibilityWindowId, int accessibilityViewId, int action) {
+    public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId,
+            int accessibilityViewId, int action) {
         try {
-            final int interactionId = mInteractionIdCounter.getAndIncrement();
-            final boolean success = connection.performAccessibilityAction(
-                    accessibilityWindowId, accessibilityViewId, action, interactionId, this,
-                    Thread.currentThread().getId());
-            if (success) {
-                return getPerformAccessibilityActionResult(interactionId);
+            IAccessibilityServiceConnection connection = getConnection(connectionId);
+            if (connection != null) {
+                final int interactionId = mInteractionIdCounter.getAndIncrement();
+                final boolean success = connection.performAccessibilityAction(
+                        accessibilityWindowId, accessibilityViewId, action, interactionId, this,
+                        Thread.currentThread().getId());
+                if (success) {
+                    return getPerformAccessibilityActionResult(interactionId);
+                }
+            } else {
+                if (DEBUG) {
+                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+                }
             }
         } catch (RemoteException re) {
-            /* ignore */
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Error while calling remote performAccessibilityAction", re);
+            }
         }
         return false;
     }
@@ -406,14 +467,14 @@
      * Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
      *
      * @param info The info.
-     * @param connection The current connection to the system.
+     * @param connectionId The id of the connection to the system.
      * @param windowScale The source window compatibility scale.
      */
-    private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info,
-            IAccessibilityServiceConnection connection, float windowScale) {
+    private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId,
+            float windowScale) {
         if (info != null) {
             applyCompatibilityScaleIfNeeded(info, windowScale);
-            info.setConnection(connection);
+            info.setConnectionId(connectionId);
             info.setSealed(true);
         }
     }
@@ -422,16 +483,16 @@
      * Finalize {@link AccessibilityNodeInfo}s before passing them to the client.
      *
      * @param infos The {@link AccessibilityNodeInfo}s.
-     * @param connection The current connection to the system.
+     * @param connectionId The id of the connection to the system.
      * @param windowScale The source window compatibility scale.
      */
     private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
-            IAccessibilityServiceConnection connection, float windowScale) {
+            int connectionId, float windowScale) {
         if (infos != null) {
             final int infosCount = infos.size();
             for (int i = 0; i < infosCount; i++) {
                 AccessibilityNodeInfo info = infos.get(i);
-                finalizeAccessibilityNodeInfo(info, connection, windowScale);
+                finalizeAccessibilityNodeInfo(info, connectionId, windowScale);
             }
         }
     }
@@ -449,4 +510,39 @@
             return result;
         }
     }
+
+    /**
+     * Gets a cached accessibility service connection.
+     *
+     * @param connectionId The connection id.
+     * @return The cached connection if such.
+     */
+    public IAccessibilityServiceConnection getConnection(int connectionId) {
+        synchronized (sConnectionCache) {
+            return sConnectionCache.get(connectionId);
+        }
+    }
+
+    /**
+     * Adds a cached accessibility service connection.
+     *
+     * @param connectionId The connection id.
+     * @param connection The connection.
+     */
+    public void addConnection(int connectionId, IAccessibilityServiceConnection connection) {
+        synchronized (sConnectionCache) {
+            sConnectionCache.put(connectionId, connection);
+        }
+    }
+
+    /**
+     * Removes a cached accessibility service connection.
+     *
+     * @param connectionId The connection id.
+     */
+    public void removeConnection(int connectionId) {
+        synchronized (sConnectionCache) {
+            sConnectionCache.remove(connectionId);
+        }
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index fa34ee7..9b0f44a 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -16,7 +16,6 @@
 
 package android.view.accessibility;
 
-import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -53,6 +52,8 @@
 
     private static final boolean DEBUG = false;
 
+    private static final int UNDEFINED = -1;
+
     // Actions.
 
     /**
@@ -107,9 +108,9 @@
     private boolean mSealed;
 
     // Data.
-    private int mAccessibilityViewId = View.NO_ID;
-    private int mAccessibilityWindowId = View.NO_ID;
-    private int mParentAccessibilityViewId = View.NO_ID;
+    private int mAccessibilityViewId = UNDEFINED;
+    private int mAccessibilityWindowId = UNDEFINED;
+    private int mParentAccessibilityViewId = UNDEFINED;
     private int mBooleanProperties;
     private final Rect mBoundsInParent = new Rect();
     private final Rect mBoundsInScreen = new Rect();
@@ -122,7 +123,7 @@
     private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
     private int mActions;
 
-    private IAccessibilityServiceConnection mConnection;
+    private int mConnectionId = UNDEFINED;
 
     /**
      * Hide constructor from clients.
@@ -181,7 +182,7 @@
             return null;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
                 mAccessibilityWindowId, childAccessibilityViewId);
     }
 
@@ -253,7 +254,7 @@
             return false;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+        return client.performAccessibilityAction(mConnectionId, mAccessibilityWindowId,
                 mAccessibilityViewId, action);
     }
 
@@ -277,7 +278,7 @@
             return Collections.emptyList();
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+        return client.findAccessibilityNodeInfosByViewText(mConnectionId, text,
                 mAccessibilityWindowId, mAccessibilityViewId);
     }
 
@@ -297,7 +298,7 @@
             return null;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
                 mAccessibilityWindowId, mParentAccessibilityViewId);
     }
 
@@ -755,15 +756,16 @@
     }
 
     /**
-     * Sets the connection for interacting with the system.
+     * Sets the unique id of the IAccessibilityServiceConnection over which
+     * this instance can send requests to the system.
      *
-     * @param connection The client token.
+     * @param connectionId The connection id.
      *
      * @hide
      */
-    public final void setConnection(IAccessibilityServiceConnection connection) {
+    public void setConnectionId(int connectionId) {
         enforceNotSealed();
-        mConnection = connection;
+        mConnectionId = connectionId;
     }
 
     /**
@@ -900,16 +902,11 @@
      * </p>
      */
     public void writeToParcel(Parcel parcel, int flags) {
-        if (mConnection == null) {
-            parcel.writeInt(0);
-        } else {
-            parcel.writeInt(1);
-            parcel.writeStrongBinder(mConnection.asBinder());
-        }
         parcel.writeInt(isSealed() ? 1 : 0);
         parcel.writeInt(mAccessibilityViewId);
         parcel.writeInt(mAccessibilityWindowId);
         parcel.writeInt(mParentAccessibilityViewId);
+        parcel.writeInt(mConnectionId);
 
         SparseIntArray childIds = mChildAccessibilityIds;
         final int childIdsSize = childIds.size();
@@ -949,10 +946,10 @@
      */
     private void init(AccessibilityNodeInfo other) {
         mSealed = other.mSealed;
-        mConnection = other.mConnection;
         mAccessibilityViewId = other.mAccessibilityViewId;
         mParentAccessibilityViewId = other.mParentAccessibilityViewId;
         mAccessibilityWindowId = other.mAccessibilityWindowId;
+        mConnectionId = other.mConnectionId;
         mBoundsInParent.set(other.mBoundsInParent);
         mBoundsInScreen.set(other.mBoundsInScreen);
         mPackageName = other.mPackageName;
@@ -970,14 +967,11 @@
      * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
      */
     private void initFromParcel(Parcel parcel) {
-        if (parcel.readInt() == 1) {
-            mConnection = IAccessibilityServiceConnection.Stub.asInterface(
-                    parcel.readStrongBinder());
-        }
         mSealed = (parcel.readInt()  == 1);
         mAccessibilityViewId = parcel.readInt();
         mAccessibilityWindowId = parcel.readInt();
         mParentAccessibilityViewId = parcel.readInt();
+        mConnectionId = parcel.readInt();
 
         SparseIntArray childIds = mChildAccessibilityIds;
         final int childrenSize = parcel.readInt();
@@ -1011,10 +1005,10 @@
      */
     private void clear() {
         mSealed = false;
-        mConnection = null;
-        mAccessibilityViewId = View.NO_ID;
-        mParentAccessibilityViewId = View.NO_ID;
-        mAccessibilityWindowId = View.NO_ID;
+        mAccessibilityViewId = UNDEFINED;
+        mParentAccessibilityViewId = UNDEFINED;
+        mAccessibilityWindowId = UNDEFINED;
+        mConnectionId = UNDEFINED;
         mChildAccessibilityIds.clear();
         mBoundsInParent.set(0, 0, 0, 0);
         mBoundsInScreen.set(0, 0, 0, 0);
@@ -1048,9 +1042,8 @@
     }
 
     private boolean canPerformRequestOverConnection(int accessibilityViewId) {
-        return (mAccessibilityWindowId != View.NO_ID
-                && accessibilityViewId != View.NO_ID
-                && mConnection != null);
+        return (mConnectionId != UNDEFINED && mAccessibilityWindowId != UNDEFINED
+                && accessibilityViewId != UNDEFINED);
     }
 
     @Override
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index a4e0688..18d0f6f 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -16,7 +16,6 @@
 
 package android.view.accessibility;
 
-import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.os.Parcelable;
 import android.view.View;
 
@@ -78,8 +77,8 @@
 
     int mAddedCount= UNDEFINED;
     int mRemovedCount = UNDEFINED;
-    int mSourceViewId = View.NO_ID;
-    int mSourceWindowId = View.NO_ID;
+    int mSourceViewId = UNDEFINED;
+    int mSourceWindowId = UNDEFINED;
 
     CharSequence mClassName;
     CharSequence mContentDescription;
@@ -87,7 +86,8 @@
     Parcelable mParcelableData;
 
     final List<CharSequence> mText = new ArrayList<CharSequence>();
-    IAccessibilityServiceConnection mConnection;
+
+    int mConnectionId = UNDEFINED;
 
     /*
      * Hide constructor.
@@ -108,8 +108,8 @@
             mSourceWindowId = source.getAccessibilityWindowId();
             mSourceViewId = source.getAccessibilityViewId();
         } else {
-            mSourceWindowId = View.NO_ID;
-            mSourceViewId = View.NO_ID;
+            mSourceWindowId = UNDEFINED;
+            mSourceViewId = UNDEFINED;
         }
     }
 
@@ -119,33 +119,21 @@
      *   <strong>Note:</strong> It is a client responsibility to recycle the received info
      *   by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
      *   to avoid creating of multiple instances.
-     *
      * </p>
      * @return The info of the source.
      */
     public AccessibilityNodeInfo getSource() {
         enforceSealed();
-        if (mSourceWindowId == View.NO_ID || mSourceViewId == View.NO_ID || mConnection == null) {
+        if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
+                || mSourceViewId == UNDEFINED) {
             return null;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection, mSourceWindowId,
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
                 mSourceViewId);
     }
 
     /**
-     * Sets the connection for interacting with the AccessibilityManagerService.
-     *
-     * @param connection The connection.
-     *
-     * @hide
-     */
-    public void setConnection(IAccessibilityServiceConnection connection) {
-        enforceNotSealed();
-        mConnection = connection;
-    }
-
-    /**
      * Gets the id of the window from which the event comes from.
      *
      * @return The window id.
@@ -561,6 +549,19 @@
     }
 
     /**
+     * Sets the unique id of the IAccessibilityServiceConnection over which
+     * this instance can send requests to the system.
+     *
+     * @param connectionId The connection id.
+     *
+     * @hide
+     */
+    public void setConnectionId(int connectionId) {
+        enforceNotSealed();
+        mConnectionId = connectionId;
+    }
+
+    /**
      * Sets if this instance is sealed.
      *
      * @param sealed Whether is sealed.
@@ -708,7 +709,7 @@
         mText.addAll(record.mText);
         mSourceWindowId = record.mSourceWindowId;
         mSourceViewId = record.mSourceViewId;
-        mConnection = record.mConnection;
+        mConnectionId = record.mConnectionId;
     }
 
     /**
@@ -732,8 +733,9 @@
         mBeforeText = null;
         mParcelableData = null;
         mText.clear();
-        mSourceViewId = View.NO_ID;
-        mSourceWindowId = View.NO_ID;
+        mSourceViewId = UNDEFINED;
+        mSourceWindowId = UNDEFINED;
+        mConnectionId = UNDEFINED;
     }
 
     @Override
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index c621ff6..c3794be 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -49,5 +49,5 @@
 
     void removeAccessibilityInteractionConnection(IWindow windowToken);
 
-    IAccessibilityServiceConnection registerEventListener(IEventListener client);
+    void registerEventListener(IEventListener client);
 }
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index d6e36bb..9fa5593 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -345,6 +345,11 @@
      * a system private class.
      */
     public synchronized void setCookie(WebAddress uri, String value) {
+        if (JniUtil.useChromiumHttpStack()) {
+            nativeSetCookie(uri.toString(), value, false);
+            return;
+        }
+
         if (value != null && value.length() > MAX_COOKIE_LENGTH) {
             return;
         }
@@ -500,6 +505,10 @@
      * is a system private class.
      */
     public synchronized String getCookie(WebAddress uri) {
+        if (JniUtil.useChromiumHttpStack()) {
+            return nativeGetCookie(uri.toString(), false);
+        }
+
         if (!mAcceptCookie || uri == null) {
             return null;
         }
@@ -573,6 +582,8 @@
      * {@hide}  Too late to release publically.
      */
     public void waitForCookieOperationsToComplete() {
+        // Note that this function is applicable for both the java
+        // and native http stacks, and works correctly with either.
         synchronized (this) {
             while (pendingCookieOperations > 0) {
                 try {
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index f29aff2..e1eff58 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -4,15 +4,12 @@
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.media.Metadata;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
-import android.webkit.HTML5VideoView;
-import android.webkit.HTML5VideoViewProxy;
 import android.widget.FrameLayout;
 import android.widget.MediaController;
 import android.widget.MediaController.MediaPlayerControl;
@@ -150,7 +147,7 @@
     private void prepareForFullScreen() {
         // So in full screen, we reset the MediaPlayer
         mPlayer.reset();
-        MediaController mc = new MediaController(mProxy.getContext());
+        MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout);
         mc.setSystemUiVisibility(mLayout.getSystemUiVisibility());
         setMediaController(mc);
         mPlayer.setScreenOnWhilePlaying(true);
@@ -261,7 +258,6 @@
         mLayout.addView(getSurfaceView(), layoutParams);
 
         mLayout.setVisibility(View.VISIBLE);
-
         WebChromeClient client = webView.getWebChromeClient();
         if (client != null) {
             client.onShowCustomView(mLayout, mCallback);
@@ -338,4 +334,33 @@
         }
         return;
     }
+
+    static class FullScreenMediaController extends MediaController {
+
+        View mVideoView;
+
+        public FullScreenMediaController(Context context, View video) {
+            super(context);
+            mVideoView = video;
+        }
+
+        @Override
+        public void show() {
+            super.show();
+            if (mVideoView != null) {
+                mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+            }
+        }
+
+        @Override
+        public void hide() {
+            if (mVideoView != null) {
+                mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
+                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+            }
+            super.hide();
+        }
+
+    }
+
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index f18a396..2b59b80 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -19,10 +19,13 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -51,7 +54,6 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsoluteLayout;
 import android.widget.AbsoluteLayout.LayoutParams;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
@@ -74,7 +76,6 @@
 
     static final String LOGTAG = "webtextview";
 
-    private Paint mRingPaint;
     private int mRingInset;
 
     private WebView         mWebView;
@@ -207,13 +208,51 @@
                 }
             }
         };
-        float ringWidth = 4f * context.getResources().getDisplayMetrics().density;
         mReceiver = new MyResultReceiver(mHandler);
-        mRingPaint = new Paint();
-        mRingPaint.setColor(0x6633b5e5);
-        mRingPaint.setStrokeWidth(ringWidth);
-        mRingPaint.setStyle(Style.FILL);
+        float ringWidth = 2f * context.getResources().getDisplayMetrics().density;
         mRingInset = (int) ringWidth;
+        setBackgroundDrawable(new BackgroundDrawable(mRingInset));
+        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
+                getPaddingBottom());
+    }
+
+    private static class BackgroundDrawable extends Drawable {
+
+        private Paint mPaint = new Paint();
+        private int mBorderWidth;
+        private Rect mInsetRect = new Rect();
+
+        public BackgroundDrawable(int width) {
+            mPaint = new Paint();
+            mPaint.setStrokeWidth(width);
+            mBorderWidth = width;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            mPaint.setColor(0x6633b5e5);
+            canvas.drawRect(getBounds(), mPaint);
+            mInsetRect.left = getBounds().left + mBorderWidth;
+            mInsetRect.top = getBounds().top + mBorderWidth;
+            mInsetRect.right = getBounds().right - mBorderWidth;
+            mInsetRect.bottom = getBounds().bottom - mBorderWidth;
+            mPaint.setColor(Color.WHITE);
+            canvas.drawRect(mInsetRect, mPaint);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+
     }
 
     public void setAutoFillable(int queryId) {
@@ -223,37 +262,9 @@
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        if (isFocused()) {
-            final int ib = getHeight() - mRingInset;
-            canvas.drawRect(0, 0, getWidth(), mRingInset, mRingPaint);
-            canvas.drawRect(0, ib, getWidth(), getHeight(), mRingPaint);
-            canvas.drawRect(0, mRingInset, mRingInset, ib, mRingPaint);
-            canvas.drawRect(getWidth() - mRingInset, mRingInset, getWidth(), ib, mRingPaint);
-        }
-    }
-
-    private void growOrShrink(boolean grow) {
-        AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams) getLayoutParams();
-        if (grow) {
-            Log.i("webtextview", "grow");
-            lp.x -= mRingInset;
-            lp.y -= mRingInset;
-            lp.width += 2 * mRingInset;
-            lp.height += 2 * mRingInset;
-            setPadding(getPaddingLeft() + mRingInset, getPaddingTop() + mRingInset,
-                    getPaddingRight() + mRingInset, getPaddingBottom() + mRingInset);
-        } else {
-            Log.i("webtextview", "shrink");
-            lp.x += mRingInset;
-            lp.y += mRingInset;
-            lp.width -= 2 * mRingInset;
-            lp.height -= 2 * mRingInset;
-            setPadding(getPaddingLeft() - mRingInset, getPaddingTop() - mRingInset,
-                    getPaddingRight() - mRingInset, getPaddingBottom() - mRingInset);
-        }
-        setLayoutParams(lp);
+    public void setPadding(int left, int top, int right, int bottom) {
+        super.setPadding(left + mRingInset, top + mRingInset,
+                right + mRingInset, bottom + mRingInset);
     }
 
     @Override
@@ -557,7 +568,6 @@
         } else if (!mInsideRemove) {
             mWebView.setActive(false);
         }
-        growOrShrink(focused);
         mFromFocusChange = false;
     }
 
@@ -968,6 +978,10 @@
      */
     /* package */ void setRect(int x, int y, int width, int height) {
         LayoutParams lp = (LayoutParams) getLayoutParams();
+        x -= mRingInset;
+        y -= mRingInset;
+        width += 2 * mRingInset;
+        height += 2 * mRingInset;
         boolean needsUpdate = false;
         if (null == lp) {
             lp = new LayoutParams(width, height, x, y);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 35fd945..24eebd7 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.Widget;
+import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.ClipboardManager;
@@ -61,6 +62,7 @@
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.util.Log;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.HardwareCanvas;
@@ -77,6 +79,7 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -366,6 +369,7 @@
 
     private final Rect mGLRectViewport = new Rect();
     private final Rect mViewRectViewport = new Rect();
+    private final RectF mVisibleContentRect = new RectF();
     private boolean mGLViewportEmpty = false;
 
     /**
@@ -503,7 +507,7 @@
     private float mLastVelY;
 
     // The id of the native layer being scrolled.
-    private int mScrollingLayer;
+    private int mCurrentScrollingLayerId;
     private Rect mScrollingLayerRect = new Rect();
 
     // only trigger accelerated fling if the new velocity is at least
@@ -738,6 +742,7 @@
     static final int SCREEN_ON                          = 136;
     static final int ENTER_FULLSCREEN_VIDEO             = 137;
     static final int UPDATE_SELECTION                   = 138;
+    static final int UPDATE_ZOOM_DENSITY                = 139;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
     private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;
@@ -793,7 +798,9 @@
         "AUTOFILL_COMPLETE", //              = 134;
         "SELECT_AT", //                      = 135;
         "SCREEN_ON", //                      = 136;
-        "ENTER_FULLSCREEN_VIDEO" //          = 137;
+        "ENTER_FULLSCREEN_VIDEO", //         = 137;
+        "UPDATE_SELECTION", //               = 138;
+        "UPDATE_ZOOM_DENSITY" //             = 139;
     };
 
     // If the site doesn't use the viewport meta tag to specify the viewport,
@@ -935,7 +942,11 @@
          * Notify the listener that the picture has changed.
          * @param view The WebView that owns the picture.
          * @param picture The new picture.
-         * @deprecated This method is now obsolete.
+         * @deprecated Due to internal changes, the picture does not include
+         * composited layers such as fixed position elements or scrollable divs.
+         * While the PictureListener API can still be used to detect changes in
+         * the WebView content, you are advised against its usage until a replacement
+         * is provided in a future Android release
          */
         @Deprecated
         public void onNewPicture(WebView view, Picture picture);
@@ -1295,8 +1306,15 @@
         if (AccessibilityManager.getInstance(mContext).isEnabled()
                 && getSettings().getJavaScriptEnabled()) {
             // exposing the TTS for now ...
-            mTextToSpeech = new TextToSpeech(getContext(), null);
-            addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
+            final Context ctx = getContext();
+            if (ctx != null) {
+                final String packageName = ctx.getPackageName();
+                if (packageName != null) {
+                    mTextToSpeech = new TextToSpeech(getContext(), null, null,
+                            packageName + ".**webview**");
+                    addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
+                }
+            }
         }
     }
 
@@ -1617,6 +1635,14 @@
         clearTextEntry();
         clearActionModes();
         dismissFullScreenMode();
+        cancelSelectDialog();
+    }
+
+    private void cancelSelectDialog() {
+        if (mListBoxDialog != null) {
+            mListBoxDialog.cancel();
+            mListBoxDialog = null;
+        }
     }
 
     /**
@@ -3268,6 +3294,8 @@
             if (mNativeClass != 0) {
                 nativeSetPauseDrawing(mNativeClass, true);
             }
+
+            cancelSelectDialog();
         }
     }
 
@@ -3637,7 +3665,7 @@
         if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
             return;
         }
-        nativeScrollLayer(mScrollingLayer, x, y);
+        nativeScrollLayer(mCurrentScrollingLayerId, x, y);
         mScrollingLayerRect.left = x;
         mScrollingLayerRect.top = y;
         onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY);
@@ -4442,6 +4470,7 @@
         Rect vBox = contentToViewRect(contentBounds);
         Rect visibleRect = new Rect();
         calcOurVisibleRect(visibleRect);
+        offsetByLayerScrollPosition(vBox);
         // If the textfield is on screen, place the WebTextView in
         // its new place, accounting for our new scroll/zoom values,
         // and adjust its textsize.
@@ -4477,6 +4506,14 @@
         }
     }
 
+    private void offsetByLayerScrollPosition(Rect box) {
+        if ((mCurrentScrollingLayerId != 0)
+                && (mCurrentScrollingLayerId == nativeFocusCandidateLayerId())) {
+            box.offsetTo(box.left - mScrollingLayerRect.left,
+                    box.top - mScrollingLayerRect.top);
+        }
+    }
+
     void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
             boolean isPictureAfterFirstLayout, boolean registerPageSwapCallback) {
         if (mNativeClass == 0)
@@ -4576,14 +4613,15 @@
         boolean UIAnimationsRunning = false;
         // Currently for each draw we compute the animation values;
         // We may in the future decide to do that independently.
-        if (mNativeClass != 0 && nativeEvaluateLayersAnimations(mNativeClass)) {
+        if (mNativeClass != 0 && !canvas.isHardwareAccelerated()
+                && nativeEvaluateLayersAnimations(mNativeClass)) {
             UIAnimationsRunning = true;
             // If we have unfinished (or unstarted) animations,
             // we ask for a repaint. We only need to do this in software
             // rendering (with hardware rendering we already have a different
             // method of requesting a repaint)
-            if (!canvas.isHardwareAccelerated())
-                invalidate();
+            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+            invalidate();
         }
 
         // decide which adornments to draw
@@ -4607,11 +4645,14 @@
                     + " extras=" + extras);
         }
 
+        calcOurContentVisibleRectF(mVisibleContentRect);
         if (canvas.isHardwareAccelerated()) {
-            int functor = nativeGetDrawGLFunction(mNativeClass,
-                    mGLViewportEmpty ? null : mGLRectViewport, mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
-            ((HardwareCanvas) canvas).callDrawGLFunction(functor);
+            Rect glRectViewport = mGLViewportEmpty ? null : mGLRectViewport;
+            Rect viewRectViewport = mGLViewportEmpty ? null : mViewRectViewport;
 
+            int functor = nativeGetDrawGLFunction(mNativeClass, glRectViewport,
+                    viewRectViewport, mVisibleContentRect, getScale(), extras);
+            ((HardwareCanvas) canvas).callDrawGLFunction(functor);
             if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
                 mHardwareAccelSkia = getSettings().getHardwareAccelSkiaEnabled();
                 nativeUseHardwareAccelSkia(mHardwareAccelSkia);
@@ -4627,7 +4668,8 @@
             canvas.setDrawFilter(df);
             // XXX: Revisit splitting content.  Right now it causes a
             // synchronization problem with layers.
-            int content = nativeDraw(canvas, color, extras, false);
+            int content = nativeDraw(canvas, mVisibleContentRect, color,
+                    extras, false);
             canvas.setDrawFilter(null);
             if (!mBlockWebkitViewMessages && content != 0) {
                 mWebViewCore.sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
@@ -4890,6 +4932,7 @@
         // should be in content coordinates.
         Rect bounds = nativeFocusCandidateNodeBounds();
         Rect vBox = contentToViewRect(bounds);
+        offsetByLayerScrollPosition(vBox);
         mWebTextView.setRect(vBox.left, vBox.top, vBox.width(), vBox.height());
         if (!Rect.intersects(bounds, visibleRect)) {
             revealSelection();
@@ -5481,10 +5524,10 @@
         mMaxAutoScrollX = getViewWidth();
         mMinAutoScrollY = 0;
         mMaxAutoScrollY = getViewHeightWithTitle();
-        mScrollingLayer = nativeScrollableLayer(viewToContentX(mSelectX),
+        mCurrentScrollingLayerId = nativeScrollableLayer(viewToContentX(mSelectX),
                 viewToContentY(mSelectY), mScrollingLayerRect,
                 mScrollingLayerBounds);
-        if (mScrollingLayer != 0) {
+        if (mCurrentScrollingLayerId != 0) {
             if (mScrollingLayerRect.left != mScrollingLayerRect.right) {
                 mMinAutoScrollX = Math.max(mMinAutoScrollX,
                         contentToViewX(mScrollingLayerBounds.left));
@@ -5797,8 +5840,9 @@
         } else {
             mGLViewportEmpty = true;
         }
+        calcOurContentVisibleRectF(mVisibleContentRect);
         nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
-                mGLViewportEmpty ? null : mViewRectViewport);
+                mGLViewportEmpty ? null : mViewRectViewport, mVisibleContentRect);
     }
 
     /**
@@ -5969,9 +6013,9 @@
     private void startScrollingLayer(float x, float y) {
         int contentX = viewToContentX((int) x + mScrollX);
         int contentY = viewToContentY((int) y + mScrollY);
-        mScrollingLayer = nativeScrollableLayer(contentX, contentY,
+        mCurrentScrollingLayerId = nativeScrollableLayer(contentX, contentY,
                 mScrollingLayerRect, mScrollingLayerBounds);
-        if (mScrollingLayer != 0) {
+        if (mCurrentScrollingLayerId != 0) {
             mTouchMode = TOUCH_DRAG_LAYER_MODE;
         }
     }
@@ -6202,7 +6246,7 @@
                     ted.mPointsInView[0] = new Point(x, y);
                     ted.mMetaState = ev.getMetaState();
                     ted.mReprocess = mDeferTouchProcess;
-                    ted.mNativeLayer = mScrollingLayer;
+                    ted.mNativeLayer = mCurrentScrollingLayerId;
                     ted.mNativeLayerRect.set(mScrollingLayerRect);
                     ted.mSequence = mTouchEventQueue.nextTouchSequence();
                     mTouchEventQueue.preQueueTouchEventData(ted);
@@ -6393,7 +6437,7 @@
                     ted.mPointsInView[0] = new Point(x, y);
                     ted.mMetaState = ev.getMetaState();
                     ted.mReprocess = mDeferTouchProcess;
-                    ted.mNativeLayer = mScrollingLayer;
+                    ted.mNativeLayer = mCurrentScrollingLayerId;
                     ted.mNativeLayerRect.set(mScrollingLayerRect);
                     ted.mSequence = mTouchEventQueue.nextTouchSequence();
                     mTouchEventQueue.preQueueTouchEventData(ted);
@@ -6702,7 +6746,7 @@
             // directions.  mTouchMode might be TOUCH_DRAG_MODE if we have
             // reached the edge of a layer but mScrollingLayer will be non-zero
             // if we initiated the drag on a layer.
-            if (mScrollingLayer != 0) {
+            if (mCurrentScrollingLayerId != 0) {
                 final int contentX = viewToContentDimension(deltaX);
                 final int contentY = viewToContentDimension(deltaY);
 
@@ -7224,7 +7268,7 @@
                     + " vx=" + vx + " vy=" + vy
                     + " maxX=" + maxX + " maxY=" + maxY
                     + " scrollX=" + scrollX + " scrollY=" + scrollY
-                    + " layer=" + mScrollingLayer);
+                    + " layer=" + mCurrentScrollingLayerId);
         }
 
         // Allow sloppy flings without overscrolling at the edges.
@@ -8333,7 +8377,7 @@
                         mSentAutoScrollMessage = false;
                         break;
                     }
-                    if (mScrollingLayer == 0) {
+                    if (mCurrentScrollingLayerId == 0) {
                         pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
                     } else {
                         scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
@@ -8431,6 +8475,11 @@
                     mZoomManager.updateZoomRange(viewState, getViewWidth(), viewState.mScrollX);
                     break;
                 }
+                case UPDATE_ZOOM_DENSITY: {
+                    final float density = (Float) msg.obj;
+                    mZoomManager.updateDefaultZoomDensity(density);
+                    break;
+                }
                 case REPLACE_BASE_CONTENT: {
                     nativeReplaceBaseContent(msg.arg1);
                     break;
@@ -8445,7 +8494,11 @@
                     // nativeCreate sets mNativeClass to a non-zero value
                     String drawableDir = BrowserFrame.getRawResFilename(
                             BrowserFrame.DRAWABLEDIR, mContext);
-                    nativeCreate(msg.arg1, drawableDir);
+                    WindowManager windowManager =
+                            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+                    Display display = windowManager.getDefaultDisplay();
+                    nativeCreate(msg.arg1, drawableDir,
+                            ActivityManager.isHighEndGfx(display));
                     if (mDelaySetPicture != null) {
                         setNewPicture(mDelaySetPicture, true);
                         mDelaySetPicture = null;
@@ -8754,10 +8807,13 @@
 
     /** @hide Called by JNI when pages are swapped (only occurs with hardware
      * acceleration) */
-    protected void pageSwapCallback() {
+    protected void pageSwapCallback(boolean notifyAnimationStarted) {
         if (inEditingMode()) {
             didUpdateWebTextViewDimensions(ANYWHERE);
         }
+        if (notifyAnimationStarted) {
+            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+        }
     }
 
     void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
@@ -8795,7 +8851,6 @@
         mSendScrollEvent = false;
         recordNewContentSize(draw.mContentSize.x,
                 draw.mContentSize.y, updateLayout);
-
         if (isPictureAfterFirstLayout) {
             // Reset the last sent data here since dealing with new page.
             mLastWidthSent = 0;
@@ -9366,7 +9421,8 @@
      * @hide only needs to be accessible to Browser and testing
      */
     public void drawPage(Canvas canvas) {
-        nativeDraw(canvas, 0, 0, false);
+        calcOurContentVisibleRectF(mVisibleContentRect);
+        nativeDraw(canvas, mVisibleContentRect, 0, 0, false);
     }
 
     /**
@@ -9474,7 +9530,7 @@
     private native Rect nativeCacheHitNodeBounds();
     private native int nativeCacheHitNodePointer();
     /* package */ native void nativeClearCursor();
-    private native void     nativeCreate(int ptr, String drawableDir);
+    private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
     private native int      nativeCursorFramePointer();
     private native Rect     nativeCursorNodeBounds();
     private native int nativeCursorNodePointer();
@@ -9497,13 +9553,14 @@
      * MUST be passed to WebViewCore with SPLIT_PICTURE_SET message so that the
      * native allocation can be freed.
      */
-    private native int nativeDraw(Canvas canvas, int color, int extra,
-            boolean splitIfNeeded);
+    private native int nativeDraw(Canvas canvas, RectF visibleRect,
+            int color, int extra, boolean splitIfNeeded);
     private native void     nativeDumpDisplayTree(String urlOrNull);
     private native boolean  nativeEvaluateLayersAnimations(int nativeInstance);
     private native int      nativeGetDrawGLFunction(int nativeInstance, Rect rect,
-            Rect viewRect, float scale, int extras);
-    private native void     nativeUpdateDrawGLFunction(Rect rect, Rect viewRect);
+            Rect viewRect, RectF visibleRect, float scale, int extras);
+    private native void     nativeUpdateDrawGLFunction(Rect rect, Rect viewRect,
+            RectF visibleRect);
     private native void     nativeExtendSelection(int x, int y);
     private native int      nativeFindAll(String findLower, String findUpper,
             boolean sameAsLastSearch);
@@ -9534,6 +9591,7 @@
      * See WebTextView.setType()
      */
     private native int      nativeFocusCandidateType();
+    private native int      nativeFocusCandidateLayerId();
     private native boolean  nativeFocusIsPlugin();
     private native Rect     nativeFocusNodeBounds();
     /* package */ native int nativeFocusNodePointer();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index a97f4dd..d136004 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -519,7 +519,12 @@
     /**
      * Update the layers' content
      */
-    private native boolean nativeUpdateLayers(int baseLayer);
+    private native boolean nativeUpdateLayers(int nativeClass, int baseLayer);
+
+    /**
+     * Notify webkit that animations have begun (on the hardware accelerated content)
+     */
+    private native void nativeNotifyAnimationStarted(int nativeClass);
 
     private native boolean nativeFocusBoundsChanged();
 
@@ -1035,6 +1040,8 @@
 
         static final int PLUGIN_SURFACE_READY = 195;
 
+        static final int NOTIFY_ANIMATION_STARTED = 196;
+
         // private message ids
         private static final int DESTROY =     200;
 
@@ -1594,6 +1601,10 @@
                             nativePluginSurfaceReady();
                             break;
 
+                        case NOTIFY_ANIMATION_STARTED:
+                            nativeNotifyAnimationStarted(mNativeClass);
+                            break;
+
                         case ADD_PACKAGE_NAMES:
                             if (BrowserFrame.sJavaBridge == null) {
                                 throw new IllegalStateException("No WebView " +
@@ -2015,7 +2026,7 @@
             return;
         }
         // Directly update the layers we last passed to the UI side
-        if (nativeUpdateLayers(mLastDrawData.mBaseLayer)) {
+        if (nativeUpdateLayers(mNativeClass, mLastDrawData.mBaseLayer)) {
             // If anything more complex than position has been touched, let's do a full draw
             webkitDraw();
         }
@@ -2337,7 +2348,8 @@
                     / mViewportDensityDpi;
         }
         if (adjust != mWebView.getDefaultZoomScale()) {
-            mWebView.updateDefaultZoomDensity(adjust);
+            Message.obtain(mWebView.mPrivateHandler,
+                    WebView.UPDATE_ZOOM_DENSITY, adjust).sendToTarget();
         }
         int defaultScale = (int) (adjust * 100);
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 84d00c9..14bdc42 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -493,11 +493,19 @@
 
         if (mHardwareAccelerated) {
             mWebView.updateScrollCoordinates(mWebView.getScrollX() - tx, mWebView.getScrollY() - ty);
+            // By adding webView matrix, we need to offset the canvas a bit
+            // to make the animation smooth.
+            canvas.translate(tx, ty);
             setZoomScale(zoomScale, false);
 
             if (mZoomScale == 0) {
                 // We've reached the end of the zoom animation.
                 mInHWAcceleratedZoom = false;
+
+                // Ensure that the zoom level is pushed to WebCore. This has not
+                // yet occurred because we prevent it from happening while
+                // mInHWAcceleratedZoom is true.
+                mWebView.sendViewSizeZoom(false);
             }
         } else {
             canvas.translate(tx, ty);
@@ -514,11 +522,12 @@
     }
 
     public void updateDoubleTapZoom(int doubleTapZoom) {
-        if (mInZoomOverview) {
-            mDoubleTapZoomFactor = doubleTapZoom / 100.0f;
-            mTextWrapScale = getReadingLevelScale();
-            refreshZoomScale(true);
-        }
+        boolean zoomIn = (mTextWrapScale - mActualScale) < .1f;
+        mDoubleTapZoomFactor = doubleTapZoom / 100.0f;
+        mTextWrapScale = getReadingLevelScale();
+        float newScale = zoomIn ? mTextWrapScale
+                : Math.min(mTextWrapScale, mActualScale);
+        setZoomScale(newScale, true, true);
     }
 
     public void refreshZoomScale(boolean reflowText) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 1a1b8d0..13375bf 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -165,6 +165,11 @@
     };
 
     /**
+     * Constant for unspecified size.
+     */
+    private static final int SIZE_UNSPECIFIED = -1;
+
+    /**
      * Use a custom NumberPicker formatting callback to use two-digit minutes
      * strings like "01". Keeping a static formatter etc. is the most efficient
      * way to do this; it avoids creating temporary objects on every call to
@@ -542,16 +547,20 @@
                 getResources().getDisplayMetrics());
         mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
                 R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
-        mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight, 0);
+        mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight,
+                SIZE_UNSPECIFIED);
         mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight,
-                Integer.MAX_VALUE);
-        if (mMinHeight > mMaxHeight) {
+                SIZE_UNSPECIFIED);
+        if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED
+                && mMinHeight > mMaxHeight) {
             throw new IllegalArgumentException("minHeight > maxHeight");
         }
-        mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth, 0);
+        mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth,
+                SIZE_UNSPECIFIED);
         mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth,
-                Integer.MAX_VALUE);
-        if (mMinWidth > mMaxWidth) {
+                SIZE_UNSPECIFIED);
+        if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED
+                && mMinWidth > mMaxWidth) {
             throw new IllegalArgumentException("minWidth > maxWidth");
         }
         mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE);
@@ -746,10 +755,10 @@
         final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight);
         super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
         // Flag if we are measured with width or height less than the respective min.
-        final int desiredWidth = Math.max(mMinWidth, getMeasuredWidth());
-        final int desiredHeight = Math.max(mMinHeight, getMeasuredHeight());
-        final int widthSize = resolveSizeAndState(desiredWidth, newWidthMeasureSpec, 0);
-        final int heightSize = resolveSizeAndState(desiredHeight, newHeightMeasureSpec, 0);
+        final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(),
+                widthMeasureSpec);
+        final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(),
+                heightMeasureSpec);
         setMeasuredDimension(widthSize, heightSize);
     }
 
@@ -767,6 +776,7 @@
                 mBeginEditOnUpEvent = false;
                 mAdjustScrollerOnUpEvent = true;
                 if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) {
+                    mSelectorWheelPaint.setAlpha(SELECTOR_WHEEL_BRIGHT_ALPHA);
                     boolean scrollersFinished = mFlingScroller.isFinished()
                             && mAdjustScroller.isFinished();
                     if (!scrollersFinished) {
@@ -1243,6 +1253,7 @@
         }
         updateInputTextView();
         initializeSelectorWheelIndices();
+        tryComputeMaxWidth();
     }
 
     @Override
@@ -1368,6 +1379,9 @@
      * @return A measure spec greedily imposing the max size.
      */
     private int makeMeasureSpec(int measureSpec, int maxSize) {
+        if (maxSize == SIZE_UNSPECIFIED) {
+            return measureSpec;
+        }
         final int size = MeasureSpec.getSize(measureSpec);
         final int mode = MeasureSpec.getMode(measureSpec);
         switch (mode) {
@@ -1383,6 +1397,26 @@
     }
 
     /**
+     * Utility to reconcile a desired size and state, with constraints imposed by
+     * a MeasureSpec. Tries to respect the min size, unless a different size is
+     * imposed by the constraints.
+     *
+     * @param minSize The minimal desired size.
+     * @param measuredSize The currently measured size.
+     * @param measureSpec The current measure spec.
+     * @return The resolved size and state.
+     */
+    private int resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize,
+            int measureSpec) {
+        if (minSize != SIZE_UNSPECIFIED) {
+            final int desiredWidth = Math.max(minSize, measuredSize);
+            return resolveSizeAndState(desiredWidth, measureSpec, 0);
+        } else {
+            return measuredSize;
+        }
+    }
+
+    /**
      * Resets the selector indices and clear the cached
      * string representation of these indices.
      */
@@ -1564,23 +1598,11 @@
      */
     private void fling(int velocityY) {
         mPreviousScrollerY = 0;
-        Scroller flingScroller = mFlingScroller;
 
-        if (mWrapSelectorWheel) {
-            if (velocityY > 0) {
-                flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
-            } else {
-                flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
-            }
+        if (velocityY > 0) {
+            mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
         } else {
-            if (velocityY > 0) {
-                int maxY = mTextSize * (mValue - mMinValue);
-                flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY);
-            } else {
-                int startY = mTextSize * (mMaxValue - mValue);
-                int maxY = startY;
-                flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY);
-            }
+            mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
         }
 
         invalidate();
diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java
index 7ba4777..07bd918 100644
--- a/core/java/android/widget/RemoteViewsService.java
+++ b/core/java/android/widget/RemoteViewsService.java
@@ -145,6 +145,9 @@
                 Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, ex);
             }
         }
+        public synchronized void onDataSetChangedAsync() {
+            onDataSetChanged();
+        }
         public synchronized int getCount() {
             int count = 0;
             try {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index ebb2604..8f495c9 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.text.Editable;
 import android.text.Selection;
+import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.method.WordIterator;
 import android.text.style.SpellCheckSpan;
@@ -42,7 +43,18 @@
  */
 public class SpellChecker implements SpellCheckerSessionListener {
 
-    private final static int MAX_SPELL_BATCH_SIZE = 50;
+    // No more than this number of words will be parsed on each iteration to ensure a minimum
+    // lock of the UI thread
+    public static final int MAX_NUMBER_OF_WORDS = 50;
+
+    // Rough estimate, such that the word iterator interval usually does not need to be shifted
+    public static final int AVERAGE_WORD_LENGTH = 7;
+
+    // When parsing, use a character window of that size. Will be shifted if needed
+    public static final int WORD_ITERATOR_INTERVAL = AVERAGE_WORD_LENGTH * MAX_NUMBER_OF_WORDS;
+
+    // Pause between each spell check to keep the UI smooth
+    private final static int SPELL_PAUSE_DURATION = 400; // milliseconds
 
     private final TextView mTextView;
 
@@ -68,6 +80,10 @@
     // concurrently due to the asynchronous nature of onGetSuggestions.
     private WordIterator mWordIterator;
 
+    private TextServicesManager mTextServicesManager;
+
+    private Runnable mSpellRunnable;
+
     public SpellChecker(TextView textView) {
         mTextView = textView;
 
@@ -81,20 +97,19 @@
         mCookie = hashCode();
     }
 
-    private void setLocale(Locale locale) {
+    private void resetSession() {
         closeSession();
 
-        final TextServicesManager textServicesManager = (TextServicesManager)
-                mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
-        if (!textServicesManager.isSpellCheckerEnabled()) {
+        mTextServicesManager = (TextServicesManager) mTextView.getContext().
+                getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        if (!mTextServicesManager.isSpellCheckerEnabled()) {
             mSpellCheckerSession = null;
         } else {
-            mSpellCheckerSession = textServicesManager.newSpellCheckerSession(
+            mSpellCheckerSession = mTextServicesManager.newSpellCheckerSession(
                     null /* Bundle not currently used by the textServicesManager */,
-                    locale, this,
+                    mCurrentLocale, this,
                     false /* means any available languages from current spell checker */);
         }
-        mCurrentLocale = locale;
 
         // Restore SpellCheckSpans in pool
         for (int i = 0; i < mLength; i++) {
@@ -103,9 +118,6 @@
         }
         mLength = 0;
 
-        // Change SpellParsers' wordIterator locale
-        mWordIterator = new WordIterator(locale);
-
         // Remove existing misspelled SuggestionSpans
         mTextView.removeMisspelledSpans((Editable) mTextView.getText());
 
@@ -113,6 +125,18 @@
         mTextView.onLocaleChanged();
     }
 
+    private void setLocale(Locale locale) {
+        mCurrentLocale = locale;
+
+        resetSession();
+
+        // Change SpellParsers' wordIterator locale
+        mWordIterator = new WordIterator(locale);
+
+        // This class is the listener for locale change: warn other locale-aware objects
+        mTextView.onLocaleChanged();
+    }
+
     /**
      * @return true if a spell checker session has successfully been created. Returns false if not,
      * for instance when spell checking has been disabled in settings.
@@ -130,6 +154,10 @@
         for (int i = 0; i < length; i++) {
             mSpellParsers[i].finish();
         }
+
+        if (mSpellRunnable != null) {
+            mTextView.removeCallbacks(mSpellRunnable);
+        }
     }
 
     private int nextSpellCheckSpanIndex() {
@@ -179,6 +207,12 @@
             // Re-check the entire text
             start = 0;
             end = mTextView.getText().length();
+        } else {
+            final boolean spellCheckerActivated = mTextServicesManager.isSpellCheckerEnabled();
+            if (isSessionActive() != spellCheckerActivated) {
+                // Spell checker has been turned of or off since last spellCheck
+                resetSession();
+            }
         }
 
         if (!isSessionActive()) return;
@@ -223,7 +257,9 @@
 
             // Do not check this word if the user is currently editing it
             if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
-                final String word = editable.subSequence(start, end).toString();
+                final String word = (editable instanceof SpannableStringBuilder) ?
+                        ((SpannableStringBuilder) editable).substring(start, end) :
+                        editable.subSequence(start, end).toString();
                 spellCheckSpan.setSpellCheckInProgress(true);
                 textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
             }
@@ -235,6 +271,7 @@
                 System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
                 textInfos = textInfosCopy;
             }
+
             mSpellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE,
                     false /* TODO Set sequentialWords to true for initial spell check */);
         }
@@ -258,38 +295,57 @@
                             ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
 
                     SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
+
                     if (!isInDictionary && looksLikeTypo) {
                         createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan);
                     }
+
                     editable.removeSpan(spellCheckSpan);
                     break;
                 }
             }
         }
 
-        final int length = mSpellParsers.length;
-        for (int i = 0; i < length; i++) {
-            final SpellParser spellParser = mSpellParsers[i];
-            if (!spellParser.isFinished()) {
-                spellParser.parse();
-            }
-        }
+        scheduleNewSpellCheck();
     }
 
-    private void createMisspelledSuggestionSpan(Editable editable,
-            SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) {
+    private void scheduleNewSpellCheck() {
+        if (mSpellRunnable == null) {
+            mSpellRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    final int length = mSpellParsers.length;
+                    for (int i = 0; i < length; i++) {
+                        final SpellParser spellParser = mSpellParsers[i];
+                        if (!spellParser.isFinished()) {
+                            spellParser.parse();
+                            break; // run one spell parser at a time to bound running time
+                        }
+                    }
+                }
+            };
+        } else {
+            mTextView.removeCallbacks(mSpellRunnable);
+        }
+
+        mTextView.postDelayed(mSpellRunnable, SPELL_PAUSE_DURATION);
+    }
+
+    private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo,
+            SpellCheckSpan spellCheckSpan) {
         final int start = editable.getSpanStart(spellCheckSpan);
         final int end = editable.getSpanEnd(spellCheckSpan);
-        if (start < 0 || end < 0) return; // span was removed in the meantime
+        if (start < 0 || end <= start) return; // span was removed in the meantime
 
         // Other suggestion spans may exist on that region, with identical suggestions, filter
-        // them out to avoid duplicates. First, filter suggestion spans on that exact region.
+        // them out to avoid duplicates.
         SuggestionSpan[] suggestionSpans = editable.getSpans(start, end, SuggestionSpan.class);
         final int length = suggestionSpans.length;
         for (int i = 0; i < length; i++) {
             final int spanStart = editable.getSpanStart(suggestionSpans[i]);
             final int spanEnd = editable.getSpanEnd(suggestionSpans[i]);
             if (spanStart != start || spanEnd != end) {
+                // Nulled (to avoid new array allocation) if not on that exact same region
                 suggestionSpans[i] = null;
             }
         }
@@ -337,8 +393,7 @@
                 SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
         editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
-        // TODO limit to the word rectangle region
-        mTextView.invalidate();
+        mTextView.invalidateRegion(start, end);
     }
 
     private class SpellParser {
@@ -362,7 +417,9 @@
             // Iterate over the newly added text and schedule new SpellCheckSpans
             final int start = editable.getSpanStart(mRange);
             final int end = editable.getSpanEnd(mRange);
-            mWordIterator.setCharSequence(editable, start, end);
+
+            int wordIteratorWindowEnd = Math.min(end, start + WORD_ITERATOR_INTERVAL);
+            mWordIterator.setCharSequence(editable, start, wordIteratorWindowEnd);
 
             // Move back to the beginning of the current word, if any
             int wordStart = mWordIterator.preceding(start);
@@ -387,11 +444,16 @@
             SuggestionSpan[] suggestionSpans = editable.getSpans(start - 1, end + 1,
                     SuggestionSpan.class);
 
-            int nbWordsChecked = 0;
+            int wordCount = 0;
             boolean scheduleOtherSpellCheck = false;
 
             while (wordStart <= end) {
                 if (wordEnd >= start && wordEnd > wordStart) {
+                    if (wordCount >= MAX_NUMBER_OF_WORDS) {
+                        scheduleOtherSpellCheck = true;
+                        break;
+                    }
+
                     // A new word has been created across the interval boundaries with this edit.
                     // Previous spans (ended on start / started on end) removed, not valid anymore
                     if (wordStart < start && wordEnd > start) {
@@ -427,17 +489,20 @@
                     }
 
                     if (createSpellCheckSpan) {
-                        if (nbWordsChecked == MAX_SPELL_BATCH_SIZE) {
-                            scheduleOtherSpellCheck = true;
-                            break;
-                        }
                         addSpellCheckSpan(editable, wordStart, wordEnd);
-                        nbWordsChecked++;
                     }
+                    wordCount++;
                 }
 
                 // iterate word by word
+                int originalWordEnd = wordEnd;
                 wordEnd = mWordIterator.following(wordEnd);
+                if ((wordIteratorWindowEnd < end) &&
+                        (wordEnd == BreakIterator.DONE || wordEnd >= wordIteratorWindowEnd)) {
+                    wordIteratorWindowEnd = Math.min(end, originalWordEnd + WORD_ITERATOR_INTERVAL);
+                    mWordIterator.setCharSequence(editable, originalWordEnd, wordIteratorWindowEnd);
+                    wordEnd = mWordIterator.following(originalWordEnd);
+                }
                 if (wordEnd == BreakIterator.DONE) break;
                 wordStart = mWordIterator.getBeginning(wordEnd);
                 if (wordStart == BreakIterator.DONE) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 185cfa9..6722d17 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1209,6 +1209,9 @@
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) imm.restartInput(this);
         }
+
+        // start or stop the cursor blinking as appropriate
+        makeBlink();
     }
 
     /**
@@ -2581,6 +2584,17 @@
     }
 
     /**
+     * Returns whether the text is allowed to be wider than the View is.
+     * If false, the text will be wrapped to the width of the View.
+     *
+     * @attr ref android.R.styleable#TextView_scrollHorizontally
+     * @hide
+     */
+    public boolean getHorizontallyScrolling() {
+        return mHorizontallyScrolling;
+    }
+
+    /**
      * Makes the TextView at least this many lines tall.
      *
      * Setting this value overrides any other (minimum) height setting. A single line TextView will
@@ -3196,7 +3210,6 @@
         }
 
         boolean needEditableForNotification = false;
-        boolean startSpellCheck = false;
 
         if (mListeners != null && mListeners.size() != 0) {
             needEditableForNotification = true;
@@ -3208,7 +3221,6 @@
             setFilters(t, mFilters);
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) imm.restartInput(this);
-            startSpellCheck = true;
         } else if (type == BufferType.SPANNABLE || mMovement != null) {
             text = mSpannableFactory.newSpannable(text);
         } else if (!(text instanceof CharWrapper)) {
@@ -3297,11 +3309,6 @@
         sendOnTextChanged(text, 0, oldlen, textLength);
         onTextChanged(text, 0, oldlen, textLength);
 
-        if (startSpellCheck && mSpellChecker != null) {
-            // This view has to have been previously attached for mSpellChecker to exist  
-            updateSpellCheckSpans(0, textLength);
-        }
-
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
         }
@@ -3816,7 +3823,6 @@
                 if (imm != null && imm.isActive(this)) {
                     imm.hideSoftInputFromWindow(getWindowToken(), 0);
                 }
-                clearFocus();
                 return;
             }
         }
@@ -3838,7 +3844,7 @@
                     | KeyEvent.FLAG_EDITOR_ACTION)));
         }
     }
-    
+
     /**
      * Set the private content type of the text, which is the
      * {@link EditorInfo#privateImeOptions EditorInfo.privateImeOptions}
@@ -4313,15 +4319,24 @@
     }
 
     private void invalidateCursor(int a, int b, int c) {
+        if (a >= 0 || b >= 0 || c >= 0) {
+            int start = Math.min(Math.min(a, b), c);
+            int end = Math.max(Math.max(a, b), c);
+            invalidateRegion(start, end);
+        }
+    }
+
+    /**
+     * Invalidates the region of text enclosed between the start and end text offsets.
+     *
+     * @hide
+     */
+    void invalidateRegion(int start, int end) {
         if (mLayout == null) {
             invalidate();
         } else {
-            if (a >= 0 || b >= 0 || c >= 0) {
-                int first = Math.min(Math.min(a, b), c);
-                int last = Math.max(Math.max(a, b), c);
-
-                int line = mLayout.getLineForOffset(first);
-                int top = mLayout.getLineTop(line);
+                int lineStart = mLayout.getLineForOffset(start);
+                int top = mLayout.getLineTop(lineStart);
 
                 // This is ridiculous, but the descent from the line above
                 // can hang down into the line we really want to redraw,
@@ -4329,36 +4344,36 @@
                 // sure everything that needs to be redrawn really is.
                 // (But not the whole line above, because that would cause
                 // the same problem with the descenders on the line above it!)
-                if (line > 0) {
-                    top -= mLayout.getLineDescent(line - 1);
+                if (lineStart > 0) {
+                    top -= mLayout.getLineDescent(lineStart - 1);
                 }
 
-                int line2;
+                int lineEnd;
 
-                if (first == last)
-                    line2 = line;
+                if (start == end)
+                    lineEnd = lineStart;
                 else
-                    line2 = mLayout.getLineForOffset(last);
+                    lineEnd = mLayout.getLineForOffset(end);
 
-                int bottom = mLayout.getLineTop(line2 + 1);
+                int bottom = mLayout.getLineBottom(lineEnd);
 
-                final int horizontalPadding = getCompoundPaddingLeft();
+                final int compoundPaddingLeft = getCompoundPaddingLeft();
                 final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true);
-                
-                // If used, the cursor drawables can have an arbitrary dimension that can go beyond
-                // the invalidated lines specified above.
-                for (int i = 0; i < mCursorCount; i++) {
-                    Rect bounds = mCursorDrawable[i].getBounds();
-                    top = Math.min(top, bounds.top);
-                    bottom = Math.max(bottom, bounds.bottom);
-                    // Horizontal bounds are already full width, no need to update
+
+                int left, right;
+                if (lineStart == lineEnd) {
+                    left = (int) mLayout.getPrimaryHorizontal(start);
+                    right = (int) (mLayout.getPrimaryHorizontal(end) + 1.0);
+                    left += compoundPaddingLeft;
+                    right += compoundPaddingLeft;
+                } else {
+                    // Rectangle bounding box when the region spans several lines
+                    left = compoundPaddingLeft;
+                    right = getWidth() - getCompoundPaddingRight();
                 }
 
-                invalidate(horizontalPadding + mScrollX, top + verticalPadding,
-                        horizontalPadding + mScrollX + getWidth() -
-                        getCompoundPaddingLeft() - getCompoundPaddingRight(),
-                        bottom + verticalPadding);
-            }
+                invalidate(mScrollX + left, verticalPadding + top,
+                        mScrollX + right, verticalPadding + bottom);
         }
     }
 
@@ -4460,8 +4475,8 @@
 
         // Resolve drawables as the layout direction has been resolved
         resolveDrawables();
-        
-        updateSpellCheckSpans(0, mText.length());
+
+        updateSpellCheckSpans(0, mText.length(), true /* create the spell checker if needed */);
     }
 
     @Override
@@ -5495,7 +5510,7 @@
                      * call performClick(), but that won't do anything in
                      * this case.)
                      */
-                    if (hasOnClickListeners()) {
+                    if (!hasOnClickListeners()) {
                         if (mMovement != null && mText instanceof Editable
                                 && mLayout != null && onCheckIsTextEditor()) {
                             InputMethodManager imm = InputMethodManager.peekInstance();
@@ -5532,7 +5547,7 @@
                          * call performClick(), but that won't do anything in
                          * this case.)
                          */
-                        if (hasOnClickListeners()) {
+                        if (!hasOnClickListeners()) {
                             View v = focusSearch(FOCUS_DOWN);
 
                             if (v != null) {
@@ -5594,8 +5609,6 @@
                 outAttrs.extras = mInputContentType.extras;
             } else {
                 outAttrs.imeOptions = EditorInfo.IME_NULL;
-                // May not be defined otherwise and needed by onEditorAction
-                mInputContentType = new InputContentType();
             }
             if (focusSearch(FOCUS_DOWN) != null) {
                 outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
@@ -5893,10 +5906,10 @@
                 if (cursorOffsetVertical != 0) {
                     canvas.translate(0, -cursorOffsetVertical);
                 }
-                invalidate(true);
+                invalidate(true); // TODO invalidate cursor region only
             } else {
                 stopAnimation();
-                invalidate(false);
+                invalidate(false); // TODO invalidate cursor region only
             }
         }
 
@@ -7613,6 +7626,13 @@
                 list.get(i).onTextChanged(text, start, before, after);
             }
         }
+
+        updateSpellCheckSpans(start, start + after, false);
+
+        // Hide the controllers as soon as text is modified (typing, procedural...)
+        // We do not hide the span controllers, since they can be added when a new text is
+        // inserted into the text view (voice IME).
+        hideCursorControllers();
     }
 
     /**
@@ -7652,15 +7672,6 @@
 
         sendOnTextChanged(buffer, start, before, after);
         onTextChanged(buffer, start, before, after);
-
-        updateSpellCheckSpans(start, start + after);
-
-        // Hide the controllers if the amount of content changed
-        if (before != after) {
-            // We do not hide the span controllers, as they can be added when a new text is
-            // inserted into the text view
-            hideCursorControllers();
-        }
     }
     
     /**
@@ -7718,10 +7729,8 @@
                 onSelectionChanged(newSelStart, newSelEnd);
             }
         }
-        
-        if (what instanceof UpdateAppearance || what instanceof ParagraphStyle
-                || (what instanceof SuggestionSpan && (((SuggestionSpan)what).getFlags()
-                        & SuggestionSpan.FLAG_AUTO_CORRECTION) != 0)) {
+
+        if (what instanceof UpdateAppearance || what instanceof ParagraphStyle) {
             if (ims == null || ims.mBatchEditNesting == 0) {
                 invalidate();
                 mHighlightPathBogus = true;
@@ -7776,17 +7785,22 @@
             }
         }
 
-        if (newStart < 0 && what instanceof SpellCheckSpan) {
-            getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
+        if (mSpellChecker != null && newStart < 0 && what instanceof SpellCheckSpan) {
+            mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
         }
     }
 
     /**
      * Create new SpellCheckSpans on the modified region.
      */
-    private void updateSpellCheckSpans(int start, int end) {
+    private void updateSpellCheckSpans(int start, int end, boolean createSpellChecker) {
         if (isTextEditable() && isSuggestionsEnabled()) {
-            getSpellChecker().spellCheck(start, end);
+            if (mSpellChecker == null && createSpellChecker) {
+                mSpellChecker = new SpellChecker(this);
+            }
+            if (mSpellChecker != null) {
+                mSpellChecker.spellCheck(start, end);
+            }
         }
     }
 
@@ -7963,16 +7977,12 @@
         @Override
         public void onClick(View view) {
             if (view == mDeleteTextView) {
-                deleteText();
-            }
-        }
-
-        private void deleteText() {
-            Editable editable = (Editable) mText;
-            int start = editable.getSpanStart(mEasyEditSpan);
-            int end = editable.getSpanEnd(mEasyEditSpan);
-            if (start >= 0 && end >= 0) {
-                editable.delete(start, end);
+                Editable editable = (Editable) mText;
+                int start = editable.getSpanStart(mEasyEditSpan);
+                int end = editable.getSpanEnd(mEasyEditSpan);
+                if (start >= 0 && end >= 0) {
+                    deleteText_internal(start, end);
+                }
             }
         }
 
@@ -8961,13 +8971,6 @@
         return packRangeInLong(offset,  offset);
     }
 
-    private SpellChecker getSpellChecker() {
-        if (mSpellChecker == null) {
-            mSpellChecker = new SpellChecker(this);
-        }
-        return mSpellChecker;
-    }
-
     private long getLastTouchOffsets() {
         SelectionModifierCursorController selectionController = getSelectionController();
         final int minOffset = selectionController.getMinTouchOffset();
@@ -9096,7 +9099,7 @@
 
             case ID_CUT:
                 setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
-                ((Editable) mText).delete(min, max);
+                deleteText_internal(min, max);
                 stopSelectionActionMode();
                 return true;
 
@@ -9127,7 +9130,7 @@
                 if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
                     // Two spaces at beginning of paste: remove one
                     final int originalLength = mText.length();
-                    ((Editable) mText).delete(min - 1, min);
+                    deleteText_internal(min - 1, min);
                     // Due to filters, there is no guarantee that exactly one character was
                     // removed: count instead.
                     final int delta = mText.length() - originalLength;
@@ -9137,7 +9140,7 @@
                         !Character.isSpaceChar(charAfter) && charAfter != '\n') {
                     // No space at beginning of paste: add one
                     final int originalLength = mText.length();
-                    ((Editable) mText).replace(min, min, " ");
+                    replaceText_internal(min, min, " ");
                     // Taking possible filters into account as above.
                     final int delta = mText.length() - originalLength;
                     min += delta;
@@ -9151,11 +9154,11 @@
 
                 if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
                     // Two spaces at end of paste: remove one
-                    ((Editable) mText).delete(max, max + 1);
+                    deleteText_internal(max, max + 1);
                 } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
                         !Character.isSpaceChar(charAfter) && charAfter != '\n') {
                     // No space at end of paste: add one
-                    ((Editable) mText).replace(max, max, " ");
+                    replaceText_internal(max, max, " ");
                 }
             }
         }
@@ -9376,42 +9379,59 @@
             mPositionY = mTempCoords[1];
         }
 
-        public boolean isVisible(int positionX, int positionY) {
-            final TextView textView = TextView.this;
-
-            if (mTempRect == null) mTempRect = new Rect();
-            final Rect clip = mTempRect;
-            clip.left = getCompoundPaddingLeft();
-            clip.top = getExtendedPaddingTop();
-            clip.right = textView.getWidth() - getCompoundPaddingRight();
-            clip.bottom = textView.getHeight() - getExtendedPaddingBottom();
-
-            final ViewParent parent = textView.getParent();
-            if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
-                return false;
-            }
-
-            int posX = mPositionX + positionX;
-            int posY = mPositionY + positionY;
-
-            // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
-            return posX >= clip.left - 1 && posX <= clip.right + 1 &&
-                    posY >= clip.top && posY <= clip.bottom;
-        }
-
-        public boolean isOffsetVisible(int offset) {
-            final int line = mLayout.getLineForOffset(offset);
-            final int lineBottom = mLayout.getLineBottom(line);
-            final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
-            return isVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
-                    lineBottom + viewportToContentVerticalOffset());
-        }
-
         public void onScrollChanged() {
             mScrollHasChanged = true;
         }
     }
 
+    private boolean isPositionVisible(int positionX, int positionY) {
+        synchronized (sTmpPosition) {
+            final float[] position = sTmpPosition;
+            position[0] = positionX;
+            position[1] = positionY;
+            View view = this;
+
+            while (view != null) {
+                if (view != this) {
+                    // Local scroll is already taken into account in positionX/Y
+                    position[0] -= view.getScrollX();
+                    position[1] -= view.getScrollY();
+                }
+
+                if (position[0] < 0 || position[1] < 0 ||
+                        position[0] > view.getWidth() || position[1] > view.getHeight()) {
+                    return false;
+                }
+
+                if (!view.getMatrix().isIdentity()) {
+                    view.getMatrix().mapPoints(position);
+                }
+
+                position[0] += view.getLeft();
+                position[1] += view.getTop();
+
+                final ViewParent parent = view.getParent();
+                if (parent instanceof View) {
+                    view = (View) parent;
+                } else {
+                    // We've reached the ViewRoot, stop iterating
+                    view = null;
+                }
+            }
+        }
+
+        // We've been able to walk up the view hierarchy and the position was never clipped
+        return true;
+    }
+
+    private boolean isOffsetVisible(int offset) {
+        final int line = mLayout.getLineForOffset(offset);
+        final int lineBottom = mLayout.getLineBottom(line);
+        final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
+        return isPositionVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
+                lineBottom + viewportToContentVerticalOffset());
+    }
+
     @Override
     protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
         super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
@@ -9510,7 +9530,7 @@
         public void updatePosition(int parentPositionX, int parentPositionY,
                 boolean parentPositionChanged, boolean parentScrolled) {
             // Either parentPositionChanged or parentScrolled is true, check if still visible
-            if (isShowing() && getPositionListener().isOffsetVisible(getTextOffset())) {
+            if (isShowing() && isOffsetVisible(getTextOffset())) {
                 if (parentScrolled) computeLocalPosition();
                 updatePosition(parentPositionX, parentPositionY);
             } else {
@@ -9803,7 +9823,7 @@
                 highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
             }
 
-            // Add to dictionary item is there a span with the misspelled flag
+            // Add to dictionary item if there is a span with the misspelled flag
             if (misspelledSpan != null) {
                 final int misspelledStart = spannable.getSpanStart(misspelledSpan);
                 final int misspelledEnd = spannable.getSpanEnd(misspelledSpan);
@@ -9867,9 +9887,7 @@
 
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            TextView textView = (TextView) view;
             Editable editable = (Editable) mText;
-
             SuggestionInfo suggestionInfo = mSuggestionInfos[position];
 
             if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
@@ -9883,7 +9901,7 @@
                             Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) {
                         spanUnionEnd = spanUnionEnd + 1;
                     }
-                    editable.replace(spanUnionStart, spanUnionEnd, "");
+                    deleteText_internal(spanUnionStart, spanUnionEnd);
                 }
                 hide();
                 return;
@@ -9891,7 +9909,7 @@
 
             final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
             final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
-            if (spanStart < 0 || spanEnd < 0) {
+            if (spanStart < 0 || spanEnd <= spanStart) {
                 // Span has been removed
                 hide();
                 return;
@@ -9901,11 +9919,13 @@
             if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
                 Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
                 intent.putExtra("word", originalText);
+                intent.putExtra("locale", getTextServicesLocale().toString());
                 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                 getContext().startActivity(intent);
                 // There is no way to know if the word was indeed added. Re-check.
+                // TODO The ExtractEditText should remove the span in the original text instead
                 editable.removeSpan(suggestionInfo.suggestionSpan);
-                updateSpellCheckSpans(spanStart, spanEnd);
+                updateSpellCheckSpans(spanStart, spanEnd, false);
             } else {
                 // SuggestionSpans are removed by replace: save them before
                 SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
@@ -9931,9 +9951,9 @@
 
                 final int suggestionStart = suggestionInfo.suggestionStart;
                 final int suggestionEnd = suggestionInfo.suggestionEnd;
-                final String suggestion = textView.getText().subSequence(
+                final String suggestion = suggestionInfo.text.subSequence(
                         suggestionStart, suggestionEnd).toString();
-                editable.replace(spanStart, spanEnd, suggestion);
+                replaceText_internal(spanStart, spanEnd, suggestion);
 
                 // Notify source IME of the suggestion pick. Do this before swaping texts.
                 if (!TextUtils.isEmpty(
@@ -9957,13 +9977,14 @@
                     // way to assign them a valid range after replacement
                     if (suggestionSpansStarts[i] <= spanStart &&
                             suggestionSpansEnds[i] >= spanEnd) {
-                        editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i],
+                        setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i],
                                 suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
                     }
                 }
 
                 // Move cursor at the end of the replaced word
-                Selection.setSelection(editable, spanEnd + lengthDifference);
+                final int newCursorPosition = spanEnd + lengthDifference;
+                setCursorPosition_internal(newCursorPosition, newCursorPosition);
             }
 
             hide();
@@ -10534,7 +10555,7 @@
                 return false;
             }
 
-            return getPositionListener().isVisible(mPositionX + mHotspotX, mPositionY);
+            return TextView.this.isPositionVisible(mPositionX + mHotspotX, mPositionY);
         }
 
         public abstract int getCurrentCursorOffset();
@@ -10823,7 +10844,7 @@
 
             // Handles can not cross and selection is at least one character
             final int selectionEnd = getSelectionEnd();
-            if (offset >= selectionEnd) offset = selectionEnd - 1;
+            if (offset >= selectionEnd) offset = Math.max(0, selectionEnd - 1);
 
             positionAtCursorOffset(offset, false);
         }
@@ -10865,7 +10886,7 @@
 
             // Handles can not cross and selection is at least one character
             final int selectionStart = getSelectionStart();
-            if (offset <= selectionStart) offset = selectionStart + 1;
+            if (offset <= selectionStart) offset = Math.min(selectionStart + 1, mText.length());
 
             positionAtCursorOffset(offset, false);
         }
@@ -11237,7 +11258,7 @@
         int max = extractRangeEndFromLong(minMax);
 
         Selection.setSelection((Spannable) mText, max);
-        ((Editable) mText).replace(min, max, content);
+        replaceText_internal(min, max, content);
 
         if (dragDropIntoItself) {
             int dragSourceStart = dragLocalState.start;
@@ -11250,7 +11271,7 @@
             }
 
             // Delete original selection
-            ((Editable) mText).delete(dragSourceStart, dragSourceEnd);
+            deleteText_internal(dragSourceStart, dragSourceEnd);
 
             // Make sure we do not leave two adjacent spaces.
             if ((dragSourceStart == 0 ||
@@ -11259,7 +11280,7 @@
                     Character.isSpaceChar(mTransformed.charAt(dragSourceStart)))) {
                 final int pos = dragSourceStart == mText.length() ?
                         dragSourceStart - 1 : dragSourceStart;
-                ((Editable) mText).delete(pos, pos + 1);
+                deleteText_internal(pos, pos + 1);
             }
         }
     }
@@ -11420,6 +11441,38 @@
         }
     }
 
+    /**
+     * Deletes the range of text [start, end[.
+     * @hide
+     */
+    protected void deleteText_internal(int start, int end) {
+        ((Editable) mText).delete(start, end);
+    }
+
+    /**
+     * Replaces the range of text [start, end[ by replacement text
+     * @hide
+     */
+    protected void replaceText_internal(int start, int end, CharSequence text) {
+        ((Editable) mText).replace(start, end, text);
+    }
+
+    /**
+     * Sets a span on the specified range of text
+     * @hide
+     */
+    protected void setSpan_internal(Object span, int start, int end, int flags) {
+        ((Editable) mText).setSpan(span, start, end, flags);
+    }
+
+    /**
+     * Moves the cursor to the specified offset position in text
+     * @hide
+     */
+    protected void setCursorPosition_internal(int start, int end) {
+        Selection.setSelection(((Editable) mText), start, end);
+    }
+
     @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
     private CharSequence            mTransformed;
@@ -11500,6 +11553,7 @@
     private Path                    mHighlightPath;
     private boolean                 mHighlightPathBogus = true;
     private static final RectF      sTempRect = new RectF();
+    private static final float[]    sTmpPosition = new float[2];
 
     // XXX should be much larger
     private static final int        VERY_WIDE = 1024*1024;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 3e96c81..fec4cbc 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1275,7 +1275,7 @@
             // record changes to the battery level.
             if (mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel &&
                     (dataSize >= MAX_MAX_HISTORY_BUFFER
-                            || ((mHistoryEnd.states^mHistoryCur.states)
+                            || ((mHistoryLastWritten.states^mHistoryCur.states)
                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
                 return;
             }
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 36f0246..61c0c8e 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -418,7 +418,7 @@
     public static final int SM_QUIT_CMD = -1;
 
     /** Message.what value when initializing */
-    public static final int SM_INIT_CMD = -1;
+    public static final int SM_INIT_CMD = -2;
 
     /**
      * Convenience constant that maybe returned by processMessage
@@ -569,6 +569,13 @@
         }
 
         /**
+         * Clear the list of Processed Message Info.
+         */
+        void cleanup() {
+            mMessages.clear();
+        }
+
+        /**
          * @return the information on a particular record. 0 is the oldest
          * record and size()-1 is the newest record. If the index is to
          * large null is returned.
@@ -608,6 +615,7 @@
         }
     }
 
+
     private static class SmHandler extends Handler {
 
         /** The debug flag */
@@ -782,15 +790,8 @@
              */
             if (destState != null) {
                 if (destState == mQuittingState) {
-                    /**
-                     * We are quitting so ignore all messages.
-                     */
-                    mSm.quitting();
-                    if (mSm.mSmThread != null) {
-                        // If we made the thread then quit looper which stops the thread.
-                        getLooper().quit();
-                        mSm.mSmThread = null;
-                    }
+                    cleanupAfterQuitting();
+
                 } else if (destState == mHaltingState) {
                     /**
                      * Call halting() if we've transitioned to the halting
@@ -803,6 +804,29 @@
         }
 
         /**
+         * Cleanup all the static variables and the looper after the SM has been quit.
+         */
+        private final void cleanupAfterQuitting() {
+            mSm.quitting();
+            if (mSm.mSmThread != null) {
+                // If we made the thread then quit looper which stops the thread.
+                getLooper().quit();
+                mSm.mSmThread = null;
+            }
+
+            mSm.mSmHandler = null;
+            mSm = null;
+            mMsg = null;
+            mProcessedMessages.cleanup();
+            mStateStack = null;
+            mTempStateStack = null;
+            mStateInfo.clear();
+            mInitialState = null;
+            mDestState = null;
+            mDeferredMessages.clear();
+        }
+
+        /**
          * Complete the construction of the state machine.
          */
         private final void completeConstruction() {
@@ -1343,10 +1367,12 @@
     /**
      * Get a message and set Message.target = this.
      *
-     * @return message
+     * @return message or null if SM has quit
      */
     public final Message obtainMessage()
     {
+        if (mSmHandler == null) return null;
+
         return Message.obtain(mSmHandler);
     }
 
@@ -1354,9 +1380,11 @@
      * Get a message and set Message.target = this and what
      *
      * @param what is the assigned to Message.what.
-     * @return message
+     * @return message or null if SM has quit
      */
     public final Message obtainMessage(int what) {
+        if (mSmHandler == null) return null;
+
         return Message.obtain(mSmHandler, what);
     }
 
@@ -1366,10 +1394,12 @@
      *
      * @param what is the assigned to Message.what.
      * @param obj is assigned to Message.obj.
-     * @return message
+     * @return message or null if SM has quit
      */
     public final Message obtainMessage(int what, Object obj)
     {
+        if (mSmHandler == null) return null;
+
         return Message.obtain(mSmHandler, what, obj);
     }
 
@@ -1380,10 +1410,13 @@
      * @param what  is assigned to Message.what
      * @param arg1  is assigned to Message.arg1
      * @param arg2  is assigned to Message.arg2
-     * @return  A Message object from the global pool.
+     * @return  A Message object from the global pool or null if
+     *          SM has quit
      */
     public final Message obtainMessage(int what, int arg1, int arg2)
     {
+        if (mSmHandler == null) return null;
+
         return Message.obtain(mSmHandler, what, arg1, arg2);
     }
 
@@ -1395,10 +1428,13 @@
      * @param arg1  is assigned to Message.arg1
      * @param arg2  is assigned to Message.arg2
      * @param obj is assigned to Message.obj
-     * @return  A Message object from the global pool.
+     * @return  A Message object from the global pool or null if
+     *          SM has quit
      */
     public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
     {
+        if (mSmHandler == null) return null;
+
         return Message.obtain(mSmHandler, what, arg1, arg2, obj);
     }
 
@@ -1406,6 +1442,9 @@
      * Enqueue a message to this state machine.
      */
     public final void sendMessage(int what) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessage(obtainMessage(what));
     }
 
@@ -1413,6 +1452,9 @@
      * Enqueue a message to this state machine.
      */
     public final void sendMessage(int what, Object obj) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessage(obtainMessage(what,obj));
     }
 
@@ -1420,6 +1462,9 @@
      * Enqueue a message to this state machine.
      */
     public final void sendMessage(Message msg) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessage(msg);
     }
 
@@ -1427,6 +1472,9 @@
      * Enqueue a message to this state machine after a delay.
      */
     public final void sendMessageDelayed(int what, long delayMillis) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);
     }
 
@@ -1434,6 +1482,9 @@
      * Enqueue a message to this state machine after a delay.
      */
     public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
     }
 
@@ -1441,6 +1492,9 @@
      * Enqueue a message to this state machine after a delay.
      */
     public final void sendMessageDelayed(Message msg, long delayMillis) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.sendMessageDelayed(msg, delayMillis);
     }
 
@@ -1485,6 +1539,9 @@
      * will be processed.
      */
     public final void quit() {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.quit();
     }
 
@@ -1499,6 +1556,9 @@
      * @return if debugging is enabled
      */
     public boolean isDbg() {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return false;
+
         return mSmHandler.isDbg();
     }
 
@@ -1508,6 +1568,9 @@
      * @param dbg is true to enable debugging.
      */
     public void setDbg(boolean dbg) {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         mSmHandler.setDbg(dbg);
     }
 
@@ -1515,6 +1578,9 @@
      * Start the state machine.
      */
     public void start() {
+        // mSmHandler can be null if the state machine has quit.
+        if (mSmHandler == null) return;
+
         /** Send the complete construction message */
         mSmHandler.completeConstruction();
     }
diff --git a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
index 18076c4..7317ecf 100644
--- a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
+++ b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
@@ -22,6 +22,7 @@
 /** {@hide} */
 interface IRemoteViewsFactory {
     void onDataSetChanged();
+    oneway void onDataSetChangedAsync();
     oneway void onDestroy(in Intent intent);
     int getCount();
     RemoteViews getViewAt(int position);
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index b7bc366..25b0065 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -29,6 +29,7 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
@@ -392,7 +393,11 @@
             final ActionBar.Tab tab = mTab;
             final View custom = tab.getCustomView();
             if (custom != null) {
-                addView(custom);
+                final ViewParent customParent = custom.getParent();
+                if (customParent != this) {
+                    if (customParent != null) ((ViewGroup) customParent).removeView(custom);
+                    addView(custom);
+                }
                 mCustomView = custom;
                 if (mTextView != null) mTextView.setVisibility(GONE);
                 if (mIconView != null) {
diff --git a/core/jni/android/graphics/HarfbuzzSkia.cpp b/core/jni/android/graphics/HarfbuzzSkia.cpp
index 92c743f..f6f7b45 100644
--- a/core/jni/android/graphics/HarfbuzzSkia.cpp
+++ b/core/jni/android/graphics/HarfbuzzSkia.cpp
@@ -211,22 +211,7 @@
 
 HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len)
 {
-    FontData* data = reinterpret_cast<FontData*>(voidface);
-    SkTypeface* typeface = data->typeFace;
-
-    const size_t tableSize = SkFontHost::GetTableSize(typeface->uniqueID(), tag);
-    if (!tableSize)
-        return HB_Err_Invalid_Argument;
-    // If Harfbuzz specified a NULL buffer then it's asking for the size of the table.
-    if (!buffer) {
-        *len = tableSize;
-        return HB_Err_Ok;
-    }
-
-    if (*len < tableSize)
-        return HB_Err_Invalid_Argument;
-    SkFontHost::GetTableData(typeface->uniqueID(), tag, 0, tableSize, buffer);
-    return HB_Err_Ok;
+    return HB_Err_Invalid_Argument;
 }
 
 }  // namespace android
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 7076e2a..662d918 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -346,9 +346,6 @@
     font->x_scale = 1;
     font->y_scale = 1;
 
-    shaperItem.font = font;
-    shaperItem.face = HB_NewFace(shaperItem.font, harfbuzzSkiaGetTable);
-
     // Reset kerning
     shaperItem.kerning_applied = false;
 
@@ -360,17 +357,17 @@
     fontData->flags = paint->getFlags();
     fontData->hinting = paint->getHinting();
 
+    shaperItem.font = font;
     shaperItem.font->userData = fontData;
 
+    shaperItem.face = HB_NewFace(NULL, harfbuzzSkiaGetTable);
+
     // We cannot know, ahead of time, how many glyphs a given script run
     // will produce. We take a guess that script runs will not produce more
     // than twice as many glyphs as there are code points plus a bit of
     // padding and fallback if we find that we are wrong.
     createGlyphArrays(shaperItem, (contextCount + 2) * 2);
 
-    // Create log clusters array
-    shaperItem.log_clusters = new unsigned short[contextCount];
-
     // Set the string properties
     shaperItem.string = chars;
     shaperItem.stringLength = contextCount;
@@ -378,7 +375,6 @@
 
 void TextLayoutCacheValue::freeShaperItem(HB_ShaperItem& shaperItem) {
     deleteGlyphArrays(shaperItem);
-    delete[] shaperItem.log_clusters;
     HB_FreeFace(shaperItem.face);
 }
 
@@ -392,6 +388,7 @@
     shaperItem.item.script = isRTL ? HB_Script_Arabic : HB_Script_Common;
 
     // Shape
+    assert(shaperItem.item.length > 0); // Harfbuzz will overwrite other memory if length is 0.
     while (!HB_ShapeItem(&shaperItem)) {
         // We overflowed our arrays. Resize and retry.
         // HB_ShapeItem fills in shaperItem.num_glyphs with the needed size.
@@ -404,6 +401,10 @@
         size_t start, size_t count, size_t contextCount, int dirFlags,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
         Vector<jchar>* const outGlyphs) {
+        if (!count) {
+            *outTotalAdvance = 0;
+            return;
+        }
 
         UBiDiLevel bidiReq = 0;
         bool forceLTR = false;
@@ -544,6 +545,10 @@
         size_t start, size_t count, bool isRTL,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
         Vector<jchar>* const outGlyphs) {
+    if (!count) {
+        *outTotalAdvance = 0;
+        return;
+    }
 
     shapeRun(shaperItem, start, count, isRTL);
 
@@ -607,14 +612,22 @@
     delete[] shaperItem.attributes;
     delete[] shaperItem.advances;
     delete[] shaperItem.offsets;
+    delete[] shaperItem.log_clusters;
 }
 
 void TextLayoutCacheValue::createGlyphArrays(HB_ShaperItem& shaperItem, int size) {
+    shaperItem.num_glyphs = size;
+
+    // These arrays are all indexed by glyph
     shaperItem.glyphs = new HB_Glyph[size];
     shaperItem.attributes = new HB_GlyphAttributes[size];
     shaperItem.advances = new HB_Fixed[size];
     shaperItem.offsets = new HB_FixedPoint[size];
-    shaperItem.num_glyphs = size;
+
+    // Although the log_clusters array is indexed by character, Harfbuzz expects that
+    // it is big enough to hold one element per glyph.  So we allocate log_clusters along
+    // with the other glyph arrays above.
+    shaperItem.log_clusters = new unsigned short[size];
 }
 
 } // namespace android
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 4f75fad..426f4f7 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -23,6 +23,7 @@
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <cutils/properties.h>
 #include <utils/ResourceTypes.h>
 
 #include <gui/SurfaceTexture.h>
@@ -736,7 +737,15 @@
 
 static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
 #ifdef USE_OPENGL_RENDERER
-    return JNI_TRUE;
+    char prop[PROPERTY_VALUE_MAX];
+    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
+        // not in the emulator
+        return JNI_TRUE;
+    }
+    // In the emulator this property will be set to 1 when hardware GLES is
+    // enabled, 0 otherwise. On old emulator versions it will be undefined.
+    property_get("ro.kernel.qemu.gles", prop, "0");
+    return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
 #else
     return JNI_FALSE;
 #endif
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 49441eb..bba4b47 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -752,6 +752,25 @@
     }
 }
 
+static void Surface_transferFrom(
+        JNIEnv* env, jobject clazz, jobject other)
+{
+    if (clazz == other)
+        return;
+
+    if (other == NULL) {
+        doThrowNPE(env);
+        return;
+    }
+
+    sp<SurfaceControl> control(getSurfaceControl(env, other));
+    sp<Surface> surface(Surface_getSurface(env, other));
+    setSurfaceControl(env, clazz, control);
+    setSurface(env, clazz, surface);
+    setSurfaceControl(env, other, 0);
+    setSurface(env, other, 0);
+}
+
 static void Surface_readFromParcel(
         JNIEnv* env, jobject clazz, jobject argParcel)
 {
@@ -820,6 +839,7 @@
     {"destroy",             "()V",  (void*)Surface_destroy },
     {"release",             "()V",  (void*)Surface_release },
     {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
+    {"transferFrom",        "(Landroid/view/Surface;)V",  (void*)Surface_transferFrom },
     {"isValid",             "()Z",  (void*)Surface_isValid },
     {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
     {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
diff --git a/core/res/res/anim/app_starting_exit.xml b/core/res/res/anim/app_starting_exit.xml
index ee8d80b..60e4109 100644
--- a/core/res/res/anim/app_starting_exit.xml
+++ b/core/res/res/anim/app_starting_exit.xml
@@ -18,7 +18,8 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:detachWallpaper="true" android:interpolator="@interpolator/decelerate_quad">
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="160" />
 </set>
 
diff --git a/core/res/res/drawable/silent_mode_indicator.xml b/core/res/res/drawable/silent_mode_indicator.xml
new file mode 100644
index 0000000..c4e129f
--- /dev/null
+++ b/core/res/res/drawable/silent_mode_indicator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="false" android:drawable="@android:color/transparent" />
+    <item android:state_selected="true"  android:drawable="@drawable/tab_selected_holo" />
+</selector>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index f972843..7a5bb6a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -134,6 +134,7 @@
                 android:layout_marginTop="5dip"
                 android:keyBackground="@drawable/btn_keyboard_key_ics"
                 android:visibility="gone"
+                android:clickable="true"
             />
 
             <!-- Emergency call button. Generally not used on tablet devices. -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 8b65b22..6df22ca 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -133,6 +133,7 @@
             android:background="#40000000"
             android:keyBackground="@drawable/btn_keyboard_key_ics"
             android:layout_marginBottom="80dip"
+            android:clickable="true"
         />
 
         <!-- emergency call button -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
index c65dd83..0b94fc1 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
@@ -93,17 +93,6 @@
         android:layout_marginLeft="8dip"
         android:layout_marginRight="8dip">
 
-        <Button android:id="@+id/ok"
-            android:text="@android:string/ok"
-            android:layout_alignParentBottom="true"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1.0"
-            android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
-            android:textSize="18sp"
-            />
-
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
@@ -112,11 +101,22 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginRight="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="8dip"
         />
+
+        <Button android:id="@+id/ok"
+            android:text="@android:string/ok"
+            android:layout_alignParentBottom="true"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.0"
+            android:layout_marginBottom="8dip"
+            android:layout_marginLeft="8dip"
+            android:textSize="18sp"
+        />
     </LinearLayout>
 
 </RelativeLayout>
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 6f0517d..9c1def2 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -32,7 +32,6 @@
     <LinearLayout android:id="@+id/pickers"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="22dip"
         android:layout_weight="1"
         android:orientation="horizontal"
         android:gravity="center">
@@ -77,7 +76,7 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="22dip"
+        android:layout_marginLeft="44dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index 67b1644..694301e 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -14,48 +14,46 @@
      limitations under the License.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- RelativeLayouts have an issue enforcing minimum heights, so just
+     work around this for now with LinearLayouts. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:orientation="horizontal"
 
-    android:paddingLeft="11dip"
+    android:paddingLeft="16dip"
     android:paddingTop="6dip"
     android:paddingBottom="6dip"
     >
-
     <ImageView android:id="@+id/icon"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentBottom="true"
-        android:layout_marginRight="9dip"
-            />
-
-
-    <TextView android:id="@+id/status"
-        android:layout_width="match_parent"
-        android:layout_height="26dip"
-
-        android:layout_toRightOf="@id/icon"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentRight="true"
-
-        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:layout_gravity="center"
+        android:layout_marginRight="16dip"
         />
 
-
-    <TextView android:id="@+id/message"
+    <LinearLayout
+        android:orientation="vertical"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        >
+        <TextView android:id="@+id/message"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top"
 
-        android:layout_toRightOf="@id/icon"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:layout_above="@id/status"
-        android:layout_alignWithParentIfMissing="true"
-        android:gravity="center_vertical"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        />
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            />
+        <TextView android:id="@+id/status"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom"
+            android:minHeight="26dp"
 
-
-</RelativeLayout>
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/global_actions_silent_mode.xml b/core/res/res/layout/global_actions_silent_mode.xml
new file mode 100644
index 0000000..18b4715
--- /dev/null
+++ b/core/res/res/layout/global_actions_silent_mode.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:orientation="horizontal"
+    >
+
+    <LinearLayout
+        android:id="@+id/option1"
+        android:layout_width="64dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/actionBarItemBackground"
+        android:contentDescription="@string/silent_mode_silent"
+        android:focusable="true"
+        >
+        <ImageView
+            android:layout_width="48dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
+            android:layout_marginTop="6dp"
+            android:layout_marginBottom="6dp"
+            android:src="@drawable/ic_audio_vol_mute"
+            android:scaleType="center"
+            android:duplicateParentState="true"
+            android:background="@drawable/silent_mode_indicator"
+            />
+    </LinearLayout>
+    <!-- Spacer -->
+    <View android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible"/>
+
+    <LinearLayout
+        android:id="@+id/option2"
+        android:layout_width="64dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/actionBarItemBackground"
+        android:contentDescription="@string/silent_mode_vibrate"
+        android:focusable="true"
+        >
+        <ImageView
+            android:layout_width="48dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
+            android:layout_marginTop="6dp"
+            android:layout_marginBottom="6dp"
+            android:src="@drawable/ic_audio_ring_notif_vibrate"
+            android:scaleType="center"
+            android:duplicateParentState="true"
+            android:background="@drawable/silent_mode_indicator"
+            />
+    </LinearLayout>
+
+    <!-- Spacer -->
+    <View android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible"/>
+
+    <LinearLayout
+        android:id="@+id/option3"
+        android:layout_width="64dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/actionBarItemBackground"
+        android:contentDescription="@string/silent_mode_ring"
+        android:focusable="true"
+        >
+        <ImageView
+            android:layout_width="48dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
+            android:layout_marginTop="6dp"
+            android:layout_marginBottom="6dp"
+            android:src="@drawable/ic_audio_vol"
+            android:scaleType="center"
+            android:duplicateParentState="true"
+            android:background="@drawable/silent_mode_indicator"
+            />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index ba0c22f..e95553f 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -193,6 +193,7 @@
         android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
         android:visibility="gone"
         android:layout_rowSpan="7"
+        android:clickable="true"
     />
 
     <!-- Music transport control -->
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index f6933c3..053acb2 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -157,6 +157,7 @@
         android:background="#40000000"
         android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
         android:visibility="gone"
+        android:clickable="true"
     />
 
     <TextView
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 59065e1..3cb19c3 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -91,17 +91,6 @@
         android:layout_marginLeft="8dip"
         android:layout_marginRight="8dip">
 
-        <Button android:id="@+id/ok"
-            android:text="@android:string/ok"
-            android:layout_alignParentBottom="true"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1.0"
-            android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
-            android:textSize="18sp"
-            />
-
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
@@ -110,11 +99,22 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginRight="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
         />
+
+        <Button android:id="@+id/ok"
+            android:text="@android:string/ok"
+            android:layout_alignParentBottom="true"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.0"
+            android:layout_marginBottom="8dip"
+            android:layout_marginLeft="8dip"
+            android:textSize="18sp"
+        />
     </LinearLayout>
 
 </RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
index b662e82..722dc26 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -153,17 +153,6 @@
         android:layout_marginLeft="8dip"
         android:layout_marginRight="8dip">
 
-        <Button android:id="@+id/ok"
-            android:text="@android:string/ok"
-            android:layout_alignParentBottom="true"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1.0"
-            android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
-            android:textSize="18sp"
-            />
-
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
@@ -172,11 +161,22 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginRight="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
         />
+
+        <Button android:id="@+id/ok"
+            android:text="@android:string/ok"
+            android:layout_alignParentBottom="true"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.0"
+            android:layout_marginBottom="8dip"
+            android:layout_marginLeft="8dip"
+            android:textSize="18sp"
+        />
     </LinearLayout>
 
 </RelativeLayout>
diff --git a/core/res/res/layout/twelve_key_entry.xml b/core/res/res/layout/twelve_key_entry.xml
index 46301cd..09c749d 100644
--- a/core/res/res/layout/twelve_key_entry.xml
+++ b/core/res/res/layout/twelve_key_entry.xml
@@ -144,7 +144,7 @@
         android:layout_marginRight="2dip"
         android:orientation="horizontal">
 
-        <Button android:id="@+id/ok"
+        <Button android:id="@+id/cancel"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
@@ -152,7 +152,7 @@
             android:layout_marginRight="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
-            android:text="@android:string/ok"
+            android:text="@android:string/cancel"
         />
 
         <Button android:id="@+id/zero"
@@ -165,7 +165,7 @@
             android:textStyle="bold"
         />
 
-        <Button android:id="@+id/cancel"
+        <Button android:id="@+id/ok"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
@@ -173,7 +173,7 @@
             android:layout_marginRight="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
-            android:text="@android:string/cancel"
+            android:text="@android:string/ok"
         />
 
     </LinearLayout>
diff --git a/core/res/res/values-af/donottranslate-cldr.xml b/core/res/res/values-af/donottranslate-cldr.xml
new file mode 100644
index 0000000..9d38717
--- /dev/null
+++ b/core/res/res/values-af/donottranslate-cldr.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">Januarie</string>
+    <string name="month_long_standalone_february">Februarie</string>
+    <string name="month_long_standalone_march">Maart</string>
+    <string name="month_long_standalone_april">April</string>
+    <string name="month_long_standalone_may">Mei</string>
+    <string name="month_long_standalone_june">Junie</string>
+    <string name="month_long_standalone_july">Julie</string>
+    <string name="month_long_standalone_august">Augustus</string>
+    <string name="month_long_standalone_september">September</string>
+    <string name="month_long_standalone_october">Oktober</string>
+    <string name="month_long_standalone_november">November</string>
+    <string name="month_long_standalone_december">Desember</string>
+
+    <string name="month_long_january">Januarie</string>
+    <string name="month_long_february">Februarie</string>
+    <string name="month_long_march">Maart</string>
+    <string name="month_long_april">April</string>
+    <string name="month_long_may">Mei</string>
+    <string name="month_long_june">Junie</string>
+    <string name="month_long_july">Julie</string>
+    <string name="month_long_august">Augustus</string>
+    <string name="month_long_september">September</string>
+    <string name="month_long_october">Oktober</string>
+    <string name="month_long_november">November</string>
+    <string name="month_long_december">Desember</string>
+
+    <string name="month_medium_january">Jan</string>
+    <string name="month_medium_february">Feb</string>
+    <string name="month_medium_march">Mar</string>
+    <string name="month_medium_april">Apr</string>
+    <string name="month_medium_may">Mei</string>
+    <string name="month_medium_june">Jun</string>
+    <string name="month_medium_july">Jul</string>
+    <string name="month_medium_august">Aug</string>
+    <string name="month_medium_september">Sep</string>
+    <string name="month_medium_october">Okt</string>
+    <string name="month_medium_november">Nov</string>
+    <string name="month_medium_december">Des</string>
+
+    <string name="month_shortest_january">1</string>
+    <string name="month_shortest_february">2</string>
+    <string name="month_shortest_march">3</string>
+    <string name="month_shortest_april">4</string>
+    <string name="month_shortest_may">5</string>
+    <string name="month_shortest_june">6</string>
+    <string name="month_shortest_july">7</string>
+    <string name="month_shortest_august">8</string>
+    <string name="month_shortest_september">9</string>
+    <string name="month_shortest_october">10</string>
+    <string name="month_shortest_november">11</string>
+    <string name="month_shortest_december">12</string>
+
+    <string name="day_of_week_long_sunday">Sondag</string>
+    <string name="day_of_week_long_monday">Maandag</string>
+    <string name="day_of_week_long_tuesday">Dinsdag</string>
+    <string name="day_of_week_long_wednesday">Woensdag</string>
+    <string name="day_of_week_long_thursday">Donderdag</string>
+    <string name="day_of_week_long_friday">Vrydag</string>
+    <string name="day_of_week_long_saturday">Saterdag</string>
+
+    <string name="day_of_week_medium_sunday">So</string>
+    <string name="day_of_week_medium_monday">Ma</string>
+    <string name="day_of_week_medium_tuesday">Di</string>
+    <string name="day_of_week_medium_wednesday">Wo</string>
+    <string name="day_of_week_medium_thursday">Do</string>
+    <string name="day_of_week_medium_friday">Vr</string>
+    <string name="day_of_week_medium_saturday">Sa</string>
+
+    <string name="day_of_week_short_sunday">So</string>
+    <string name="day_of_week_short_monday">Ma</string>
+    <string name="day_of_week_short_tuesday">Di</string>
+    <string name="day_of_week_short_wednesday">Wo</string>
+    <string name="day_of_week_short_thursday">Do</string>
+    <string name="day_of_week_short_friday">Vr</string>
+    <string name="day_of_week_short_saturday">Sa</string>
+
+    <string name="day_of_week_shortest_sunday">1</string>
+    <string name="day_of_week_shortest_monday">2</string>
+    <string name="day_of_week_shortest_tuesday">3</string>
+    <string name="day_of_week_shortest_wednesday">4</string>
+    <string name="day_of_week_shortest_thursday">5</string>
+    <string name="day_of_week_shortest_friday">6</string>
+    <string name="day_of_week_shortest_saturday">7</string>
+
+    <string name="am">vm.</string>
+    <string name="pm">nm.</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%Y/%m/%d</string>
+    <string name="numeric_date_format">yyyy/MM/dd</string>
+    <string name="numeric_date_template">"%s/%s/%s"</string>
+    <string name="month_day_year">%d %B %Y</string>
+    <string name="time_of_day">%-l:%M:%S %p</string>
+    <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%d %b %Y</string>
+    <string name="month_day">%-e %B</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%Y %b</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s - %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s - %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s/%2$s/%3$s - %10$s %9$s/%7$s/%8$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s %2$s %3$s - %10$s %9$s %7$s %8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s %2$s %3$s - %10$s %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_md1_md2">%2$s %3$s-%8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s %2$s %3$s - %7$s %8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s %2$s %3$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s %2$s %3$s - %6$s, y %7$s %8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, y MMM dd</string>
+</resources>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 168030c..cb235ba 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -634,7 +634,7 @@
     <string name="relationTypeParent" msgid="4755635567562925226">"Ouer"</string>
     <string name="relationTypePartner" msgid="7266490285120262781">"Vennoot"</string>
     <string name="relationTypeReferredBy" msgid="101573059844135524">"Verwys deur"</string>
-    <string name="relationTypeRelative" msgid="1799819930085610271">"Relatief"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Familielid"</string>
     <string name="relationTypeSister" msgid="1735983554479076481">"Suster"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Eggenoot"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Gepasmaakte"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Oop Wi-Fi-netwerke beskikbaar"</item>
     <item quantity="other" msgid="7915895323644292768">"Oop Wi-Fi-netwerke beskikbaar"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Meld aan by Wi-Fi-netwerk"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kon nie aan Wi-Fikoppel nie"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" het \'n swak internetverbinding."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1219,6 +1222,6 @@
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Toestel gesluit."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
     <string name="sending" msgid="8715108995741758718">"Stuur tans..."</string>
-    <string name="launchBrowserDefault" msgid="2057951947297614725">"Begin Browser?"</string>
-    <string name="SetupCallDefault" msgid="6870275517518479651">"Aanvaar Bel?"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Begin webblaaier?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Aanvaar oproep?"</string>
 </resources>
diff --git a/core/res/res/values-am/donottranslate-cldr.xml b/core/res/res/values-am/donottranslate-cldr.xml
new file mode 100644
index 0000000..2319fbf
--- /dev/null
+++ b/core/res/res/values-am/donottranslate-cldr.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">ጃንዩወሪ</string>
+    <string name="month_long_standalone_february">ፌብሩወሪ</string>
+    <string name="month_long_standalone_march">ማርች</string>
+    <string name="month_long_standalone_april">ኤፕረል</string>
+    <string name="month_long_standalone_may">ሜይ</string>
+    <string name="month_long_standalone_june">ጁን</string>
+    <string name="month_long_standalone_july">ጁላይ</string>
+    <string name="month_long_standalone_august">ኦገስት</string>
+    <string name="month_long_standalone_september">ሴፕቴምበር</string>
+    <string name="month_long_standalone_october">ኦክተውበር</string>
+    <string name="month_long_standalone_november">ኖቬምበር</string>
+    <string name="month_long_standalone_december">ዲሴምበር</string>
+
+    <string name="month_long_january">ጃንዩወሪ</string>
+    <string name="month_long_february">ፌብሩወሪ</string>
+    <string name="month_long_march">ማርች</string>
+    <string name="month_long_april">ኤፕረል</string>
+    <string name="month_long_may">ሜይ</string>
+    <string name="month_long_june">ጁን</string>
+    <string name="month_long_july">ጁላይ</string>
+    <string name="month_long_august">ኦገስት</string>
+    <string name="month_long_september">ሴፕቴምበር</string>
+    <string name="month_long_october">ኦክተውበር</string>
+    <string name="month_long_november">ኖቬምበር</string>
+    <string name="month_long_december">ዲሴምበር</string>
+
+    <string name="month_medium_january">ጃንዩ</string>
+    <string name="month_medium_february">ፌብሩ</string>
+    <string name="month_medium_march">ማርች</string>
+    <string name="month_medium_april">ኤፕረ</string>
+    <string name="month_medium_may">ሜይ</string>
+    <string name="month_medium_june">ጁን</string>
+    <string name="month_medium_july">ጁላይ</string>
+    <string name="month_medium_august">ኦገስ</string>
+    <string name="month_medium_september">ሴፕቴ</string>
+    <string name="month_medium_october">ኦክተ</string>
+    <string name="month_medium_november">ኖቬም</string>
+    <string name="month_medium_december">ዲሴም</string>
+
+    <string name="month_shortest_january">ጃ</string>
+    <string name="month_shortest_february">ፌ</string>
+    <string name="month_shortest_march">ማ</string>
+    <string name="month_shortest_april">ኤ</string>
+    <string name="month_shortest_may">ሜ</string>
+    <string name="month_shortest_june">ጁ</string>
+    <string name="month_shortest_july">ጁ</string>
+    <string name="month_shortest_august">ኦ</string>
+    <string name="month_shortest_september">ሴ</string>
+    <string name="month_shortest_october">ኦ</string>
+    <string name="month_shortest_november">ኖ</string>
+    <string name="month_shortest_december">ዲ</string>
+
+    <string name="day_of_week_long_sunday">እሑድ</string>
+    <string name="day_of_week_long_monday">ሰኞ</string>
+    <string name="day_of_week_long_tuesday">ማክሰኞ</string>
+    <string name="day_of_week_long_wednesday">ረቡዕ</string>
+    <string name="day_of_week_long_thursday">ሐሙስ</string>
+    <string name="day_of_week_long_friday">ዓርብ</string>
+    <string name="day_of_week_long_saturday">ቅዳሜ</string>
+
+    <string name="day_of_week_medium_sunday">እሑድ</string>
+    <string name="day_of_week_medium_monday">ሰኞ</string>
+    <string name="day_of_week_medium_tuesday">ማክሰ</string>
+    <string name="day_of_week_medium_wednesday">ረቡዕ</string>
+    <string name="day_of_week_medium_thursday">ሐሙስ</string>
+    <string name="day_of_week_medium_friday">ዓርብ</string>
+    <string name="day_of_week_medium_saturday">ቅዳሜ</string>
+
+    <string name="day_of_week_short_sunday">እሑድ</string>
+    <string name="day_of_week_short_monday">ሰኞ</string>
+    <string name="day_of_week_short_tuesday">ማክሰ</string>
+    <string name="day_of_week_short_wednesday">ረቡዕ</string>
+    <string name="day_of_week_short_thursday">ሐሙስ</string>
+    <string name="day_of_week_short_friday">ዓርብ</string>
+    <string name="day_of_week_short_saturday">ቅዳሜ</string>
+
+    <string name="day_of_week_shortest_sunday">እ</string>
+    <string name="day_of_week_shortest_monday">ሰ</string>
+    <string name="day_of_week_shortest_tuesday">ማ</string>
+    <string name="day_of_week_shortest_wednesday">ረ</string>
+    <string name="day_of_week_shortest_thursday">ሐ</string>
+    <string name="day_of_week_shortest_friday">ዓ</string>
+    <string name="day_of_week_shortest_saturday">ቅ</string>
+
+    <string name="am">ጡዋት</string>
+    <string name="pm">ከሳዓት</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%d/%m/%Y</string>
+    <string name="numeric_date_format">dd/MM/yyyy</string>
+    <string name="numeric_date_template">"%s/%s/%s"</string>
+    <string name="month_day_year">%d %B %Y</string>
+    <string name="time_of_day">%-l:%M:%S %p</string>
+    <string name="date_and_time">%-l:%M:%S %p %b %-e %Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%b %-e %Y</string>
+    <string name="month_day">%B %-e</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%Y %b</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s - %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s - %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s %2$s %3$s - %10$s %9$s %7$s %8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s %2$s %3$s - %10$s %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_md1_md2">%2$s %3$s-%8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s %2$s %3$s - %7$s %8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s %2$s %3$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s %2$s %3$s - %6$s, y %7$s %8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, y MMM dd</string>
+</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 728ef4c..c51ca35 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"አውታረ መረብ ሲኖር Wi-Fi ክፈት"</item>
     <item quantity="other" msgid="7915895323644292768">"አውታረ መረቦች ሲኖሩ Wi-Fi ክፈት"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ደካማ የበይነመረብ ግንኙነት ኣለው፡፡"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ቀጥታ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a07106b..120a001 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"هناك شبكة Wi-Fi مفتوحة متاحة"</item>
     <item quantity="other" msgid="7915895323644292768">"هناك شبكات Wi-Fi مفتوحة متاحة"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"تعذر الاتصال بـ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" تحتوي على اتصال إنترنت ضعيف."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"اتصال Wi-Fi مباشر"</string>
diff --git a/core/res/res/values-be/donottranslate-cldr.xml b/core/res/res/values-be/donottranslate-cldr.xml
new file mode 100644
index 0000000..365e60d
--- /dev/null
+++ b/core/res/res/values-be/donottranslate-cldr.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_may">травень</string>
+
+    <string name="month_long_january">студзень</string>
+    <string name="month_long_february">люты</string>
+    <string name="month_long_march">сакавік</string>
+    <string name="month_long_april">красавік</string>
+    <string name="month_long_may">май</string>
+    <string name="month_long_june">чэрвень</string>
+    <string name="month_long_july">ліпень</string>
+    <string name="month_long_august">жнівень</string>
+    <string name="month_long_september">верасень</string>
+    <string name="month_long_october">кастрычнік</string>
+    <string name="month_long_november">лістапад</string>
+    <string name="month_long_december">снежань</string>
+
+    <string name="month_medium_january">сту</string>
+    <string name="month_medium_february">лют</string>
+    <string name="month_medium_march">сак</string>
+    <string name="month_medium_april">кра</string>
+    <string name="month_medium_may">май</string>
+    <string name="month_medium_june">чэр</string>
+    <string name="month_medium_july">ліп</string>
+    <string name="month_medium_august">жні</string>
+    <string name="month_medium_september">вер</string>
+    <string name="month_medium_october">кас</string>
+    <string name="month_medium_november">ліс</string>
+    <string name="month_medium_december">сне</string>
+
+    <string name="month_shortest_january">с</string>
+    <string name="month_shortest_february">л</string>
+    <string name="month_shortest_march">с</string>
+    <string name="month_shortest_april">к</string>
+    <string name="month_shortest_may">м</string>
+    <string name="month_shortest_june">ч</string>
+    <string name="month_shortest_july">л</string>
+    <string name="month_shortest_august">ж</string>
+    <string name="month_shortest_september">в</string>
+    <string name="month_shortest_october">к</string>
+    <string name="month_shortest_november">л</string>
+    <string name="month_shortest_december">с</string>
+
+    <string name="day_of_week_long_sunday">нядзеля</string>
+    <string name="day_of_week_long_monday">панядзелак</string>
+    <string name="day_of_week_long_tuesday">аўторак</string>
+    <string name="day_of_week_long_wednesday">серада</string>
+    <string name="day_of_week_long_thursday">чацвер</string>
+    <string name="day_of_week_long_friday">пятніца</string>
+    <string name="day_of_week_long_saturday">субота</string>
+
+    <string name="day_of_week_medium_sunday">нд</string>
+    <string name="day_of_week_medium_monday">пн</string>
+    <string name="day_of_week_medium_tuesday">аў</string>
+    <string name="day_of_week_medium_wednesday">ср</string>
+    <string name="day_of_week_medium_thursday">чц</string>
+    <string name="day_of_week_medium_friday">пт</string>
+    <string name="day_of_week_medium_saturday">сб</string>
+
+    <string name="day_of_week_short_sunday">нд</string>
+    <string name="day_of_week_short_monday">пн</string>
+    <string name="day_of_week_short_tuesday">аў</string>
+    <string name="day_of_week_short_wednesday">ср</string>
+    <string name="day_of_week_short_thursday">чц</string>
+    <string name="day_of_week_short_friday">пт</string>
+    <string name="day_of_week_short_saturday">сб</string>
+
+    <string name="day_of_week_shortest_sunday">н</string>
+    <string name="day_of_week_shortest_monday">п</string>
+    <string name="day_of_week_shortest_tuesday">а</string>
+    <string name="day_of_week_shortest_wednesday">с</string>
+    <string name="day_of_week_shortest_thursday">ч</string>
+    <string name="day_of_week_shortest_friday">п</string>
+    <string name="day_of_week_shortest_saturday">с</string>
+
+    <string name="am">да палудня</string>
+    <string name="pm">пасля палудня</string>
+    <string name="yesterday">учора</string>
+    <string name="today">сёння</string>
+    <string name="tomorrow">заўтра</string>
+
+    <string name="hour_minute_24">%-k.%M</string>
+    <string name="hour_minute_ampm">%-l.%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l.%M %p</string>
+    <string name="twelve_hour_time_format">h.mm a</string>
+    <string name="twenty_four_hour_time_format">H.mm</string>
+    <string name="numeric_date">%-e.%-m.%Y</string>
+    <string name="numeric_date_format">d.M.yyyy</string>
+    <string name="numeric_date_template">"%s.%s.%s"</string>
+    <string name="month_day_year">%-e %B %Y</string>
+    <string name="time_of_day">%H.%M.%S</string>
+    <string name="date_and_time">%H.%M.%S %-e.%-m.%Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+    <string name="month_day">%B %-e</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
+    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s, %1$s - %7$s %8$s, %6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s, %1$s - %10$s %7$s %8$s, %6$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s, %1$s - %10$s %7$s %8$s, %6$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s, %1$s - %7$s %8$s, %6$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">MMMM d, EEEE</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
+</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 97996ab..8045b40 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Адкрытая сетка Wi-Fi даступная"</item>
     <item quantity="other" msgid="7915895323644292768">"Даступны адкрытыя сеткі Wi-Fi"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Уваход у сетку Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Немагчыма падключыцца да Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" дрэннае падключэнне да Інтэрнэту."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Апублікаваць праз..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Прылада заблакаваная."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Адпраўка..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Запусцiць браўзер?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Адказаць?"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 66b5cae..0a0748f 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Има достъпна отворена Wi-Fi мрежа"</item>
     <item quantity="other" msgid="7915895323644292768">"Има достъпни отворени Wi-Fi мрежи"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Влизане в Wi-Fi мрежа"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можа да се свърже с Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" има лоша връзка с интернет."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Споделяне със..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Устройството е заключено."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Изпраща се..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Да се стартира ли браузърът?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Да се приеме ли обаждането?"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 09ee9cf..8563e1d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Xarxa Wi-fi oberta disponible"</item>
     <item quantity="other" msgid="7915895323644292768">"Xarxes Wi-fi obertes disponibles"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia la sessió a la xarxa Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No s\'ha pogut connectar a la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" té una mala connexió a Internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 74ee156..b45c6d6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Přihlásit se k síti Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Připojení k síti Wi-Fi se nezdařilo"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" má pomalé připojení k internetu."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Přímé připojení sítě Wi-Fi"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Sdílet s..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Zařízení je uzamčeno."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Odesílání..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustit prohlížeč?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Přijmout hovor?"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 465ec4e..5e40ea0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Log ind på Wi-Fi-netværk"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kunne ikke oprette forbindelse til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" har en dårlig internetforbindelse."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med:"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Enhed låst."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Sender..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte browseren?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Vil du besvare opkaldet?"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f77187c..98e3e80 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -160,14 +160,14 @@
     <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Ermöglicht Anwendungen die Ausführung eventuell kostenpflichtiger Aktionen"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Lesen und schreiben Sie Ihre SMS, E-Mails und anderen Nachrichten."</string>
-    <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Meine persönlichen Informationen"</string>
+    <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
     <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Tablets"</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ihren Standort"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Ihren physischen Standort überwachen"</string>
-    <string name="permgrouplab_network" msgid="5808983377727109831">"Netzwerkkommunikation"</string>
+    <string name="permgrouplab_network" msgid="5808983377727109831">"Netzkommunikation"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Ermöglicht Anwendungen den Zugriff auf verschiedene Netzwerkfunktionen"</string>
-    <string name="permgrouplab_accounts" msgid="3359646291125325519">"Meine Konten"</string>
+    <string name="permgrouplab_accounts" msgid="3359646291125325519">"Ihre Konten"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Zugriff auf verfügbare Konten"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardware-Steuerelemente"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkter Zugriff auf Hardware über Headset"</string>
@@ -209,7 +209,7 @@
     <string name="permlab_getTasks" msgid="5005277531132573353">"laufende Apps abrufen"</string>
     <string name="permdesc_getTasks" msgid="7048711358713443341">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausführten Aufgaben abzurufen. Schädliche Anwendungen können so eventuell geheime Informationen zu anderen Anwendungen entdecken."</string>
     <string name="permlab_reorderTasks" msgid="5669588525059921549">"Laufende Apps neu ordnen"</string>
-    <string name="permdesc_reorderTasks" msgid="126252774270522835">"Ermöglicht einer App, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Anwendungen können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
+    <string name="permdesc_reorderTasks" msgid="126252774270522835">"Ermöglicht einer App, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Apps können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
     <string name="permlab_removeTasks" msgid="4802740047161700683">"Aktive Apps beenden"</string>
     <string name="permdesc_removeTasks" msgid="2000332928514575461">"Ermöglicht einer App das Entfernen von Aufgaben und Beenden der entsprechenden Apps. Schädliche Apps können das Verhalten anderer Apps stören."</string>
     <string name="permlab_setDebugApp" msgid="4339730312925176742">"Fehlerbeseitigung für App aktivieren"</string>
@@ -223,7 +223,7 @@
     <string name="permlab_forceStopPackages" msgid="1447830113260156236">"Beenden anderer Anwendungen erzwingen"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Ermöglicht einer App, das Beenden anderer Anwendungen zu erzwingen"</string>
     <string name="permlab_forceBack" msgid="1804196839880393631">"Schließen der App erzwingen"</string>
-    <string name="permdesc_forceBack" msgid="6534109744159919013">"Ermöglicht einer App, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden."</string>
+    <string name="permdesc_forceBack" msgid="6534109744159919013">"Ermöglicht einer App, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Apps benötigt werden."</string>
     <string name="permlab_dump" msgid="1681799862438954752">"Systeminternen Status abrufen"</string>
     <string name="permdesc_dump" msgid="2198776174276275220">"Ermöglicht einer App, den internen Status des Systems abzurufen. Schädliche Apps rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
@@ -298,7 +298,7 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ermöglicht einer App, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Anwendungsressourcen verschieben"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer App, Anwendungsressourcen von internen auf externe Medien zu verschieben und umgekehrt"</string>
-    <string name="permlab_readLogs" msgid="6615778543198967614">"Lesen vertraulicher Protokolldaten"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"Vertrauliche Protokolldaten lesen"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ermöglicht einer App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ermöglicht einer App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Für Wiedergabe beliebigen Mediendecodierer verwenden"</string>
@@ -409,9 +409,9 @@
     <string name="permlab_bindGadget" msgid="776905339015863471">"Widgets auswählen"</string>
     <string name="permdesc_bindGadget" msgid="2098697834497452046">"Ermöglicht der App, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"Telefonstatus ändern"</string>
-    <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer App, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
+    <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer App, die Telefonfunktionen des Geräts zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"Telefonstatus lesen und identifizieren"</string>
-    <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der App, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
+    <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Eine App mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Standby-Modus des Tablets deaktivieren"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Standby-Modus deaktivieren"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ermöglicht einer App, den Standby-Modus des Tablets zu deaktivieren."</string>
@@ -444,7 +444,7 @@
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Ermöglicht einer App, die Kontoauthentifizierungsfunktionen des Konto-Managers zu verwenden, einschließlich die Funktionen zum Erstellen von Konten und zum Abrufen und Einstellen der entsprechenden Passwörter"</string>
     <string name="permlab_manageAccounts" msgid="4440380488312204365">"Kontoliste verwalten"</string>
     <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Ermöglicht einer App, Konten hinzuzufügen und zu entfernen oder deren Passwörter zu löschen"</string>
-    <string name="permlab_useCredentials" msgid="6401886092818819856">"Authentifizierungsinformationen eines Kontos verwenden"</string>
+    <string name="permlab_useCredentials" msgid="6401886092818819856">"Informationen zur Authentifizierung eines Kontos verwenden"</string>
     <string name="permdesc_useCredentials" msgid="7416570544619546974">"Ermöglicht einer App, Authentifizierungs-Token anzufordern"</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"Netzwerkstatus anzeigen"</string>
     <string name="permdesc_accessNetworkState" msgid="558721128707712766">"Ermöglicht einer App, den Status aller Netzwerke anzuzeigen"</string>
@@ -905,9 +905,9 @@
     <string name="aerr_process" msgid="4507058997035697579">"Leider wurde der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> beendet."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht."\n\n"Möchten Sie sie schließen?"</string>
-    <string name="anr_activity_process" msgid="7018289416670457797">"Aktivität <xliff:g id="ACTIVITY">%1$s</xliff:g> reagiert nicht."\n\n"Möchten Sie sie beenden?"</string>
+    <string name="anr_activity_process" msgid="7018289416670457797">"Aktivität \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" reagiert nicht."\n\n"Möchten Sie sie beenden?"</string>
     <string name="anr_application_process" msgid="7208175830253210526">"<xliff:g id="APPLICATION">%1$s</xliff:g> reagiert nicht. Möchten Sie sie schließen?"</string>
-    <string name="anr_process" msgid="306819947562555821">"Prozess <xliff:g id="PROCESS">%1$s</xliff:g> reagiert nicht."\n\n"Möchten Sie ihn beenden?"</string>
+    <string name="anr_process" msgid="306819947562555821">"Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" reagiert nicht."\n\n"Möchten Sie ihn beenden?"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Bericht"</string>
     <string name="wait" msgid="7147118217226317732">"Warten"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Verfügbares WLAN-Netzwerk öffnen"</item>
     <item quantity="other" msgid="7915895323644292768">"Verfügbare WLAN-Netzwerke öffnen"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN-Netzwerk anmelden"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" hat eine schlechte Internetverbindung."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1096,7 +1099,7 @@
     <string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Durch Berühren weitere Informationen zur Mobildatennutzung aufrufen"</string>
     <string name="no_matches" msgid="8129421908915840737">"Keine Treffer"</string>
-    <string name="find_on_page" msgid="1946799233822820384">"Auf Seite suchen"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Suchen"</string>
   <plurals name="matches_found">
     <item quantity="one" msgid="8167147081136579439">"1 Treffer"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> von <xliff:g id="TOTAL">%d</xliff:g>"</item>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Teilen mit..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Gerät gesperrt"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Wird gesendet..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Anruf annehmen?"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 54980a5..f5704a9 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Συνδεθείτε στο δίκτυο Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" έχει κακή σύνδεση Διαδικτύου."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Κοινή χρήση με..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Η συσκευή κλειδώθηκε."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Αποστολή..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Εκκίνηση προγράμματος περιήγησης;"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Αποδοχή κλήσης;"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 7981b52..86f81bb 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -40,7 +40,7 @@
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Service was enabled for:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Service has been disabled."</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"Registration was successful."</string>
-    <string name="serviceErased" msgid="1288584695297200972">"Erasure was successful."</string>
+    <string name="serviceErased" msgid="1288584695297200972">"Erase successful."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"Incorrect password."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI complete."</string>
     <string name="badPin" msgid="5085454289896032547">"The old PIN that you typed is not correct."</string>
@@ -150,9 +150,9 @@
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Silent mode"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sound is OFF"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sound is ON"</string>
-    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
-    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Airplane mode is ON"</string>
-    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Airplane mode is OFF"</string>
+    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
+    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
+    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Open available Wi-Fi network"</item>
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" has a poor Internet connection."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ba79143..6d4067c 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Accede a una red Wi-Fi."</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se pudo conectar a la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" tiene una mala conexión a Internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloqueado"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Envío en curso..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Deseas iniciar el navegador?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"¿Deseas aceptar la llamada?"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a7aeb01..bfd64a2 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -793,7 +793,7 @@
     <string name="last_month" msgid="3959346739979055432">"El mes pasado"</string>
     <string name="older" msgid="5211975022815554840">"Anterior"</string>
   <plurals name="num_days_ago">
-    <item quantity="one" msgid="861358534398115820">"ayer"</item>
+    <item quantity="one" msgid="861358534398115820">"Ayer"</item>
     <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
   </plurals>
   <plurals name="in_num_seconds">
@@ -825,7 +825,7 @@
     <item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
-    <item quantity="one" msgid="8463161711492680309">"ayer"</item>
+    <item quantity="one" msgid="8463161711492680309">"Ayer"</item>
     <item quantity="other" msgid="3453342639616481191">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
   </plurals>
   <plurals name="abbrev_in_num_seconds">
@@ -919,10 +919,10 @@
     <string name="screen_compat_mode_hint" msgid="2953716574198046484">"Vuelve a habilitar esta opción en Ajustes &gt; Aplicaciones &gt; Administrar aplicaciones."</string>
     <string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
-    <string name="android_upgrading_title" msgid="378740715658358071">"Actualizando Android..."</string>
-    <string name="android_upgrading_apk" msgid="274409861603566003">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <string name="android_upgrading_title" msgid="378740715658358071">"Actualizando Android"</string>
+    <string name="android_upgrading_apk" msgid="274409861603566003">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
     <string name="android_upgrading_starting_apps" msgid="7959542881906488763">"Iniciando aplicaciones"</string>
-    <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando arranque"</string>
+    <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando inicio..."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
     <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Seleccionar para cambiar a la aplicación"</string>
     <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"¿Cambiar de aplicación?"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Red Wi-Fi abierta disponible"</item>
     <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abiertas disponibles"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sesión en red Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se ha podido establecer conexión con la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" tiene una mala conexión a Internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloqueado"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Enviando..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Iniciar el navegador?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"¿Aceptar la llamada?"</string>
 </resources>
diff --git a/core/res/res/values-et/donottranslate-cldr.xml b/core/res/res/values-et/donottranslate-cldr.xml
new file mode 100644
index 0000000..d50d041
--- /dev/null
+++ b/core/res/res/values-et/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">jaanuar</string>
+    <string name="month_long_standalone_february">veebruar</string>
+    <string name="month_long_standalone_march">märts</string>
+    <string name="month_long_standalone_april">aprill</string>
+    <string name="month_long_standalone_may">mai</string>
+    <string name="month_long_standalone_june">juuni</string>
+    <string name="month_long_standalone_july">juuli</string>
+    <string name="month_long_standalone_august">august</string>
+    <string name="month_long_standalone_september">september</string>
+    <string name="month_long_standalone_october">oktoober</string>
+    <string name="month_long_standalone_november">november</string>
+    <string name="month_long_standalone_december">detsember</string>
+
+    <string name="month_long_january">jaanuar</string>
+    <string name="month_long_february">veebruar</string>
+    <string name="month_long_march">märts</string>
+    <string name="month_long_april">aprill</string>
+    <string name="month_long_may">mai</string>
+    <string name="month_long_june">juuni</string>
+    <string name="month_long_july">juuli</string>
+    <string name="month_long_august">august</string>
+    <string name="month_long_september">september</string>
+    <string name="month_long_october">oktoober</string>
+    <string name="month_long_november">november</string>
+    <string name="month_long_december">detsember</string>
+
+    <string name="month_medium_january">jaan</string>
+    <string name="month_medium_february">veebr</string>
+    <string name="month_medium_march">märts</string>
+    <string name="month_medium_april">apr</string>
+    <string name="month_medium_may">mai</string>
+    <string name="month_medium_june">juuni</string>
+    <string name="month_medium_july">juuli</string>
+    <string name="month_medium_august">aug</string>
+    <string name="month_medium_september">sept</string>
+    <string name="month_medium_october">okt</string>
+    <string name="month_medium_november">nov</string>
+    <string name="month_medium_december">dets</string>
+
+    <string name="month_shortest_january">1</string>
+    <string name="month_shortest_february">2</string>
+    <string name="month_shortest_march">3</string>
+    <string name="month_shortest_april">4</string>
+    <string name="month_shortest_may">5</string>
+    <string name="month_shortest_june">6</string>
+    <string name="month_shortest_july">7</string>
+    <string name="month_shortest_august">8</string>
+    <string name="month_shortest_september">9</string>
+    <string name="month_shortest_october">10</string>
+    <string name="month_shortest_november">11</string>
+    <string name="month_shortest_december">12</string>
+
+    <string name="day_of_week_long_sunday">pühapäev</string>
+    <string name="day_of_week_long_monday">esmaspäev</string>
+    <string name="day_of_week_long_tuesday">teisipäev</string>
+    <string name="day_of_week_long_wednesday">kolmapäev</string>
+    <string name="day_of_week_long_thursday">neljapäev</string>
+    <string name="day_of_week_long_friday">reede</string>
+    <string name="day_of_week_long_saturday">laupäev</string>
+
+    <string name="day_of_week_medium_sunday">P</string>
+    <string name="day_of_week_medium_monday">E</string>
+    <string name="day_of_week_medium_tuesday">T</string>
+    <string name="day_of_week_medium_wednesday">K</string>
+    <string name="day_of_week_medium_thursday">N</string>
+    <string name="day_of_week_medium_friday">R</string>
+    <string name="day_of_week_medium_saturday">L</string>
+
+    <string name="day_of_week_short_sunday">P</string>
+    <string name="day_of_week_short_monday">E</string>
+    <string name="day_of_week_short_tuesday">T</string>
+    <string name="day_of_week_short_wednesday">K</string>
+    <string name="day_of_week_short_thursday">N</string>
+    <string name="day_of_week_short_friday">R</string>
+    <string name="day_of_week_short_saturday">L</string>
+
+    <string name="day_of_week_shortest_sunday">1</string>
+    <string name="day_of_week_shortest_monday">2</string>
+    <string name="day_of_week_shortest_tuesday">3</string>
+    <string name="day_of_week_shortest_wednesday">4</string>
+    <string name="day_of_week_shortest_thursday">5</string>
+    <string name="day_of_week_shortest_friday">6</string>
+    <string name="day_of_week_shortest_saturday">7</string>
+
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="yesterday">Yesterday</string>
+    <string name="today">Today</string>
+    <string name="tomorrow">Tomorrow</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%d.%m.%Y</string>
+    <string name="numeric_date_format">dd.MM.yyyy</string>
+    <string name="numeric_date_template">"%s.%s.%s"</string>
+    <string name="month_day_year">%-e %B %Y</string>
+    <string name="time_of_day">%-k:%M:%S</string>
+    <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%d.%m.%Y</string>
+    <string name="month_day">%-e %B</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
+    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s - %10$s %6$s, %8$s.%7$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s, %2$s %4$s - %10$s %6$s, %8$s, %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s, %2$s %4$s - %10$s %6$s, %8$s, %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s, %2$s %4$s - %6$s, %8$s, %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s, %2$s - %6$s, %8$s, %7$s %9$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, d, MMM y</string>
+</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4801b32..5870c86 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Avatud WiFi võrk on saadaval"</item>
     <item quantity="other" msgid="7915895323644292768">"Avatud WiFi-võrgud on saadaval"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Logi sisse WiFi-võrku"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ei saanud WiFi-ga ühendust"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" on halb Interneti-ühendus."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WiFi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Jaga kasutaja(te)ga ..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Seade lukustatud."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Saatmine ..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Kas käivitada brauser?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Kas vastata kõnele?"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 02ce1b8..cb4e615 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"شبکه Wi-Fi موجود را باز کنید"</item>
     <item quantity="other" msgid="7915895323644292768">"شبکه های Wi-Fi موجود را باز کنید"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"ورود به شبکه Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"اتصال به Wi-Fi ممکن نیست"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" اتصال اینترنتی ضعیفی دارد."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 49cae50..5c4e1d7 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Kirjaudu wifi-verkkoon"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wifi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" : huono internetyhteys."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Suora wifi-yhteys"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Jaa seuraavien kautta:"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Laite lukittu."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Lähetetään..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Käynnistetäänkö selain?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Vastataanko puheluun?"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4b33998..c04550b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="byteShort" msgid="8340973892742019101">"O"</string>
+    <string name="byteShort" msgid="8340973892742019101">"o"</string>
     <string name="kilobyteShort" msgid="5973789783504771878">"Ko"</string>
     <string name="megabyteShort" msgid="6355851576770428922">"Mo"</string>
     <string name="gigabyteShort" msgid="3259882455212193214">"Go"</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" dispose d\'une mauvaise connexion Internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Partager avec..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Appareil verrouillé"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Envoi en cours…"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer le navigateur ?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Prendre l\'appel ?"</string>
 </resources>
diff --git a/core/res/res/values-hi/donottranslate-cldr.xml b/core/res/res/values-hi/donottranslate-cldr.xml
new file mode 100644
index 0000000..d9405d8
--- /dev/null
+++ b/core/res/res/values-hi/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">जनवरी</string>
+    <string name="month_long_standalone_february">फरवरी</string>
+    <string name="month_long_standalone_march">मार्च</string>
+    <string name="month_long_standalone_april">अप्रैल</string>
+    <string name="month_long_standalone_may">मई</string>
+    <string name="month_long_standalone_june">जून</string>
+    <string name="month_long_standalone_july">जुलाई</string>
+    <string name="month_long_standalone_august">अगस्त</string>
+    <string name="month_long_standalone_september">सितम्बर</string>
+    <string name="month_long_standalone_october">अक्तूबर</string>
+    <string name="month_long_standalone_november">नवम्बर</string>
+    <string name="month_long_standalone_december">दिसम्बर</string>
+
+    <string name="month_long_january">जनवरी</string>
+    <string name="month_long_february">फरवरी</string>
+    <string name="month_long_march">मार्च</string>
+    <string name="month_long_april">अप्रैल</string>
+    <string name="month_long_may">मई</string>
+    <string name="month_long_june">जून</string>
+    <string name="month_long_july">जुलाई</string>
+    <string name="month_long_august">अगस्त</string>
+    <string name="month_long_september">सितम्बर</string>
+    <string name="month_long_october">अक्तूबर</string>
+    <string name="month_long_november">नवम्बर</string>
+    <string name="month_long_december">दिसम्बर</string>
+
+    <string name="month_medium_january">जनवरी</string>
+    <string name="month_medium_february">फरवरी</string>
+    <string name="month_medium_march">मार्च</string>
+    <string name="month_medium_april">अप्रैल</string>
+    <string name="month_medium_may">मई</string>
+    <string name="month_medium_june">जून</string>
+    <string name="month_medium_july">जुलाई</string>
+    <string name="month_medium_august">अगस्त</string>
+    <string name="month_medium_september">सितम्बर</string>
+    <string name="month_medium_october">अक्तूबर</string>
+    <string name="month_medium_november">नवम्बर</string>
+    <string name="month_medium_december">दिसम्बर</string>
+
+    <string name="month_shortest_january">ज</string>
+    <string name="month_shortest_february">फ़</string>
+    <string name="month_shortest_march">मा</string>
+    <string name="month_shortest_april">अ</string>
+    <string name="month_shortest_may">म</string>
+    <string name="month_shortest_june">जू</string>
+    <string name="month_shortest_july">जु</string>
+    <string name="month_shortest_august">अ</string>
+    <string name="month_shortest_september">सि</string>
+    <string name="month_shortest_october">अ</string>
+    <string name="month_shortest_november">न</string>
+    <string name="month_shortest_december">दि</string>
+
+    <string name="day_of_week_long_sunday">रविवार</string>
+    <string name="day_of_week_long_monday">सोमवार</string>
+    <string name="day_of_week_long_tuesday">मंगलवार</string>
+    <string name="day_of_week_long_wednesday">बुधवार</string>
+    <string name="day_of_week_long_thursday">गुरुवार</string>
+    <string name="day_of_week_long_friday">शुक्रवार</string>
+    <string name="day_of_week_long_saturday">शनिवार</string>
+
+    <string name="day_of_week_medium_sunday">रवि</string>
+    <string name="day_of_week_medium_monday">सोम</string>
+    <string name="day_of_week_medium_tuesday">मंगल</string>
+    <string name="day_of_week_medium_wednesday">बुध</string>
+    <string name="day_of_week_medium_thursday">गुरु</string>
+    <string name="day_of_week_medium_friday">शुक्र</string>
+    <string name="day_of_week_medium_saturday">शनि</string>
+
+    <string name="day_of_week_short_sunday">रवि</string>
+    <string name="day_of_week_short_monday">सोम</string>
+    <string name="day_of_week_short_tuesday">मंगल</string>
+    <string name="day_of_week_short_wednesday">बुध</string>
+    <string name="day_of_week_short_thursday">गुरु</string>
+    <string name="day_of_week_short_friday">शुक्र</string>
+    <string name="day_of_week_short_saturday">शनि</string>
+
+    <string name="day_of_week_shortest_sunday">र</string>
+    <string name="day_of_week_shortest_monday">सो</string>
+    <string name="day_of_week_shortest_tuesday">मं</string>
+    <string name="day_of_week_shortest_wednesday">बु</string>
+    <string name="day_of_week_shortest_thursday">गु</string>
+    <string name="day_of_week_shortest_friday">शु</string>
+    <string name="day_of_week_shortest_saturday">श</string>
+
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="yesterday">Yesterday</string>
+    <string name="today">Today</string>
+    <string name="tomorrow">Tomorrow</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%-e-%-m-%Y</string>
+    <string name="numeric_date_format">d-M-yyyy</string>
+    <string name="numeric_date_template">"%s-%s-%s"</string>
+    <string name="month_day_year">%-e %B %Y</string>
+    <string name="time_of_day">%-l:%M:%S %p</string>
+    <string name="date_and_time">%-l:%M:%S %p %d-%m-%Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%d-%m-%Y</string>
+    <string name="month_day">%-e %B</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s/%2$s – %10$s %6$s, %8$s/%7$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s-%2$s-%4$s – %10$s %8$s-%7$s-%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
+</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 7f140f1..6aeb2c1 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"उपलब्‍ध Wi-Fi नेटवर्क खोलें"</item>
     <item quantity="other" msgid="7915895323644292768">"खुले Wi-Fi नेटवर्क उपलब्‍ध है"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi नेटवर्क में साइन इन करें"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi से कनेक्‍ट नहीं हो सका"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" के पास एक कमज़ोर इंटरनेट कनेक्‍शन है."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi प्रत्यक्ष"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"इससे साझा करें..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"उपकरण लॉक कर दिया गया."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"भेज रहा है..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"ब्राउज़र लॉन्च करें?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"कॉल स्वीकार करें?"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0599a6b..f8177e9 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijava na WiFi mrežu"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ne može se spojiti na Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ima lošu internetsku vezu."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Izravni Wi-Fi"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Dijeli sa..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Uređaj zaključan."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Slanje u tijeku..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Pokrenuti preglednik?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Prihvatiti poziv?"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6e395f3..6ce743f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Bejelentkezés Wi-Fi hálózatba"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" rossz internetkapcsolattal rendelkezik."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Megosztás..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Az eszköz le van zárva."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Küldés..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Böngésző indítása?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Hívás fogadása?"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 930c89e..5ab5443 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Jaringan Wi-Fi terbuka tersedia"</item>
     <item quantity="other" msgid="7915895323644292768">"Jaringan Wi-Fi terbuka tersedia"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Masuk ke jaringan Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak dapat tersambung ke Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" memiliki sambungan internet yang buruk."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Langsung"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Berbagi dengan..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Perangkat tergembok."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Mengirim..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Luncurkan Peramban?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Terima Panggilan?"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bd7350d..e56bc1e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Rete Wi-Fi aperta disponibile"</item>
     <item quantity="other" msgid="7915895323644292768">"Reti Wi-Fi aperte disponibili"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Accedi a rete Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossibile connettersi alla rete Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ha una connessione Internet debole."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Condividi con..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Dispositivo bloccato."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Invio..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Avviare l\'applicazione Browser?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Accettare la chiamata?"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7b315c2..2c30c9c 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -901,7 +901,7 @@
     <string name="chooseUsbActivity" msgid="7892597146032121735">"בחר יישום עבור מכשיר ה-USB"</string>
     <string name="noApplications" msgid="1691104391758345586">"אין יישומים שיכולים לבצע פעולה זו."</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"לצערנו ה<xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string>
+    <string name="aerr_application" msgid="932628488013092776">"לצערנו, פעולת ה<xliff:g id="APPLICATION">%1$s</xliff:g> הופסקה."</string>
     <string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב."\n\n" האם ברצונך לסגור אותו?"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"רשת Wi-Fi פתוחה זמינה"</item>
     <item quantity="other" msgid="7915895323644292768">"רשתות Wi-Fi פתוחות זמינות"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"היכנס לרשת WiFi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"אין אפשרות להתחבר ל-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" בעל חיבור גרוע לאינטרנט."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ישיר"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index d0e94c8..b8726d9 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Wi-Fiオープンネットワークが利用できます"</item>
     <item quantity="other" msgid="7915895323644292768">"Wi-Fiオープンネットワークが利用できます"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fiネットワークにログイン"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiに接続できませんでした"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" はインターネット接続に問題があります。"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"共有相手..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"端末がロックされています。"</string>
     <string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"送信しています..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"ブラウザを起動しますか?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"通話を受けますか?"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index fe048be..af2264c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"개방형 Wi-Fi 네트워크 사용 가능"</item>
     <item quantity="other" msgid="7915895323644292768">"개방형 Wi-Fi 네트워크 사용 가능"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi 네트워크에 로그인"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi에 연결할 수 없습니다"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" 인터넷 연결 상태가 좋지 않습니다."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"기기가 잠겼습니다."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"보내는 중..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"브라우저를 실행하시겠습니까?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"통화를 수락하시겠습니까?"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index bb3b044..c2c03e6 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Atidaryti galimą „Wi-Fi“ tinklą"</item>
     <item quantity="other" msgid="7915895323644292768">"Atidaryti galimus „Wi-Fi“ tinklus"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prisijungti prie „Wi-Fi“ tinklo"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepavyko prisijungti prie „Wi-Fi“"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" turi prastą interneto ryšį."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Tiesioginis „Wi-Fi“ ryšys"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Bendrinti su..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Įrenginys užrakintas."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Siunčiama..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Paleisti naršyklę?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Priimti skambutį?"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dc60a35..bd63bb3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Pierakstieties Wi-Fi tīklā"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nevarēja izveidot savienojumu ar Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ir slikts interneta savienojums."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Koplietot ar..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Ierīce ir bloķēta."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Notiek sūtīšana..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Vai palaist pārlūkprogrammu?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Vai pieņemt zvanu?"</string>
 </resources>
diff --git a/core/res/res/values-ms/donottranslate-cldr.xml b/core/res/res/values-ms/donottranslate-cldr.xml
new file mode 100644
index 0000000..09d461c
--- /dev/null
+++ b/core/res/res/values-ms/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">Januari</string>
+    <string name="month_long_standalone_february">Februari</string>
+    <string name="month_long_standalone_march">Mac</string>
+    <string name="month_long_standalone_april">April</string>
+    <string name="month_long_standalone_may">Mei</string>
+    <string name="month_long_standalone_june">Jun</string>
+    <string name="month_long_standalone_july">Julai</string>
+    <string name="month_long_standalone_august">Ogos</string>
+    <string name="month_long_standalone_september">September</string>
+    <string name="month_long_standalone_october">Oktober</string>
+    <string name="month_long_standalone_november">November</string>
+    <string name="month_long_standalone_december">Disember</string>
+
+    <string name="month_long_january">Januari</string>
+    <string name="month_long_february">Februari</string>
+    <string name="month_long_march">Mac</string>
+    <string name="month_long_april">April</string>
+    <string name="month_long_may">Mei</string>
+    <string name="month_long_june">Jun</string>
+    <string name="month_long_july">Julai</string>
+    <string name="month_long_august">Ogos</string>
+    <string name="month_long_september">September</string>
+    <string name="month_long_october">Oktober</string>
+    <string name="month_long_november">November</string>
+    <string name="month_long_december">Disember</string>
+
+    <string name="month_medium_january">Jan</string>
+    <string name="month_medium_february">Feb</string>
+    <string name="month_medium_march">Mac</string>
+    <string name="month_medium_april">Apr</string>
+    <string name="month_medium_may">Mei</string>
+    <string name="month_medium_june">Jun</string>
+    <string name="month_medium_july">Jul</string>
+    <string name="month_medium_august">Ogos</string>
+    <string name="month_medium_september">Sep</string>
+    <string name="month_medium_october">Okt</string>
+    <string name="month_medium_november">Nov</string>
+    <string name="month_medium_december">Dis</string>
+
+    <string name="month_shortest_january">1</string>
+    <string name="month_shortest_february">2</string>
+    <string name="month_shortest_march">3</string>
+    <string name="month_shortest_april">4</string>
+    <string name="month_shortest_may">5</string>
+    <string name="month_shortest_june">6</string>
+    <string name="month_shortest_july">7</string>
+    <string name="month_shortest_august">8</string>
+    <string name="month_shortest_september">9</string>
+    <string name="month_shortest_october">10</string>
+    <string name="month_shortest_november">11</string>
+    <string name="month_shortest_december">12</string>
+
+    <string name="day_of_week_long_sunday">Ahad</string>
+    <string name="day_of_week_long_monday">Isnin</string>
+    <string name="day_of_week_long_tuesday">Selasa</string>
+    <string name="day_of_week_long_wednesday">Rabu</string>
+    <string name="day_of_week_long_thursday">Khamis</string>
+    <string name="day_of_week_long_friday">Jumaat</string>
+    <string name="day_of_week_long_saturday">Sabtu</string>
+
+    <string name="day_of_week_medium_sunday">Ahd</string>
+    <string name="day_of_week_medium_monday">Isn</string>
+    <string name="day_of_week_medium_tuesday">Sel</string>
+    <string name="day_of_week_medium_wednesday">Rab</string>
+    <string name="day_of_week_medium_thursday">Kha</string>
+    <string name="day_of_week_medium_friday">Jum</string>
+    <string name="day_of_week_medium_saturday">Sab</string>
+
+    <string name="day_of_week_short_sunday">Ahd</string>
+    <string name="day_of_week_short_monday">Isn</string>
+    <string name="day_of_week_short_tuesday">Sel</string>
+    <string name="day_of_week_short_wednesday">Rab</string>
+    <string name="day_of_week_short_thursday">Kha</string>
+    <string name="day_of_week_short_friday">Jum</string>
+    <string name="day_of_week_short_saturday">Sab</string>
+
+    <string name="day_of_week_shortest_sunday">1</string>
+    <string name="day_of_week_shortest_monday">2</string>
+    <string name="day_of_week_shortest_tuesday">3</string>
+    <string name="day_of_week_shortest_wednesday">4</string>
+    <string name="day_of_week_shortest_thursday">5</string>
+    <string name="day_of_week_shortest_friday">6</string>
+    <string name="day_of_week_shortest_saturday">7</string>
+
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="yesterday">Yesterday</string>
+    <string name="today">Today</string>
+    <string name="tomorrow">Tomorrow</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%d/%m/%Y</string>
+    <string name="numeric_date_format">dd/MM/yyyy</string>
+    <string name="numeric_date_template">"%s/%s/%s"</string>
+    <string name="month_day_year">%d %B %Y</string>
+    <string name="time_of_day">%-l:%M:%S %p</string>
+    <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%d %b %Y</string>
+    <string name="month_day">%B %-e</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%Y %b</string>
+    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, y MMM d</string>
+</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b268575..b8a47d9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Rangkaian Wi-Fi terbuka tersedia"</item>
     <item quantity="other" msgid="7915895323644292768">"Rangkaian Wi-Fi terbuka tersedia"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Log masuk ke rangkaian Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak boleh menyambung kepada Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" mempunyai sambungan internet yang kurang baik."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Langsung"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Kongsi dengan..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Peranti dikunci."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Menghantar..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancarkan Penyemak Imbas?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Terima Panggilan?"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e9c0965..b01d275 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -302,7 +302,7 @@
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Lar appen lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med nettbrettet, og kan inneholde personlig eller privat informasjon."</string>
     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Lar appen lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med telefonen, og kan inneholde personlig eller privat informasjon."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"bruke en hvilken som helst mediedekoder for avspilling"</string>
-    <string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Gir en app tillatelse til å bruke en hvilken som helst installert mediedekoder for å dekode for avspilling."</string>
+    <string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Lar apper bruke en hvilken som helst installert mediedekoder for å dekode for avspilling."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lese/skrive ressurser eid av diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Lar applikasjonen lese og skrive enhver ressurs eid av gruppen diag; for eksempel, filer i /dev. Dette kan potensielt påvirke systemets sikkerhet og stabilitet. Dette bør KUN brukes for maskinvarespesifikke diagnoseverktøy laget av operatøren eller produsenten."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"aktivere eller deaktigere applikasjonskomponenter"</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Logg deg på Wi-Fi-nettverket"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan ikke koble til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" har en dårlig Internett-tilkobling."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Enheten er låst."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Sender …"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte nettleseren?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Vil du besvare anropet?"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1ab6b3f..84c1817 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Open Wi-Fi-netwerk beschikbaar"</item>
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi-netwerken beschikbaar"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Aanmelden bij wifi-netwerk"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan geen verbinding maken met Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" heeft een slechte internetverbinding."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cc04e9c..46f5027 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -36,7 +36,7 @@
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problem z połączeniem lub błędny kod MMI."</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"Operacja jest ograniczona wyłącznie do numerów ustalonych."</string>
-    <string name="serviceEnabled" msgid="8147278346414714315">"Usługa była włączona."</string>
+    <string name="serviceEnabled" msgid="8147278346414714315">"Usługa została włączona."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Usługa została włączona dla:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Usługa została wyłączona."</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"Rejestracja powiodła się."</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Zaloguj się w sieci Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nie można połączyć się z siecią Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ma powolne połączenie internetowe."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Udostępnij..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Urządzenie zablokowane."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Wysyłanie..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Uruchomić przeglądarkę?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Odebrać połączenie?"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 16e1282..55d9106 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -51,7 +51,7 @@
     <string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID do Autor da Chamada"</string>
-    <string name="ClirMmi" msgid="7784673673446833091">"ID do autor da chamada efectuada"</string>
+    <string name="ClirMmi" msgid="7784673673446833091">"ID do autor da chamada efetuada"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Encaminhamento de chamadas"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Chamada em espera"</string>
     <string name="BaMmi" msgid="455193067926770581">"Barramento de chamadas"</string>
@@ -170,7 +170,7 @@
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"As suas contas"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Aceda às contas disponíveis."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlos de hardware"</string>
-    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Aceda directamente ao hardware no telefone."</string>
+    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Aceda diretamente ao hardware no telefone."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Chamadas telefónicas"</string>
     <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"Monitorize, grave e processe chamadas telefónicas."</string>
     <string name="permgrouplab_systemTools" msgid="4652191644082714048">"Ferramentas do sistema"</string>
@@ -291,7 +291,7 @@
     <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Permite a uma aplicação eliminar ficheiros em cache."</string>
     <string name="permlab_getPackageSize" msgid="4799785352306641460">"medir espaço de armazenamento da aplicação"</string>
     <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Permite a uma aplicação obter os respectivos código, dados e tamanhos de cache"</string>
-    <string name="permlab_installPackages" msgid="335800214119051089">"instalar aplicações directamente"</string>
+    <string name="permlab_installPackages" msgid="335800214119051089">"instalar aplicações diretamente"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Permite a uma aplicação instalar pacotes novos ou actualizados do Android. Algumas aplicações maliciosas podem utilizar este item para adicionar novas aplicações com autorizações arbitrariamente fortes."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"eliminar todos os dados da aplicações"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite a uma aplicação libertar espaço de armazenamento no tablet eliminando ficheiros no directório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema."</string>
@@ -395,12 +395,12 @@
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite o acesso ao controlador MTP de kernel para implementar o protocolo MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite à aplicação controlar vários periféricos para fins de teste de hardware."</string>
-    <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone directamente"</string>
+    <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone diretamente"</string>
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Permite à aplicação marcar números de telefone sem a intervenção do utilizador. Algumas aplicações maliciosas podem provocar o aparecimento de chamadas inesperadas na sua conta telefónica. Tenha em atenção que isto não permite à aplicação marcar números de emergência."</string>
-    <string name="permlab_callPrivileged" msgid="4198349211108497879">"marcar directamente quaisquer números de telefone"</string>
+    <string name="permlab_callPrivileged" msgid="4198349211108497879">"marcar diretamente quaisquer números de telefone"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Permite à aplicação marcar qualquer número de telefone, incluindo números de emergência, sem a intervenção do utilizador. Algumas aplicações maliciosas podem efectuar chamadas desnecessárias e ilegais para serviços de emergência."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente a configuração do tablet CDMA"</string>
-    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente a configuração do telefone CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar diretamente a configuração do tablet CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar diretamente a configuração do telefone CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Permite que a aplicação inicie o aprovisionamento CDMA. As aplicações mal intencionadas podem iniciar o aprovisionamento CDMA desnecessariamente"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar notificações de actualização de localização"</string>
     <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Permite a activação/desactivação de notificações de actualização de localização a partir do rádio. Não se destina a utilização por aplicações normais."</string>
@@ -463,7 +463,7 @@
     <string name="permlab_changeWifiState" msgid="7280632711057112137">"alterar estado de Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Permite a uma aplicação ligar e desligar de pontos de acesso de Wi-Fi, bem como efectuar alterações a redes Wi-Fi configuradas."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepção Multicast Wi-Fi"</string>
-    <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite que uma aplicação receba pacotes não enviados directamente para o dispositivo. Esta opção pode ser útil para descobrir serviços oferecidos na vizinhança. Utiliza mais energia do que o modo não multicast."</string>
+    <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite que uma aplicação receba pacotes não enviados diretamente para o dispositivo. Esta opção pode ser útil para descobrir serviços oferecidos na vizinhança. Utiliza mais energia do que o modo não multicast."</string>
     <string name="permlab_accessWimaxState" msgid="2800410363171809280">"ver estado do WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="8298035866227524023">"Permite a uma aplicação ver as informações acerca do estado do Wi-Fi."</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"alterar estado do WiMAX"</string>
@@ -935,7 +935,7 @@
     <string name="volume_ringtone" msgid="6885421406845734650">"Volume da campainha"</string>
     <string name="volume_music" msgid="5421651157138628171">"Volume de multimédia"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"A reproduzir através de Bluetooth"</string>
-    <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Toque silencioso seleccionado"</string>
+    <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Toque silencioso selecionado"</string>
     <string name="volume_call" msgid="3941680041282788711">"Volume da chamada recebida"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume de chamada recebida em Bluetooth"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"Volume do alarme"</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sessão na rede Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível ligar a Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" tem uma ligação à internet fraca."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1020,7 +1023,7 @@
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccione para desactivar depuração USB."</string>
-    <string name="select_input_method" msgid="6865512749462072765">"Selecionar método de entrada"</string>
+    <string name="select_input_method" msgid="6865512749462072765"></string>
     <string name="configure_input_methods" msgid="6324843080254191535">"Configurar métodos de entrada"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1081,7 +1084,7 @@
     <string name="vpn_text" msgid="1610714069627824309">"Toque para gerir a rede."</string>
     <string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string>
     <string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
-    <string name="no_file_chosen" msgid="6363648562170759465">"Não foi seleccionado nenhum ficheiro"</string>
+    <string name="no_file_chosen" msgid="6363648562170759465">"Não foi selecionado nenhum ficheiro"</string>
     <string name="reset" msgid="2448168080964209908">"Repor"</string>
     <string name="submit" msgid="1602335572089911941">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Modo automóvel activado"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Partilhar com..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Aparelho bloqueado."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"A enviar..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Iniciar Navegador?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Aceitar Chamada?"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 77c52f7..5a0d43d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" tem uma conexão de baixa qualidade com a Internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 86492fa..e9e6e92 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Conectaţi-vă la reţeaua Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nu se poate conecta la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" are o conexiune la internet slabă."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Distribuiţi cu..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Dispozitiv blocat."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Se trimite..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Lansaţi browserul?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Acceptaţi apelul?"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d0a40954..65028dc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Найдена доступная сеть Wi-Fi"</item>
     <item quantity="other" msgid="7915895323644292768">"Найдены доступные сети Wi-Fi"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Подключение к Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не удалось подключиться к сети Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" – плохое интернет-соединение."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1189,7 +1192,7 @@
     <string name="data_usage_warning_body" msgid="7217480745540055170">"Проверить трафик и настройки"</string>
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Передача данных 2G/3G отключена"</string>
     <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Передача данных 4G отключена"</string>
-    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Мобильный Интернет отключен"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Моб. Интернет отключен"</string>
     <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Передача данных через Wi-Fi отключена"</string>
     <string name="data_usage_limit_body" msgid="4313857592916426843">"Нажмите, чтобы включить"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Превышен лимита трафика 2G и 3G"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Настройка доступа"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Устройство заблокировано."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Отправка..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Запустить браузер?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Принять вызов?"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f075d27..a8fb3eb 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prihlásiť sa do siete Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepodarilo sa pripojiť k sieti Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" má nekvalitné internetové pripojenie."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Priame pripojenie Wi-Fi"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Zdieľať s..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Zariadenie je zamknuté."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Prebieha odosielanie..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustiť prehliadač?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Prijať hovor?"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e298819..a66a769 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavite se v omrežje Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Z omrežjem Wi-Fi se ni mogoče povezati"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ima slabo internetno povezavo."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Skupna raba z ..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Naprava zaklenjena."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Pošiljanje ..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Ali želite odpreti brskalnik?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Ali želite sprejeti klic?"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f083a6d..f24cc03 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Доступна је отворена Wi-Fi мрежа"</item>
     <item quantity="other" msgid="7915895323644292768">"Доступне су отворене Wi-Fi мреже"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Пријављивање на Wi-Fi мрежу"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Није било могуће повезати са Wi-Fi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" има лошу интернет везу."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Дељење са..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Уређај је закључан."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Слање..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Желите ли да покренете прегледач?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Желите ли да прихватите позив?"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2e04d8f..2620efb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Logga in på ett Wi-Fi-nätverk"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Det gick inte att ansluta till Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" har en dålig Internetanslutning."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi direkt"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Dela med..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Enheten är låst."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Skickas ..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Vill du öppna webbläsaren?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Vill du ta emot samtal?"</string>
 </resources>
diff --git a/core/res/res/values-sw/donottranslate-cldr.xml b/core/res/res/values-sw/donottranslate-cldr.xml
new file mode 100644
index 0000000..2bc07c1
--- /dev/null
+++ b/core/res/res/values-sw/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">Januari</string>
+    <string name="month_long_standalone_february">Februari</string>
+    <string name="month_long_standalone_march">Machi</string>
+    <string name="month_long_standalone_april">Aprili</string>
+    <string name="month_long_standalone_may">Mei</string>
+    <string name="month_long_standalone_june">Juni</string>
+    <string name="month_long_standalone_july">Julai</string>
+    <string name="month_long_standalone_august">Agosti</string>
+    <string name="month_long_standalone_september">Septemba</string>
+    <string name="month_long_standalone_october">Oktoba</string>
+    <string name="month_long_standalone_november">Novemba</string>
+    <string name="month_long_standalone_december">Desemba</string>
+
+    <string name="month_long_january">Januari</string>
+    <string name="month_long_february">Februari</string>
+    <string name="month_long_march">Machi</string>
+    <string name="month_long_april">Aprili</string>
+    <string name="month_long_may">Mei</string>
+    <string name="month_long_june">Juni</string>
+    <string name="month_long_july">Julai</string>
+    <string name="month_long_august">Agosti</string>
+    <string name="month_long_september">Septemba</string>
+    <string name="month_long_october">Oktoba</string>
+    <string name="month_long_november">Novemba</string>
+    <string name="month_long_december">Desemba</string>
+
+    <string name="month_medium_january">Jan</string>
+    <string name="month_medium_february">Feb</string>
+    <string name="month_medium_march">Mac</string>
+    <string name="month_medium_april">Apr</string>
+    <string name="month_medium_may">Mei</string>
+    <string name="month_medium_june">Jun</string>
+    <string name="month_medium_july">Jul</string>
+    <string name="month_medium_august">Ago</string>
+    <string name="month_medium_september">Sep</string>
+    <string name="month_medium_october">Okt</string>
+    <string name="month_medium_november">Nov</string>
+    <string name="month_medium_december">Des</string>
+
+    <string name="month_shortest_january">1</string>
+    <string name="month_shortest_february">2</string>
+    <string name="month_shortest_march">3</string>
+    <string name="month_shortest_april">4</string>
+    <string name="month_shortest_may">5</string>
+    <string name="month_shortest_june">6</string>
+    <string name="month_shortest_july">7</string>
+    <string name="month_shortest_august">8</string>
+    <string name="month_shortest_september">9</string>
+    <string name="month_shortest_october">10</string>
+    <string name="month_shortest_november">11</string>
+    <string name="month_shortest_december">12</string>
+
+    <string name="day_of_week_long_sunday">Jumapili</string>
+    <string name="day_of_week_long_monday">Jumatatu</string>
+    <string name="day_of_week_long_tuesday">Jumanne</string>
+    <string name="day_of_week_long_wednesday">Jumatano</string>
+    <string name="day_of_week_long_thursday">Alhamisi</string>
+    <string name="day_of_week_long_friday">Ijumaa</string>
+    <string name="day_of_week_long_saturday">Jumamosi</string>
+
+    <string name="day_of_week_medium_sunday">Jpi</string>
+    <string name="day_of_week_medium_monday">Jtt</string>
+    <string name="day_of_week_medium_tuesday">Jnn</string>
+    <string name="day_of_week_medium_wednesday">Jtn</string>
+    <string name="day_of_week_medium_thursday">Alh</string>
+    <string name="day_of_week_medium_friday">Iju</string>
+    <string name="day_of_week_medium_saturday">Jmo</string>
+
+    <string name="day_of_week_short_sunday">Jpi</string>
+    <string name="day_of_week_short_monday">Jtt</string>
+    <string name="day_of_week_short_tuesday">Jnn</string>
+    <string name="day_of_week_short_wednesday">Jtn</string>
+    <string name="day_of_week_short_thursday">Alh</string>
+    <string name="day_of_week_short_friday">Iju</string>
+    <string name="day_of_week_short_saturday">Jmo</string>
+
+    <string name="day_of_week_shortest_sunday">1</string>
+    <string name="day_of_week_shortest_monday">2</string>
+    <string name="day_of_week_shortest_tuesday">3</string>
+    <string name="day_of_week_shortest_wednesday">4</string>
+    <string name="day_of_week_shortest_thursday">5</string>
+    <string name="day_of_week_shortest_friday">6</string>
+    <string name="day_of_week_shortest_saturday">7</string>
+
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="yesterday">Yesterday</string>
+    <string name="today">Today</string>
+    <string name="tomorrow">Tomorrow</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%Y/%m/%d</string>
+    <string name="numeric_date_format">yyyy/MM/dd</string>
+    <string name="numeric_date_template">"%s/%s/%s"</string>
+    <string name="month_day_year">%Y %B %-e</string>
+    <string name="time_of_day">%H:%M:%S</string>
+    <string name="date_and_time">%H:%M:%S %Y %b %-e</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%Y %b %-e</string>
+    <string name="month_day">%B %-e</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%Y %B</string>
+    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%Y %b</string>
+    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s/%2$s/%3$s – %10$s %9$s/%7$s/%8$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, y MMM d</string>
+</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d1287d8..d1d4fff 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -49,7 +49,7 @@
     <string name="invalidPin" msgid="3850018445187475377">"Chapisha PIN ambayo ina nambari 4 hadi 8."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"Andika PUK ambayo ina urefu wa nambari 8 au zaidi."</string>
     <string name="needPuk" msgid="919668385956251611">"Kadi yako ya SIM imefungwa na PUK. Anika msimbo wa PUK ili kuifungua."</string>
-    <string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua kadi ya SIM."</string>
+    <string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua SIM kadi."</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Kitambulisho cha Mpigaji wa Simu Inayoingia"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID ya Mpigaji simu Inayotoka nje"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Kusambaza simu"</string>
@@ -199,11 +199,11 @@
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"Tuma ujumbe wa SMS bila ya thibitisho"</string>
     <string name="permdesc_sendSmsNoConfirmation" msgid="4477752891276276168">"Huruhusu programu kutuma ujumbe wa SMS. Programu hatari huenda zikagharimu pesa kwa kutuma ujumbe bila ya uthibitishaji wako."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"soma SMS au MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma SMS zilizohifadhiwa kwenye kompyuta yako ndogo au kadi ya SIM. Huenda programu hasidi zikasoma SMS zako za siri."</string>
-    <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma SMS zilizohifadhiwa kwenye kompyuta yako ndogo au SIM kadi. Huenda programu hasidi zikasoma SMS zako za siri."</string>
+    <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au SIM kadi. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"hariri SMS au MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika ujumbe wa SMS uliohifadhiwa kwenye kompyuta yako au kadi ya SIM. Huenda programu hasidi zikafuta ujumbe wako."</string>
-    <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika ujumbe wa SMS uliohifadhiwa kwenye kompyuta yako au SIM kadi. Huenda programu hasidi zikafuta ujumbe wako."</string>
+    <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au SIM kadi. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"pokea WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Huruhusu programu kupokea na kuchakata ujumbe wa WAP. Programu mbaya za kompyuta huenda zikafuatilia ujumbe wako au kuzifuta bila kukuonyesha."</string>
     <string name="permlab_getTasks" msgid="5005277531132573353">"epua programu zinazoendeshwa"</string>
@@ -266,11 +266,11 @@
     <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>
     <string name="permlab_bindTextService" msgid="7358378401915287938">"Imefungwa kwa huduma ya maandishi"</string>
-    <string name="permdesc_bindTextService" msgid="172508880651909350">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha pazia cha huduma ya maandishi (k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
+    <string name="permdesc_bindTextService" msgid="172508880651909350">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mandhari cha huduma ya maandishi (k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"funga kwa huduma ya VPN"</string>
     <string name="permdesc_bindVpnService" msgid="6011554199384584151">"Huruhusu kishikiliaji kufunga kusano cha kiwango cha juu cha huduma ya Vpn. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string>
-    <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>
+    <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string>
+    <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mandhari. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha huduma ya wiji. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
@@ -423,10 +423,10 @@
     <string name="permlab_factoryTest" msgid="3715225492696416187">"endesha katika hali ya jaribio ya kiwanda"</string>
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Endesha kama jaribio la mtengenezaji la kiwango cha chini, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya kompyuta ndogo. Inapatikana tu wakati kompyuta ndogo inaendeshwa katika hali ya jaribio la mtengenezaji."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Endesha kama jaribio la kiwango cha chini cha mtengenezaji, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya simu. Inapatikana tu wakati simu inaendeshwa katika gumzo ya jaribio ya mtengenezaji."</string>
-    <string name="permlab_setWallpaper" msgid="6627192333373465143">"weka pazia"</string>
-    <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Huruhusu programu kuweka pazia ya mfumo."</string>
-    <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"weka vidokezo vya ukubwa wa pazia"</string>
-    <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Huruhusu programu kuweka vidokezo vya ukubwa wa pazia ya mfumo."</string>
+    <string name="permlab_setWallpaper" msgid="6627192333373465143">"weka mandhari"</string>
+    <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Huruhusu programu kuweka mandhari ya mfumo."</string>
+    <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"weka vidokezo vya ukubwa wa mandhari"</string>
+    <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Huruhusu programu kuweka vidokezo vya ukubwa wa mandhari ya mfumo."</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"weka upya mfumo kwa chaguo-msingi za kiwanda"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Huruhusu programu kuweka upya kabisa mfumo kwa mipangilio yake ya kiwanda, kwa hivyo kufuta data zote, usanidi, na programu za kompyuta zilizosanidiwa."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"weka muda"</string>
@@ -665,11 +665,11 @@
     <string name="lockscreen_charged" msgid="4938930459620989972">"Imechajiwa."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"Kishika nafasi<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Unganisha chaja yako"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna kadi ya SIM."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna kadi ya SIM katika kompyuta ndogo."</string>
-    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna kadi ya SIM kwenye simu."</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Tafadhali ingiza kadi ya SIM."</string>
-    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kadi ya SIM inakosekana au haisomekani. Tafadhali ingiza kadi ya SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna SIM kadi."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Tafadhali ingiza SIM kadi."</string>
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kadi ya SIM inakosekana au haisomekani. Tafadhali ingiza SIM kadi."</string>
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kadi yako ya SIM imelemazwa kabisa. "\n" tafadhali wasiliana na mtoa huduma wako wa psiwaya ili kupata kadi nyingine ya SIM."</string>
     <string name="lockscreen_transport_prev_description" msgid="201594905152746886">"Kitufe cha awali cha wimbo"</string>
     <string name="lockscreen_transport_next_description" msgid="6089297650481292363">"Kitufe cha wimbo unaofuata"</string>
@@ -681,7 +681,7 @@
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kadi ya SIM imefungwa na PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Tafadhali angalia Mwongozo wa Mtumiaji au wasiliana na Huduma kwa Wateja."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kadi ya SIM imefungwa."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua kadi ya SIM..."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua SIM kadi..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Umechora vibaya ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Tafadhali jaribu tena kati ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Haujaingiza nenosiri yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>Tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Haujaingiza PIN yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
@@ -844,7 +844,7 @@
     <item quantity="one" msgid="2178576254385739855">"kesho"</item>
     <item quantity="other" msgid="2973062968038355991">"kati ya siku <xliff:g id="COUNT">%d</xliff:g>"</item>
   </plurals>
-    <string name="preposition_for_date" msgid="9093949757757445117">"mnamo <xliff:g id="DATE">%s</xliff:g>"</string>
+    <string name="preposition_for_date" msgid="9093949757757445117">"tarehe <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="preposition_for_time" msgid="5506831244263083793">"Saa <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"ndani  ya <xliff:g id="YEAR">%s</xliff:g>"</string>
     <string name="day" msgid="8144195776058119424">"siku"</string>
@@ -892,7 +892,7 @@
     <string name="no" msgid="5141531044935541497">"Ghairi"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Zingatia"</string>
     <string name="loading" msgid="1760724998928255250">"Inapakia..."</string>
-    <string name="capital_on" msgid="1544682755514494298">"Mnamo"</string>
+    <string name="capital_on" msgid="1544682755514494298">"Washa"</string>
     <string name="capital_off" msgid="6815870386972805832">"ZIMA"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Kamilisha kitendo kwa kutumia"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Tumia kama chaguo-msingi la kitendo hiki."</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Ingia kwa mtandao wa Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Haikuweza kuunganisha kwa Mtandao-Hewa"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" inao muunganisho duni wa wavuti."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Mtandao hewa Moja kwa moja"</string>
@@ -976,7 +979,7 @@
     <string name="sms_control_yes" msgid="2532062172402615953">"Sawa"</string>
     <string name="sms_control_no" msgid="1715320703137199869">"Ghairi"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na kadi ya SIM halali iliyoingizwa."</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"Kadi ya SIM imeongezwa"</string>
     <string name="sim_added_message" msgid="1209265974048554242">"Lazima uwashe upya kifaa chako ili kufikia mtandao wa simu."</string>
@@ -1074,8 +1077,8 @@
     <string name="input_method_binding_label" msgid="1283557179944992649">"Mbinu ya uingizaji"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"Sawazisha"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ufikiaji"</string>
-    <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pazia"</string>
-    <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha pazia"</string>
+    <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
+    <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
     <string name="vpn_title" msgid="8219003246858087489">"VPN imeamilishwa."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="1610714069627824309">"Gonga ili kudhibiti mtandao."</string>
@@ -1130,7 +1133,7 @@
     <string name="sync_do_nothing" msgid="8717589462945226869">"Usifanye chochote kwa sasa."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Chagua akaunti"</string>
     <string name="add_account_label" msgid="2935267344849993553">"Ongeza akaunti"</string>
-    <string name="choose_account_text" msgid="6891230675141555481">"Akaunti gani ungependa kutumia?"</string>
+    <string name="choose_account_text" msgid="6891230675141555481">"Ungependa kutumia akaunti gani?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Ongeza akaunti"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Ongezeko"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Punguza"</string>
@@ -1152,7 +1155,7 @@
     <string name="checkbox_not_checked" msgid="5174639551134444056">"haijakaguliwa"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Iliyochaguliwa"</string>
     <string name="radiobutton_not_selected" msgid="2908760184307722393">"Haijachaguliwa"</string>
-    <string name="switch_on" msgid="551417728476977311">"Mnamo"</string>
+    <string name="switch_on" msgid="551417728476977311">"Washa"</string>
     <string name="switch_off" msgid="7249798614327155088">"zima"</string>
     <string name="togglebutton_pressed" msgid="4180411746647422233">"iliyobonyezwa"</string>
     <string name="togglebutton_not_pressed" msgid="4495147725636134425">"Haijabonyezwa"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Shiriki na..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Kifaa kimefungwa."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Inatuma..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Zindua Kivinjari?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Kubali Simu?"</string>
 </resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 921bcf4..431a502 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -62,8 +62,8 @@
 
     <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
     <dimen name="default_app_widget_padding_left">12dp</dimen>
-    <dimen name="default_app_widget_padding_top">12dp</dimen>
-    <dimen name="default_app_widget_padding_right">4dp</dimen>
+    <dimen name="default_app_widget_padding_top">4dp</dimen>
+    <dimen name="default_app_widget_padding_right">12dp</dimen>
     <dimen name="default_app_widget_padding_bottom">20dp</dimen>
 
     <!-- Minimum width for an action button in the menu area of an action bar -->
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index abd1208..0e933be 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
     <item quantity="other" msgid="7915895323644292768">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ไม่สามารถเชื่อมต่อ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"แบ่งปันกับ..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"ล็อกอุปกรณ์อยู่"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"กำลังส่ง..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"เปิดเบราว์เซอร์หรือไม่"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"รับสายหรือไม่"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bc47b0a..dc33146 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Mag-sign in sa Wi-Fi network"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Hindi makakonekta sa Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ay mayroong mahinang koneksyon sa internet."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Ibahagi kay..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Naka-lock ang device."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Ipinapadala..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Ilunsad ang Browser?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Tanggapin ang Tawag?"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d27d95b..cdd2ad7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Kullanılabilir kablosuz ağı aç"</item>
     <item quantity="other" msgid="7915895323644292768">"Kullanılabilir kablosuz ağları aç"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Kablosuz ağda oturum açın"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kablosuz bağlantısı kurulamadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" internet bağlantısı zayıf."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Kablosuz Doğrudan Bağlantı"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Şununla paylaş..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Cihaz kilitli."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Gönderiliyor..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Tarayıcı Başlatılsın mı?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Çağrı Kabul Edilsin mi?"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fae9aad..2ea5fd5 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"Відкрита Wi-Fi мережа доступна"</item>
     <item quantity="other" msgid="7915895323644292768">"Відкриті Wi-Fi мережі доступні"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Вхід у мережу Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" має погане з’єднання з Інтернетом."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 72b91fc..ebfffb0 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -38,9 +38,9 @@
     <string name="mmiFdnError" msgid="5224398216385316471">"Chỉ hạn chế thao tác đối với số quay số định sẵn."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Dịch vụ đã được bật."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Dịch vụ đã được bật cho:"</string>
-    <string name="serviceDisabled" msgid="1937553226592516411">"Dịch vụ đã bị vô hiệu hoá."</string>
+    <string name="serviceDisabled" msgid="1937553226592516411">"Dịch vụ đã bị vô hiệu hóa."</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"Đăng ký thành công."</string>
-    <string name="serviceErased" msgid="1288584695297200972">"Xoá thành công."</string>
+    <string name="serviceErased" msgid="1288584695297200972">"Xóa thành công."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"Mật khẩu không chính xác."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI hoàn tất."</string>
     <string name="badPin" msgid="5085454289896032547">"Mã PIN cũ bạn đã nhập không chính xác."</string>
@@ -48,7 +48,7 @@
     <string name="mismatchPin" msgid="3695902225843339274">"Mã PIN bạn đã nhập không khớp."</string>
     <string name="invalidPin" msgid="3850018445187475377">"Nhập mã PIN có từ 4 đến 8 số."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"Nhập PUK có từ 8 số trở lên."</string>
-    <string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khoá PUK. Nhập mã PUK để mở khoá thẻ SIM đó."</string>
+    <string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khóa PUK. Nhập mã PUK để mở khóa thẻ SIM đó."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Nhập mã PUK2 để bỏ chặn thẻ SIM."</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Số gọi đến"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Số gọi đi"</string>
@@ -83,7 +83,7 @@
     <string name="serviceClassFAX" msgid="5566624998840486475">"FAX"</string>
     <string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
     <string name="serviceClassDataAsync" msgid="4523454783498551468">"Không đồng bộ"</string>
-    <string name="serviceClassDataSync" msgid="7530000519646054776">"Đồng bộ hoá"</string>
+    <string name="serviceClassDataSync" msgid="7530000519646054776">"Đồng bộ hóa"</string>
     <string name="serviceClassPacket" msgid="6991006557993423453">"Gói"</string>
     <string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
     <string name="roamingText0" msgid="7170335472198694945">"Chỉ báo Chuyển vùng Bật"</string>
@@ -124,11 +124,11 @@
     <string name="httpErrorFileNotFound" msgid="5588380756326017105">"Không tìm thấy tệp được yêu cầu."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Quá nhiều yêu cầu đang được xử lý. Hãy thử lại sau."</string>
     <string name="notification_title" msgid="1259940370369187045">"Lỗi đăng nhập đối với <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
-    <string name="contentServiceSync" msgid="8353523060269335667">"Đồng bộ hoá"</string>
-    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hoá"</string>
-    <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xoá <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
+    <string name="contentServiceSync" msgid="8353523060269335667">"Đồng bộ hóa"</string>
+    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hóa"</string>
+    <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xóa <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="2292820184396262278">"Bộ nhớ máy tính bảng đã đầy! Hãy xóa một số tệp để giải phóng dung lượng."</string>
-    <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xoá một số tệp để tạo thêm dung lượng."</string>
+    <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xóa một số tệp để tạo thêm dung lượng."</string>
     <string name="me" msgid="6545696007631404292">"Tôi"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tùy chọn máy tính bảng"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Tùy chọn điện thoại"</string>
@@ -180,8 +180,8 @@
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Dung lượng"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Truy cập bộ nhớ USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Truy cập thẻ SD."</string>
-    <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hoá hoặc sửa đổi thanh trạng thái"</string>
-    <string name="permdesc_statusBar" msgid="1365473595331989732">"Cho phép ứng dụng vô hiệu hoá thanh trạng thái hoặc thêm và xoá biểu tượng hệ thống."</string>
+    <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
+    <string name="permdesc_statusBar" msgid="1365473595331989732">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"thanh trạng thái"</string>
     <string name="permdesc_statusBarService" msgid="4097605867643520920">"Cho phép ứng dụng là thanh trạng thái."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"mở rộng/thu gọn thanh trạng thái"</string>
@@ -189,9 +189,9 @@
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"chặn các cuộc gọi đi"</string>
     <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Cho phép ứng dụng xử lý cuộc gọi đi và thay đổi số đã được quay số. Các ứng dụng độc hại có thể giám sát, chuyển hướng hoặc chặn các cuộc gọi đi."</string>
     <string name="permlab_receiveSms" msgid="2697628268086208535">"nhận SMS"</string>
-    <string name="permdesc_receiveSms" msgid="6298292335965966117">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+    <string name="permdesc_receiveSms" msgid="6298292335965966117">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
     <string name="permlab_receiveMms" msgid="8894700916188083287">"nhận MMS"</string>
-    <string name="permdesc_receiveMms" msgid="4563346832000174373">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+    <string name="permdesc_receiveMms" msgid="4563346832000174373">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"nhận các truyền phát khẩn cấp"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Cho phép ứng dụng truy xuất và xử lý các thư phát khẩn cấp. Quyền này chỉ khả dụng đối với các ứng dụng hệ thống."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"gửi tin nhắn SMS"</string>
@@ -203,9 +203,9 @@
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Cho phép ứng dụng đọc tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể đọc tin nhắn bí mật của bạn."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"chỉnh sửa SMS hoặc MMS"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên máy tính bảng hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
-    <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xoá tin nhắn của bạn."</string>
+    <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"nhận WAP"</string>
-    <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+    <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
     <string name="permlab_getTasks" msgid="5005277531132573353">"truy xuất các ứng dụng đang chạy"</string>
     <string name="permdesc_getTasks" msgid="7048711358713443341">"Cho phép ứng dụng truy xuất thông tin về các công việc hiện đang chạy. Có thể cho phép các ứng dụng độc hại phát hiện thông tin riêng tư về các ứng dụng khác."</string>
     <string name="permlab_reorderTasks" msgid="5669588525059921549">"sắp xếp lại các ứng dụng đang chạy"</string>
@@ -234,8 +234,8 @@
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"giám sát và kiểm soát tất cả khởi chạy ứng dụng"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Các ứng dụng độc hại có thể làm tổn hại hoàn toàn hệ thống. Quyền này chỉ cần cho việc phát triển, không bao giờ dùng cho việc sử dụng thông thường."</string>
-    <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xoá của gói"</string>
-    <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Cho phép ứng dụng truyền phát thông báo rằng gói ứng dụng đã bị xoá. Các ứng dụng độc hại có thể sử dụng quyền này để loại bỏ mọi ứng dụng đang chạy khác."</string>
+    <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xóa của gói"</string>
+    <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Cho phép ứng dụng truyền phát thông báo rằng gói ứng dụng đã bị xóa. Các ứng dụng độc hại có thể sử dụng quyền này để loại bỏ mọi ứng dụng đang chạy khác."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"gửi truyền phát SMS nhận được"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Cho phép ứng dụng truyền phát thông báo rằng đã nhận được tin nhắn SMS. Các ứng dụng độc hại có thẻ sử dụng quyền này để giả mạo tin nhắn SMS đến."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"gửi truyền phát WAP-PUSH nhận được"</string>
@@ -283,19 +283,19 @@
     <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Cho phép ứng dụng yêu cầu tín hiệu đã cung cấp được gửi đến tất cả các quá trình liên tục."</string>
     <string name="permlab_persistentActivity" msgid="8659652042401085862">"đặt ứng dụng luôn chạy"</string>
     <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình để hệ thống không thể sử dụng ứng dụng đó cho các ứng dụng khác."</string>
-    <string name="permlab_deletePackages" msgid="3343439331576348805">"xoá ứng dụng"</string>
-    <string name="permdesc_deletePackages" msgid="3634943677518723314">"Cho phép ứng dụng xoá các gói Android. Các ứng dụng độc hại có thể sử dụng quyền này để xoá các ứng dụng quan trọng."</string>
-    <string name="permlab_clearAppUserData" msgid="2192134353540277878">"xoá dữ liệu của ứng dụng khác"</string>
-    <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Cho phép ứng dụng xoá dữ liệu của người dùng."</string>
-    <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"xoá bộ nhớ cache của các ứng dụng khác"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Cho phép ứng dụng xoá các tệp bộ nhớ cache."</string>
+    <string name="permlab_deletePackages" msgid="3343439331576348805">"xóa ứng dụng"</string>
+    <string name="permdesc_deletePackages" msgid="3634943677518723314">"Cho phép ứng dụng xóa các gói Android. Các ứng dụng độc hại có thể sử dụng quyền này để xóa các ứng dụng quan trọng."</string>
+    <string name="permlab_clearAppUserData" msgid="2192134353540277878">"xóa dữ liệu của ứng dụng khác"</string>
+    <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Cho phép ứng dụng xóa dữ liệu của người dùng."</string>
+    <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"xóa bộ nhớ cache của các ứng dụng khác"</string>
+    <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Cho phép ứng dụng xóa các tệp bộ nhớ cache."</string>
     <string name="permlab_getPackageSize" msgid="4799785352306641460">"đo dung lượng lưu trữ ứng dụng"</string>
     <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Cho phép ứng dụng truy xuất mã, dữ liệu và kích thước bộ nhớ cache của nó"</string>
     <string name="permlab_installPackages" msgid="335800214119051089">"cài đặt trực tiếp ứng dụng"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Các ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có quyền mạnh mẽ tùy ý."</string>
-    <string name="permlab_clearAppCache" msgid="4747698311163766540">"xoá tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
+    <string name="permlab_clearAppCache" msgid="4747698311163766540">"xóa tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Cho phép ứng dụng giải phóng bộ nhớ máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xoá các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Chuyển tài nguyên của ứng dụng"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Cho phép ứng dụng di chuyển các tài nguyên của ứng dụng từ phương tiện truyền thông bên trong ra phương tiện bên ngoài và ngược lại."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"đọc dữ liệu nhật ký nhạy cảm"</string>
@@ -305,7 +305,7 @@
     <string name="permdesc_anyCodecForPlayback" msgid="2101444559995480174">"Cho phép ứng dụng sử dụng bất kỳ bộ giải mã phương tiện đã cài đặt nào để giải mã phát lại."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"đọc/ghi vào tài nguyên do chẩn đoán sở hữu"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Cho phép ứng dụng đọc và ghi vào bất kỳ tài nguyên nào do nhóm chẩn đoán sở hữu; ví dụ: các tệp trong /dev. Quyền này có thể ảnh hưởng đến sự ổn định và bảo mật của hệ thống. CHỈ nên sử dụng quyền này cho các chẩn đoán phần cứng cụ thể bởi nhà sản xuất hoặc nhà cung cấp dịch vụ."</string>
-    <string name="permlab_changeComponentState" msgid="79425198834329406">"bật hoặc vô hiệu hoá các thành phần ứng dụng"</string>
+    <string name="permlab_changeComponentState" msgid="79425198834329406">"bật hoặc vô hiệu hóa các thành phần ứng dụng"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của máy tính bảng. Phải cẩn thận khi sử dụng quyền này vì nó có thể khiến các thành phần rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của điện thoại. Phải cẩn thận khi sử dụng quyền này vì quyền này có thể khiến các thành phần ứng dụng rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"đặt ứng dụng ưa thích"</string>
@@ -327,7 +327,7 @@
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Cho phép ứng dụng đọc tất cả dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu (địa chỉ) liên hệ được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
     <string name="permlab_readProfile" msgid="6824681438529842282">"đọc d.liệu t.sử của bạn"</string>
     <string name="permdesc_readProfile" product="default" msgid="6335739730324727203">"Cho phép ứng dụng đọc thông tin tiểu sử cá nhân được lưu trên thiết bị của bạn, ví dụ như tên và thông tin liên hệ của bạn. Điều này nghĩa là ứng dụng có thể nhận dạng bạn và gửi thông tin tiểu sử của bạn cho những người khác."</string>
     <string name="permlab_writeProfile" msgid="4679878325177177400">"ghi dữ liệu t.sử của bạn"</string>
@@ -359,14 +359,14 @@
     <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Cho phép ứng dụng đọc nội dung của bộ đệm khung."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và định tuyến."</string>
-    <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm thanh"</string>
-    <string name="permdesc_recordAudio" msgid="6493228261176552356">"Cho phép ứng dụng truy cập vào đường dẫn bản ghi âm thanh."</string>
+    <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm"</string>
+    <string name="permdesc_recordAudio" msgid="6493228261176552356">"Cho phép ứng dụng truy cập vào đường dẫn bản ghi âm."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh và quay video"</string>
     <string name="permdesc_camera" msgid="6004878235852154239">"Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng thu thập ảnh mà máy ảnh chụp vào bất kỳ thời điểm nào."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa vĩnh viễn máy tính bảng"</string>
-    <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hoá điện thoại"</string>
+    <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hóa điện thoại"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Cho phép ứng dụng vô hiệu hóa vĩnh viễn toàn bộ máy tính bảng. Việc này rất nguy hiểm."</string>
-    <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Cho phép ứng dụng vô hiệu hoá vĩnh viễn toàn bộ điện thoại. Việc này rất nguy hiểm."</string>
+    <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Cho phép ứng dụng vô hiệu hóa vĩnh viễn toàn bộ điện thoại. Việc này rất nguy hiểm."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"buộc máy tính bảng khởi động lại"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"buộc khởi động lại điện thoại"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Cho phép ứng dụng buộc máy tính bảng khởi động lại."</string>
@@ -396,7 +396,7 @@
     <string name="permlab_hardware_test" msgid="4148290860400659146">"kiểm tra phần cứng"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Cho phép ứng dụng kiểm soát các thiết bị ngoại vi khác nhau nhằm mục đích kiểm tra phần cứng."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"gọi trực tiếp số điện thoại"</string>
-    <string name="permdesc_callPhone" msgid="3369867353692722456">"Cho phép ứng dụng gọi các số điện thoại mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể dẫn đến các cuộc gọi không mong muốn trên hoá đơn điện thoại của bạn. Lưu ý rằng quyền này không cho phép ứng dụng gọi các số khẩn cấp."</string>
+    <string name="permdesc_callPhone" msgid="3369867353692722456">"Cho phép ứng dụng gọi các số điện thoại mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể dẫn đến các cuộc gọi không mong muốn trên hóa đơn điện thoại của bạn. Lưu ý rằng quyền này không cho phép ứng dụng gọi các số khẩn cấp."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"gọi trực tiếp số điện thoại bất kỳ"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Cho phép ứng dụng gọi bất kỳ số điện thoại nào, kể cả số khẩn cấp mà không cần sự can thiệp của bạn. Các ứng dụng độc hại có thể thực hiện các cuộc gọi không cần thiết và bất hợp pháp vào dịch vụ khẩn cấp."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"trực tiếp bắt đầu thiết lập máy tính bảng CDMA"</string>
@@ -428,7 +428,7 @@
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"Đặt gợi ý kích thước hình nền"</string>
     <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Cho phép ứng dụng đặt gợi ý kích thước hình nền của hệ thống."</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"đặt lại hệ thống về mặc định ban đầu"</string>
-    <string name="permdesc_masterClear" msgid="5033465107545174514">"Cho phép ứng dụng đặt lại toàn bộ hệ thống về cài đặt ban đầu, xoá tất cả dữ liệu, cấu hình và ứng dụng đã cài đặt."</string>
+    <string name="permdesc_masterClear" msgid="5033465107545174514">"Cho phép ứng dụng đặt lại toàn bộ hệ thống về cài đặt ban đầu, xóa tất cả dữ liệu, cấu hình và ứng dụng đã cài đặt."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"đặt giờ"</string>
     <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Cho phép ứng dụng thay đổi giờ trên đồng hồ của máy tính bảng."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Cho phép ứng dụng thay đổi giờ trên đồng hồ của điện thoại."</string>
@@ -443,7 +443,7 @@
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"hoạt động như trình xác thực tài khoản"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Cho phép ứng dụng sử dụng các tính năng của trình xác thực tài khoản của AccountManager, bao gồm tạo tài khoản, nhận và đặt mật khẩu của các tài khoản đó."</string>
     <string name="permlab_manageAccounts" msgid="4440380488312204365">"quản lý danh sách tài khoản"</string>
-    <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Cho phép ứng dụng thực hiện các thao tác như thêm và xoá tài khoản cũng như xoá mật khẩu của các tài khoản đó."</string>
+    <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Cho phép ứng dụng thực hiện các thao tác như thêm và xóa tài khoản cũng như xóa mật khẩu của các tài khoản đó."</string>
     <string name="permlab_useCredentials" msgid="6401886092818819856">"sử dụng thông tin xác thực tài khoản"</string>
     <string name="permdesc_useCredentials" msgid="7416570544619546974">"Cho phép ứng dụng yêu cầu mã thông báo xác thực."</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"xem trạng thái mạng"</string>
@@ -476,24 +476,24 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Cho phép ứng dụng xem cấu hình của điện thoại Bluetooth nội hạt cũng như tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kiểm soát Liên lạc trường gần"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Cho phép ứng dụng liên lạc với thẻ Liên lạc trường gần (NFC), thẻ và trình đọc."</string>
-    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hoá khoá phím"</string>
-    <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hoá khoá phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hoá khoá phím khi nhận được cuộc gọi đến sau đó bật lại khoá phím khi cuộc gọi kết thúc."</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hoá"</string>
-    <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Cho phép ứng dụng đọc cài đặt đồng bộ hoá, chẳng hạn như liệu đồng bộ hoá đã được bật cho Danh bạ hay chưa."</string>
-    <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"ghi cài đặt đồng bộ hoá"</string>
-    <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Cho phép ứng dụng sửa đổi cài đặt đồng bộ hoá, chẳng hạn như liệu đồng bộ hoá đã được bật cho Danh bạ chưa."</string>
-    <string name="permlab_readSyncStats" msgid="7396577451360202448">"đọc thống kê đồng bộ hoá"</string>
-    <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Cho phép ứng dụng đọc thống kê đồng bộ hoá, ví dụ: lịch sử đồng bộ hoá đã diễn ra."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hóa khóa phím"</string>
+    <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hóa khóa phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hóa khóa phím khi nhận được cuộc gọi đến sau đó bật lại khóa phím khi cuộc gọi kết thúc."</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hóa"</string>
+    <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa, chẳng hạn như liệu đồng bộ hóa đã được bật cho Danh bạ hay chưa."</string>
+    <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"ghi cài đặt đồng bộ hóa"</string>
+    <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Cho phép ứng dụng sửa đổi cài đặt đồng bộ hóa, chẳng hạn như liệu đồng bộ hóa đã được bật cho Danh bạ chưa."</string>
+    <string name="permlab_readSyncStats" msgid="7396577451360202448">"đọc thống kê đồng bộ hóa"</string>
+    <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Cho phép ứng dụng đọc thống kê đồng bộ hóa, ví dụ: lịch sử đồng bộ hóa đã diễn ra."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
-    <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Cho phép ứng dụng nhận các chi tiết về nguồn cấp dữ liệu hiện đã được đồng bộ hoá."</string>
+    <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Cho phép ứng dụng nhận các chi tiết về nguồn cấp dữ liệu hiện đã được đồng bộ hóa."</string>
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"ghi nguồn cấp dữ liệu đã đăng ký"</string>
-    <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hoá. Quyền này có thể cho phép ứng dụng độc hại thay đổi nguồn cấp dữ liệu đã đồng bộ hoá của bạn."</string>
+    <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hóa. Quyền này có thể cho phép ứng dụng độc hại thay đổi nguồn cấp dữ liệu đã đồng bộ hóa của bạn."</string>
     <string name="permlab_readDictionary" msgid="432535716804748781">"đọc từ điển do người dùng xác định"</string>
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Cho phép ứng dụng đọc bất kỳ từ, tên và cụm từ riêng nào mà người dùng có thể đã lưu trữ trong từ điển của người dùng."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"ghi vào từ điển do người dùng xác định"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Cho phép ứng dụng ghi từ mới vào từ điển của người dùng."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"sửa đổi/xóa nội dung bộ nhớ USB"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"sửa đổi/xoá nội dung thẻ SD"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"sửa đổi/xóa nội dung thẻ SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"C.phép ứ.dụng ghi vào b.nhớ USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Cho phép ứng dụng ghi vào thẻ SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"sửa đổi/xóa nội dung trên bộ nhớ phương tiện cục bộ"</string>
@@ -517,7 +517,7 @@
     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Thay đổi mật khẩu mở khóa màn hình"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Khóa màn hình"</string>
     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kiểm tra cách và thời điểm khóa màn hình"</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Xoá tất cả dữ liệu"</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Xóa tất cả dữ liệu"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Xóa dữ liệu trên máy tính bảng mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string>
@@ -646,16 +646,16 @@
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Mã PUK"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Mã Pin mới"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Chạm để nhập mật khẩu"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khoá"</string>
+    <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khóa"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Nhập PIN để mở khóa"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Mã PIN không chính xác!"</string>
-    <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khoá, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
+    <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Số khẩn cấp"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Không có dịch vụ nào."</string>
-    <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khoá."</string>
-    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Trình đơn để mở khoá hoặc thực hiện cuộc gọi khẩn cấp."</string>
-    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Trình đơn để mở khoá."</string>
-    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Vẽ hình để mở khoá"</string>
+    <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khóa."</string>
+    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Trình đơn để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
+    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Trình đơn để mở khóa."</string>
+    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Vẽ hình để mở khóa"</string>
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Cuộc gọi khẩn cấp"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Quay lại cuộc gọi"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Chính xác!"</string>
@@ -677,32 +677,32 @@
     <string name="lockscreen_transport_play_description" msgid="5888422938351019426">"Nút phát"</string>
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"Nút dừng"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Chỉ cuộc gọi khẩn cấp"</string>
-    <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khoá"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khoá PUK."</string>
+    <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khóa"</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khóa PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Vui lòng xem Hướng dẫn Người dùng hoặc liên hệ với Trung tâm Chăm sóc Khách hàng."</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Thẻ SIM đã bị khoá."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Đang mở khoá thẻ SIM…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Thẻ SIM đã bị khóa."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Đang mở khóa thẻ SIM…"</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Bạn đã nhập sai mật khẩu <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giấy."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Bạn đã nhập sai PIN <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khoá điện thoại bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khóa điện thoại bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Bạn đã mở khóa máy tính bảng không đúng cách <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, máy tính bảng sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Bạn đã mở khóa điện thoại không đúng cách <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, điện thoại sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Bạn đã mở khóa máy tính bảng không đúng cách <xliff:g id="NUMBER">%d</xliff:g> lần. Bây giờ, máy tính bảng sẽ được đặt lại về mặc định ban đầu."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Bạn đã mở khóa điện thoại không đúng cách <xliff:g id="NUMBER">%d</xliff:g> lần. Bây giờ, điện thoại sẽ được đặt lại về mặc định ban đầu."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Đã quên hình?"</string>
-    <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Mở khoá tài khoản"</string>
+    <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Mở khóa tài khoản"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2446246026221678244">"Quá nhiều lần nhập hình!"</string>
-    <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Để mở khoá, hãy đăng nhập bằng tài khoản Google của bạn"</string>
+    <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Để mở khóa, hãy đăng nhập bằng tài khoản Google của bạn"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Tên người dùng (email)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Mật khẩu"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Đăng nhập"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Tên người dùng hoặc mật khẩu không hợp lệ."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Bạn quên tên người dùng hoặc mật khẩu?"\n"Hãy truy cập "<b>"google.com/accounts/recovery"</b></string>
     <string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Đang kiểm tra..."</string>
-    <string name="lockscreen_unlock_label" msgid="737440483220667054">"Mở khoá"</string>
+    <string name="lockscreen_unlock_label" msgid="737440483220667054">"Mở khóa"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Bật âm thanh"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Tắt âm thanh"</string>
     <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Đã bắt đầu vẽ hình"</string>
@@ -745,7 +745,7 @@
     <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>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"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 máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
-    <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="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 để xóa 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>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"thêm thư thoại"</string>
@@ -766,7 +766,7 @@
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"Trình đơn+"</string>
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"dấu cách"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"nhập"</string>
-    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"xoá"</string>
+    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"xóa"</string>
     <string name="search_go" msgid="8298016669822141719">"Tìm kiếm"</string>
     <string name="searchview_description_search" msgid="6749826639098512120">"Tìm kiếm"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"Truy vấn tìm kiếm"</string>
@@ -896,7 +896,7 @@
     <string name="capital_off" msgid="6815870386972805832">"TẮT"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Hoàn tất tác vụ đang sử dụng"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Sử dụng theo mặc định đối với tác vụ này."</string>
-    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Xoá mặc định trong Cài đặt Màn hình trang chủ &gt; Ứng dụng&gt; Quản lý ứng dụng."</string>
+    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Xóa mặc định trong Cài đặt Màn hình trang chủ &gt; Ứng dụng&gt; Quản lý ứng dụng."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Chọn tác vụ"</string>
     <string name="chooseUsbActivity" msgid="7892597146032121735">"Chọn ứng dụng cho thiết bị USB"</string>
     <string name="noApplications" msgid="1691104391758345586">"Không ứng dụng nào có thể thực hiện tác vụ này."</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Đăng nhập vào mạng Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Không thể kết nối với Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" có kết nối internet kém."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1019,7 +1022,7 @@
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Bạn có chắc chắn muốn định dạng thẻ SD không? Tất cả dữ liệu trên thẻ của bạn sẽ bị mất."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Định dạng"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
-    <string name="adb_active_notification_message" msgid="8470296818270110396">"Chọn để vô hiệu hoá gỡ lỗi USB."</string>
+    <string name="adb_active_notification_message" msgid="8470296818270110396">"Chọn để vô hiệu hóa gỡ lỗi USB."</string>
     <string name="select_input_method" msgid="6865512749462072765">"Chọn phương thức nhập"</string>
     <string name="configure_input_methods" msgid="6324843080254191535">"Định cấu hình phương thức nhập liệu"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1072,7 +1075,7 @@
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Yêu cầu Quyền"</string>
     <string name="permission_request_notification_with_subtitle" msgid="4325409589686688000">"Yêu cầu Quyền"\n"cho tài khoản <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"Phương thức nhập"</string>
-    <string name="sync_binding_label" msgid="3687969138375092423">"Đồng bộ hoá"</string>
+    <string name="sync_binding_label" msgid="3687969138375092423">"Đồng bộ hóa"</string>
     <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>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"Chia sẻ với..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Thiết bị đã bị khóa."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"Đang gửi..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Khởi chạy trình duyệt?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"Chấp nhận cuộc gọi?"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b92008f..f3ff28f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -319,7 +319,7 @@
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"开机时自动启动"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"允许应用程序在系统完成启动后立即自行启动。这样会延长平板电脑的启动时间,而且如果应用程序一直运行,会降低平板电脑的整体速度。"</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"允许应用程序在系统完成启动后即自行启动。这样会延长手机的启动时间,而且如果应用程序一直运行,会降低手机的整体速度。"</string>
-    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送置顶广播"</string>
+    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送持久广播"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可借此让平板电脑耗用太多内存,从而降低其速度或稳定性。"</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机耗用太多内存,从而降低其速度或稳定性。"</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"读取联系人数据"</string>
@@ -904,9 +904,9 @@
     <string name="aerr_application" msgid="932628488013092776">"很抱歉,“<xliff:g id="APPLICATION">%1$s</xliff:g>”已停止运行。"</string>
     <string name="aerr_process" msgid="4507058997035697579">"抱歉,进程“<xliff:g id="PROCESS">%1$s</xliff:g>”已停止运行。"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="8339738283149696827">"“<xliff:g id="APPLICATION">%2$s</xliff:g>”无响应。"\n\n"要将它关闭吗?"</string>
-    <string name="anr_activity_process" msgid="7018289416670457797">"活动“<xliff:g id="ACTIVITY">%1$s</xliff:g>”无响应。"\n\n"要将它关闭吗?"</string>
-    <string name="anr_application_process" msgid="7208175830253210526">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”无响应。要将它关闭吗?"</string>
+    <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
+    <string name="anr_activity_process" msgid="7018289416670457797">"活动 <xliff:g id="ACTIVITY">%1$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
+    <string name="anr_application_process" msgid="7208175830253210526">"<xliff:g id="APPLICATION">%1$s</xliff:g> 无响应。要将它关闭吗?"</string>
     <string name="anr_process" msgid="306819947562555821">"进程 <xliff:g id="PROCESS">%1$s</xliff:g> 无响应。"\n\n"要将它关闭吗?"</string>
     <string name="force_close" msgid="8346072094521265605">"确定"</string>
     <string name="report" msgid="4060218260984795706">"报告"</string>
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
     <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"连接到 Wi-Fi 网络"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" 互联网连接状况不佳。"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1181,7 +1184,7 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"导航首页"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上导航"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多选项"</string>
-    <string name="storage_internal" msgid="7556050805474115618">"内存空间"</string>
+    <string name="storage_internal" msgid="7556050805474115618">"内部存储空间"</string>
     <string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"编辑..."</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"分享方式..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"设备已锁定。"</string>
     <string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"正在发送..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"要启动浏览器吗?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"要接听电话吗?"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 80c3ee5..335df13 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -959,6 +959,9 @@
     <item quantity="one" msgid="1634101450343277345">"開啟可用 Wi-Fi 網路"</item>
     <item quantity="other" msgid="7915895323644292768">"開啟可用 Wi-Fi 網路"</item>
   </plurals>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 WiFi 網路"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" 網際網路連線狀況不佳。"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1218,10 +1221,7 @@
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"分享活動..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"裝置已鎖定。"</string>
     <string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
-    <!-- no translation found for sending (8715108995741758718) -->
-    <skip />
-    <!-- no translation found for launchBrowserDefault (2057951947297614725) -->
-    <skip />
-    <!-- no translation found for SetupCallDefault (6870275517518479651) -->
-    <skip />
+    <string name="sending" msgid="8715108995741758718">"傳送中..."</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"啟動「瀏覽器」嗎?"</string>
+    <string name="SetupCallDefault" msgid="6870275517518479651">"接聽電話嗎?"</string>
 </resources>
diff --git a/core/res/res/values-zu/donottranslate-cldr.xml b/core/res/res/values-zu/donottranslate-cldr.xml
new file mode 100644
index 0000000..df578ed
--- /dev/null
+++ b/core/res/res/values-zu/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">uJanuwari</string>
+    <string name="month_long_standalone_february">uFebruwari</string>
+    <string name="month_long_standalone_march">uMashi</string>
+    <string name="month_long_standalone_april">u-Apreli</string>
+    <string name="month_long_standalone_may">uMeyi</string>
+    <string name="month_long_standalone_june">uJuni</string>
+    <string name="month_long_standalone_july">uJulayi</string>
+    <string name="month_long_standalone_august">uAgasti</string>
+    <string name="month_long_standalone_september">uSepthemba</string>
+    <string name="month_long_standalone_october">u-Okthoba</string>
+    <string name="month_long_standalone_november">uNovemba</string>
+    <string name="month_long_standalone_december">uDisemba</string>
+
+    <string name="month_long_january">Januwari</string>
+    <string name="month_long_february">Februwari</string>
+    <string name="month_long_march">Mashi</string>
+    <string name="month_long_april">Apreli</string>
+    <string name="month_long_may">Meyi</string>
+    <string name="month_long_june">Juni</string>
+    <string name="month_long_july">Julayi</string>
+    <string name="month_long_august">Agasti</string>
+    <string name="month_long_september">Septhemba</string>
+    <string name="month_long_october">Okthoba</string>
+    <string name="month_long_november">Novemba</string>
+    <string name="month_long_december">Disemba</string>
+
+    <string name="month_medium_january">Jan</string>
+    <string name="month_medium_february">Feb</string>
+    <string name="month_medium_march">Mas</string>
+    <string name="month_medium_april">Apr</string>
+    <string name="month_medium_may">Mey</string>
+    <string name="month_medium_june">Jun</string>
+    <string name="month_medium_july">Jul</string>
+    <string name="month_medium_august">Aga</string>
+    <string name="month_medium_september">Sep</string>
+    <string name="month_medium_october">Okt</string>
+    <string name="month_medium_november">Nov</string>
+    <string name="month_medium_december">Dis</string>
+
+    <string name="month_shortest_january">J</string>
+    <string name="month_shortest_february">F</string>
+    <string name="month_shortest_march">M</string>
+    <string name="month_shortest_april">A</string>
+    <string name="month_shortest_may">M</string>
+    <string name="month_shortest_june">J</string>
+    <string name="month_shortest_july">J</string>
+    <string name="month_shortest_august">A</string>
+    <string name="month_shortest_september">S</string>
+    <string name="month_shortest_october">O</string>
+    <string name="month_shortest_november">N</string>
+    <string name="month_shortest_december">D</string>
+
+    <string name="day_of_week_long_sunday">Sonto</string>
+    <string name="day_of_week_long_monday">Msombuluko</string>
+    <string name="day_of_week_long_tuesday">Lwesibili</string>
+    <string name="day_of_week_long_wednesday">Lwesithathu</string>
+    <string name="day_of_week_long_thursday">uLwesine</string>
+    <string name="day_of_week_long_friday">Lwesihlanu</string>
+    <string name="day_of_week_long_saturday">Mgqibelo</string>
+
+    <string name="day_of_week_medium_sunday">Son</string>
+    <string name="day_of_week_medium_monday">Mso</string>
+    <string name="day_of_week_medium_tuesday">Bil</string>
+    <string name="day_of_week_medium_wednesday">Tha</string>
+    <string name="day_of_week_medium_thursday">Sin</string>
+    <string name="day_of_week_medium_friday">Hla</string>
+    <string name="day_of_week_medium_saturday">Mgq</string>
+
+    <string name="day_of_week_short_sunday">Son</string>
+    <string name="day_of_week_short_monday">Mso</string>
+    <string name="day_of_week_short_tuesday">Bil</string>
+    <string name="day_of_week_short_wednesday">Tha</string>
+    <string name="day_of_week_short_thursday">Sin</string>
+    <string name="day_of_week_short_friday">Hla</string>
+    <string name="day_of_week_short_saturday">Mgq</string>
+
+    <string name="day_of_week_shortest_sunday">S</string>
+    <string name="day_of_week_shortest_monday">M</string>
+    <string name="day_of_week_shortest_tuesday">B</string>
+    <string name="day_of_week_shortest_wednesday">T</string>
+    <string name="day_of_week_shortest_thursday">S</string>
+    <string name="day_of_week_shortest_friday">H</string>
+    <string name="day_of_week_shortest_saturday">M</string>
+
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="yesterday">Yesterday</string>
+    <string name="today">Today</string>
+    <string name="tomorrow">Tomorrow</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%Y-%m-%d</string>
+    <string name="numeric_date_format">yyyy-MM-dd</string>
+    <string name="numeric_date_template">"%s-%s-%s"</string>
+    <string name="month_day_year">%-e %B %Y</string>
+    <string name="time_of_day">%-l:%M:%S %p</string>
+    <string name="date_and_time">%-l:%M:%S %p %-e %b %Y</string>
+    <string name="date_time">%2$s %1$s</string>
+    <string name="time_date">%1$s %3$s</string>
+    <string name="abbrev_month_day_year">%-e %b %Y</string>
+    <string name="month_day">%B %-e</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%Y %B</string>
+    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%Y %b</string>
+    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
+    <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string>
+    <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
+    <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, y MMM d</string>
+</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index eadb0ea..e9321a4 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -73,11 +73,11 @@
     <string name="RestrictedOnData" msgid="8653794784690065540">"Insizakalo yedatha ivaliwe."</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Insizakalo ephuthumayo ivimbelwe."</string>
     <string name="RestrictedOnNormal" msgid="4953867011389750673">"Insizakalo yezwi ivimbelwe."</string>
-    <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Zonke izinsizakalo Zezwi zivimbelwe."</string>
+    <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Wonke amasevisi Wezwi avimbelwe."</string>
     <string name="RestrictedOnSms" msgid="8314352327461638897">"Insizakalo ye-SMS ivaliwe."</string>
-    <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Izinsizakalo Zezwi/Idatha zivimbelwe."</string>
-    <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Izinsizakalo Zezwi/SMS zivimbelwe."</string>
-    <string name="RestrictedOnAll" msgid="2714924667937117304">"Zonke izinsizakalo Zezwi/Idatha/SMS zivimbelwe."</string>
+    <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Amasevisi Wezwi/Idatha avimbelwe."</string>
+    <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Amasevisi Wezwi/SMS avimbelwe."</string>
+    <string name="RestrictedOnAll" msgid="2714924667937117304">"Wonke amasevisi Wezwi/Idatha/SMS avimbelwe."</string>
     <string name="serviceClassVoice" msgid="1258393812335258019">"Izwi"</string>
     <string name="serviceClassData" msgid="872456782077937893">"Idatha"</string>
     <string name="serviceClassFAX" msgid="5566624998840486475">"Ifeksi"</string>
@@ -99,7 +99,7 @@
     <string name="roamingText10" msgid="3992906999815316417">"Iyazulazula - Isici Sensizakalo Eyingxenye"</string>
     <string name="roamingText11" msgid="4154476854426920970">"Ibhena Yokuzulazula Ivuliwe"</string>
     <string name="roamingText12" msgid="1189071119992726320">"Ibhena yokuzulazula ivaliwe"</string>
-    <string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Izinsizakalo"</string>
+    <string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Isevisi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -463,7 +463,7 @@
     <string name="permlab_changeWifiState" msgid="7280632711057112137">"shintsha isimo se-WiFi"</string>
     <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Ivumela uhlelo lokusebena ukuxhuma futhi ingaxhumeki kumaphoyinti e-Wi-Fi, nokwenza izinguquko kumanethiwekhi e-Wi-Fi amisiwe."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ivumela isamukeli se-Wi-Fi Multicast"</string>
-    <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ivumela uhlelo lokusebenza ukuthola amaphakhethe ngokungaqondile angeyona awedivaysi yakho. Lokhu kungaba usizo lapho uthola izinsizakalo ezinikezwa eduze. Kusebenzisa amandla amaninigi kunemodi yokungajikijeli okuningi."</string>
+    <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ivumela uhlelo lokusebenza ukuthola amaphakhethe ngokungaqondile angeyona awedivaysi yakho. Lokhu kungaba usizo lapho uthola amasevisi anikezwa eduze. Kusebenzisa amandla amaninigi kunemodi yokungajikijeli okuningi."</string>
     <string name="permlab_accessWimaxState" msgid="2800410363171809280">"Buka isimo se-WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="8298035866227524023">"Ivumela uhlelo lokusebenza ukubuka ulwazi mayelana nesimo se-WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"shintsha isimo se-WiMAX"</string>
@@ -504,7 +504,7 @@
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Ivumela uhlelo lokusebenza ukusebenzisa insizakalo ye-SIP ukwenza/ukuthola amakholi e-Inthanethi."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"funda ukusetshenziswa komlando wohleloxhumano"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Ivumela uhlelo lokusebenza ukufunda umlando wokusebenza kohleloxhumano kwezinhleloxhumano eziqondile nezinhlelo zokusebenza."</string>
-    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"phatha uhleloxhumano lwenqubomgomo"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"phatha inqubomgomo yenethiwekhi"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Ivumela uhlelo lokusebenza ukuthi liphathe amapholisi wohleloxhumano kanye nokuchaza imithetho eqondile yohlelo lokusebenza."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"lungisa ukubala kokusebenza kohleloxhumano"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Ivumela ukulungisa kokuthi ukusebenza kohleloxhumano aluvumelwe kuhlelo lokusebenza. Ayisetshenziswa izinhlelo zokusebenza ezivamile."</string>
@@ -698,7 +698,7 @@
     <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Ukuvula, ngena ngemvumekwi-akhawunti ye-Google"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Igama lomsebenzisi (i-imeyli)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Iphasiwedi"</string>
-    <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ngena ngemvume"</string>
+    <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ngena"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Igama lomsebezisi elingalungile noma iphasiwedi."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Ukhohlwe igama lomsebenzisi noma iphasiwedi?"\n"Vakashela"<b>"google.com/accounts/recovery"</b></string>
     <string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Iyahlola..."</string>
@@ -768,8 +768,8 @@
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"faka"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"susa"</string>
     <string name="search_go" msgid="8298016669822141719">"Sesha"</string>
-    <string name="searchview_description_search" msgid="6749826639098512120">"Cinga"</string>
-    <string name="searchview_description_query" msgid="5911778593125355124">"Cinga umbuzo"</string>
+    <string name="searchview_description_search" msgid="6749826639098512120">"Sesha"</string>
+    <string name="searchview_description_query" msgid="5911778593125355124">"Umbuzo wosesho"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"xazulula umbuzo"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Thumela umbuzo"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"Ukusesha ngezwi"</string>
@@ -852,7 +852,7 @@
     <string name="hour" msgid="2126771916426189481">"ihora"</string>
     <string name="hours" msgid="894424005266852993">"amahora"</string>
     <string name="minute" msgid="9148878657703769868">"Okuncane"</string>
-    <string name="minutes" msgid="5646001005827034509">"imizuzu"</string>
+    <string name="minutes" msgid="5646001005827034509">"amaminithi"</string>
     <string name="second" msgid="3184235808021478">"isekhondi"</string>
     <string name="seconds" msgid="3161515347216589235">"amasekhondi"</string>
     <string name="week" msgid="5617961537173061583">"iviki"</string>
@@ -959,6 +959,9 @@
     <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>
+    <string name="wifi_available_sign_in" msgid="9157196203958866662">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string>
+    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" inoxhumano oluphansi lwe-inthanethi."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"I-WiFi Eqondile"</string>
@@ -968,7 +971,7 @@
     <string name="wifi_p2p_pin_go_negotiation_request_message" msgid="5177412094633377308">"Isethaphu yoheloxhumano oluqondile lwe-WiFi lwesicelo kusuka ku <xliff:g id="P2P_DEVICE_ADDRESS">%1$s</xliff:g>. Faka i-pin ukuze uqhubeke"</string>
     <string name="wifi_p2p_pin_display_message" msgid="2834049169114922902">"i-pin ye-WPS <xliff:g id="P2P_WPS_PIN">%1$s</xliff:g> idinga ukufakiwa kudivayisi ye-peer <xliff:g id="P2P_CLIENT_ADDRESS">%2$s</xliff:g> ukuze isethaphu yohleloxhumano iqhubeke"</string>
     <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"I-Wi-Fi Direct ivulekile"</string>
-    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Thinta ze uthole izisetho"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Thinta ukuze uthole izilungiselelo"</string>
     <string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Uhlelo lokusebenza olungaziwa"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Ithumela imiyalezo ye-SMS"</string>
@@ -976,7 +979,7 @@
     <string name="sms_control_yes" msgid="2532062172402615953">"KULUNGILE"</string>
     <string name="sms_control_no" msgid="1715320703137199869">"Khansela"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Ikhadi le-SIM likhishiwe"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"Uhleloxhumano lweselula aluzutholakala kuwena kuze kube uqala kabusha ufake i-SIM card efanele."</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"Inethiwekhi yeselula ngeke itholakale kuwena kuze kube uqala kabusha ufake ikhadi le-SIM elifanele."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwenziwe"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"Ikhadi le-SIM lengeziwe"</string>
     <string name="sim_added_message" msgid="1209265974048554242">"Kufanele uqalise kabusha idivaysi yakho ukuze ungene kuhleloxhumano yeselula."</string>
@@ -1078,8 +1081,8 @@
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
     <string name="vpn_title" msgid="8219003246858087489">"i-VPN ivuselelwe"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
-    <string name="vpn_text" msgid="1610714069627824309">"Thepha ukuphatha uhleloxhumano."</string>
-    <string name="vpn_text_long" msgid="4907843483284977618">"Ixhume ku-<xliff:g id="SESSION">%s</xliff:g>. Thepha ukuphatha uhleloxhumano."</string>
+    <string name="vpn_text" msgid="1610714069627824309">"Thepha ukuphatha inethiwekhi."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Ixhume ku-<xliff:g id="SESSION">%s</xliff:g>. Thepha ukuphatha inethiwekhi."</string>
     <string name="upload_file" msgid="2897957172366730416">"Khetha ifayela"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string>
     <string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d0ab8b1..af59198 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1493,6 +1493,10 @@
         <enum name="KEYCODE_LANGUAGE_SWITCH" value="204" />
         <enum name="KEYCODE_MANNER_MODE" value="205" />
         <enum name="KEYCODE_3D_MODE" value="206" />
+        <enum name="KEYCODE_CONTACTS" value="207" />
+        <enum name="KEYCODE_CALENDAR" value="208" />
+        <enum name="KEYCODE_MUSIC" value="209" />
+        <enum name="KEYCODE_CALCULATOR" value="210" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 25f7d25..30002c5 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -742,6 +742,7 @@
     <!-- Name of the wimax state tracker clas -->
     <string name="config_wimaxStateTrackerClassname"></string>
 
-    <!-- Name of screensaver components to look for if none has been chosen by the user -->
-    <string name="config_defaultDreamComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
+    <!-- Base "touch slop" value used by ViewConfiguration as a
+         movement threshold where scrolling should begin. -->
+    <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c8ba26a..7b785ec 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 /* //device/apps/common/assets/res/any/strings.xml
 **
@@ -286,6 +286,12 @@
     <string name="screen_lock">Screen lock</string>
     <!-- Button to turn off the phone, within the Phone Options dialog -->
     <string name="power_off">Power off</string>
+    <!-- Spoken description for ringer silent option. [CHAR LIMIT=NONE] -->
+    <string name="silent_mode_silent">Ringer off</string>
+    <!-- Spoken description for ringer vibrate option. [CHAR LIMIT=NONE] -->
+    <string name="silent_mode_vibrate">Ringer vibrate</string>
+    <!-- Spoken description for ringer normal option. [CHAR LIMIT=NONE] -->
+    <string name="silent_mode_ring">Ringer on</string>
 
     <!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. -->
     <string name="shutdown_progress">Shutting down\u2026</string>
@@ -2721,6 +2727,12 @@
         <item quantity="other">Open Wi-Fi networks available</item>
     </plurals>
 
+    <!-- A notification is shown when a captive portal network is detected.  This is the notification's title. -->
+    <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
+
+    <!-- A notification is shown when a captive portal network is detected.  This is the notification's message. -->
+    <string name="wifi_available_sign_in_detailed"><xliff:g id="wifi_network_ssid">%1$s</xliff:g></string>
+
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
      <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  The complete alert msg is: <hotspot name> + this string, i.e. "Linksys has a poor internet connection" -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b18d88f..fe5388b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -810,7 +810,7 @@
     
     <!-- Special theme for the recent apps dialog, to allow customization
          with overlays. -->
-    <style name="Theme.Dialog.RecentApplications">
+    <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowBackground">@android:color/transparent</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.RecentApplications</item>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index d23dfd3..3ffa085 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -38,7 +38,8 @@
     public int mSoftapIterations = 100;
     public int mScanIterations = 100;
     public int mReconnectIterations = 100;
-    public int mSleepTime = 30 * 1000;  // default sleep time is 30 seconds
+    // sleep time before restart wifi, default is set to 2 minutes
+    public int mSleepTime = 2 * 60 * 1000;
     public String mReconnectSsid = "securenetdhcp";
     public String mReconnectPassword = "androidwifi";
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index adf1883c8..0580ebc 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -62,6 +62,8 @@
     public static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
     public static final int SHORT_TIMEOUT = 5 * 1000;
     public static final long LONG_TIMEOUT = 50 * 1000;
+    // 2 minutes timer between wifi stop and start
+    public static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000;
     public static final int SUCCESS = 0;  // for Wifi tethering state change
     public static final int FAILURE = 1;
     public static final int INIT = -1;
@@ -247,6 +249,8 @@
         sleep(SHORT_TIMEOUT);
         removeConfiguredNetworksAndDisableWifi();
         mWifiRegexs = mCM.getTetherableWifiRegexs();
+        // after wifi is shutdown, wait for 2 minute to enable wifi
+        sleep(WIFI_STOP_START_INTERVAL);
      }
 
     public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
index d586396..5a4a2d0 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
@@ -77,10 +77,13 @@
                 mReason = "no state is recorded.";
                 return false;
             } else if (mStateDepository.size() > 1) {
-                Log.v(LOG_TAG, "no broadcast is expected, " +
-                        "instead broadcast is probably received");
-                mReason = "no broadcast is expected, instead broadcast is probably received";
-                return false;
+                for (int i = 0; i < mStateDepository.size(); i++) {
+                    if (mStateDepository.get(i) != mTransitionTarget) {
+                        Log.v(LOG_TAG, "state changed.");
+                        mReason = "Unexpected state change";
+                        return false;
+                    }
+                }
             } else if (mStateDepository.get(0) != mTransitionTarget) {
                 Log.v(LOG_TAG, mTransitionTarget + " is expected, but it is " +
                         mStateDepository.get(0));
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index d9b770a..b1f4bf1 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -66,7 +66,7 @@
         // Each test case will start with cellular connection
         if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
                 Settings.System.AIRPLANE_MODE_ON) == 1) {
-            Log.v(LOG_TAG, "airplane is not disabled, disable it.");
+            log("airplane is not disabled, disable it.");
             cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
         }
         if (!UtilHelper.isWifiOnly()) {
@@ -84,13 +84,13 @@
     @Override
     public void tearDown() throws Exception {
         cmActivity.finish();
-        Log.v(LOG_TAG, "tear down ConnectivityManagerTestActivity");
+        log("tear down ConnectivityManagerTestActivity");
         wl.release();
         cmActivity.removeConfiguredNetworksAndDisableWifi();
         // if airplane mode is set, disable it.
         if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
                 Settings.System.AIRPLANE_MODE_ON) == 1) {
-            Log.v(LOG_TAG, "disable airplane mode if it is enabled");
+            log("disable airplane mode if it is enabled");
             cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
         }
         super.tearDown();
@@ -104,17 +104,24 @@
         assertTrue("not connected to cellular network", extraNetInfo.isConnected());
     }
 
+    private void log(String message) {
+        Log.v(LOG_TAG, message);
+    }
+
+    private void sleep(long sleeptime) {
+        try {
+            Thread.sleep(sleeptime);
+        } catch (InterruptedException e) {}
+    }
+
     // Test case 1: Test enabling Wifi without associating with any AP, no broadcast on network
     //              event should be expected.
     @LargeTest
     public void test3GToWifiNotification() {
         // Enable Wi-Fi to avoid initial UNKNOWN state
         cmActivity.enableWifi();
-        try {
-            Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
-        } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
-        }
+        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+
         // Wi-Fi is disabled
         cmActivity.disableWifi();
 
@@ -123,11 +130,8 @@
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
                 State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
         // Wait for 10 seconds for broadcasts to be sent out
-        try {
-            Thread.sleep(10 * 1000);
-        } catch (Exception e) {
-            fail("thread in sleep is interrupted.");
-        }
+        sleep(10 * 1000);
+
         // As Wifi stays in DISCONNETED, Mobile statys in CONNECTED,
         // the connectivity manager will not broadcast any network connectivity event for Wifi
         NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
@@ -138,22 +142,18 @@
                 NetworkState.DO_NOTHING, State.DISCONNECTED);
         // Eanble Wifi without associating with any AP
         cmActivity.enableWifi();
-        try {
-            Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
-        } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
-        }
+        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
 
         // validate state and broadcast
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "the state for WIFI is changed");
-            Log.v(LOG_TAG, "reason: " +
+            log("the state for WIFI is changed");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue("state validation fail", false);
         }
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-            Log.v(LOG_TAG, "the state for MOBILE is changed");
-            Log.v(LOG_TAG, "reason: " +
+            log("the state for MOBILE is changed");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue("state validation fail", false);
         }
@@ -182,7 +182,7 @@
 
         assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        Log.v(LOG_TAG, "wifi state is enabled");
+        log("wifi state is enabled");
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
         if (!UtilHelper.isWifiOnly()) {
@@ -192,15 +192,15 @@
 
         // validate states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "Wifi state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Wifi state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
         if (!UtilHelper.isWifiOnly()) {
             if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-                Log.v(LOG_TAG, "Mobile state transition validation failed.");
-                Log.v(LOG_TAG, "reason: " +
+                log("Mobile state transition validation failed.");
+                log("reason: " +
                         cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue(false);
             }
@@ -219,16 +219,11 @@
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
-        try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
-        } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
-        }
-
+        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         // Disable Wifi
-        Log.v(LOG_TAG, "Disable Wifi");
+        log("Disable Wifi");
         if (!cmActivity.disableWifi()) {
-            Log.v(LOG_TAG, "disable Wifi failed");
+            log("disable Wifi failed");
             return;
         }
 
@@ -254,8 +249,10 @@
         cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.TO_CONNECTION, State.CONNECTED);
 
+        // wait for 2 minutes before restart wifi
+        sleep(ConnectivityManagerTestActivity.WIFI_STOP_START_INTERVAL);
         // Enable Wifi again
-        Log.v(LOG_TAG, "Enable Wifi again");
+        log("Enable Wifi again");
         cmActivity.enableWifi();
 
         // Wait for Wifi to be connected and mobile to be disconnected
@@ -268,8 +265,8 @@
 
         // validate wifi states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "Wifi state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Wifi state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
@@ -288,11 +285,7 @@
             ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
-        try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
-        } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
-        }
+        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
 
         NetworkInfo networkInfo;
         if (!UtilHelper.isWifiOnly()) {
@@ -318,15 +311,15 @@
 
         // validate states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "Wifi state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Wifi state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
         if (!UtilHelper.isWifiOnly()) {
             if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-                Log.v(LOG_TAG, "Mobile state transition validation failed.");
-                Log.v(LOG_TAG, "reason: " +
+                log("Mobile state transition validation failed.");
+                log("reason: " +
                         cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue(false);
             }
@@ -346,19 +339,16 @@
         assertEquals(State.DISCONNECTED, networkInfo.getState());
 
         // Enable airplane mode
+        log("Enable airplane mode");
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
-        try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
-        } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
-        }
+        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
 
         networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         assertEquals(State.DISCONNECTED, networkInfo.getState());
 
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-            Log.v(LOG_TAG, "Mobile state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Mobile state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue(false);
         }
@@ -381,14 +371,14 @@
 
         // Validate the state transition
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-            Log.v(LOG_TAG, "Mobile state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Mobile state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue(false);
         }
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-          Log.v(LOG_TAG, "Wifi state transition validation failed.");
-          Log.v(LOG_TAG, "reason: " +
+          log("Wifi state transition validation failed.");
+          log("reason: " +
                   cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
           assertTrue(false);
         }
@@ -399,6 +389,7 @@
     public void testDataConnectionOverAMWithWifi() {
         assertNotNull("SSID is null", TEST_ACCESS_POINT);
         // Eanble airplane mode
+        log("Enable airplane mode");
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
 
         NetworkInfo networkInfo;
@@ -423,15 +414,15 @@
 
         // validate state and broadcast
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "state validate for Wifi failed");
-            Log.v(LOG_TAG, "reason: " +
+            log("state validate for Wifi failed");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue("State validation failed", false);
         }
         if (!UtilHelper.isWifiOnly()) {
             if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-                Log.v(LOG_TAG, "state validation for Mobile failed");
-                Log.v(LOG_TAG, "reason: " +
+                log("state validation for Mobile failed");
+                log("reason: " +
                         cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue("state validation failed", false);
             }
@@ -454,7 +445,7 @@
         try {
             Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
+            log("exception: " + e.toString());
         }
 
         // Enable airplane mode without clearing Wifi
@@ -466,7 +457,7 @@
         try {
             Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
+            log("exception: " + e.toString());
         }
 
         // Prepare for state validation
@@ -487,8 +478,8 @@
 
         // validate the state transition
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
-            Log.v(LOG_TAG, "Wifi state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
+            log("Wifi state transition validation failed.");
+            log("reason: " +
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
@@ -511,13 +502,13 @@
         try {
             Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
-            Log.v(LOG_TAG, "exception: " + e.toString());
+            log("exception: " + e.toString());
         }
 
         // Disconnect from the current AP
-        Log.v(LOG_TAG, "disconnect from the AP");
+        log("disconnect from the AP");
         if (!cmActivity.disconnectAP()) {
-            Log.v(LOG_TAG, "failed to disconnect from " + TEST_ACCESS_POINT);
+            log("failed to disconnect from " + TEST_ACCESS_POINT);
         }
 
         // Verify the connectivity state for Wifi is DISCONNECTED
@@ -525,7 +516,7 @@
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         if (!cmActivity.disableWifi()) {
-            Log.v(LOG_TAG, "disable Wifi failed");
+            log("disable Wifi failed");
             return;
         }
         assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 22b1759..d33a445 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -136,7 +136,7 @@
 
         // step 2: verify Wifi state and network state;
         assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.CONNECTED, 2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                State.CONNECTED, 6 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // step 3: verify the current connected network is the given SSID
         assertNotNull("Wifi connection returns null", mAct.mWifiManager.getConnectionInfo());
@@ -166,8 +166,9 @@
             String ssid = networks.get(i).SSID;
             log("-- START Wi-Fi connection test to : " + ssid + " --");
             connectToWifi(networks.get(i));
-            sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT,
-                    "interruped while waiting for wifi disabled.");
+            // wait for 2 minutes between wifi stop and start
+            sleep(ConnectivityManagerTestActivity.WIFI_STOP_START_INTERVAL,
+                  "interruped while connected to wifi");
             log("-- END Wi-Fi connection test to " + ssid + " -- ");
         }
     }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 7578e67..2069789 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -63,10 +63,12 @@
     private final static long WIFI_IDLE_MS = 60 * 1000;
 
     /**
-     * The delay for Wi-Fi to get into idle, after screen off + WIFI_IDEL_MS + WIFI_IDLE_DELAY
-     * the Wi-Fi should be in idle mode and device should be in cellular mode.
+     * Delay after issuing wifi shutdown.
+     * The framework keep driver up for at leat 2 minutes to avoid problems
+     * that a quick shutdown could cause on wext driver and protentially
+     * on cfg based driver
      */
-    private final static long WIFI_IDLE_DELAY = 3 * 1000;
+    private final static long WIFI_SHUTDOWN_DELAY = 2 * 60 * 1000;
 
     private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
     private ConnectivityManagerTestActivity mAct;
@@ -92,6 +94,9 @@
         mPassword = mRunner.mReconnectPassword;
         mScanIterations = mRunner.mScanIterations;
         mWifiSleepTime = mRunner.mSleepTime;
+        log(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
+            + "mScanIterations(%d), mWifiSleepTime(%d)", mReconnectIterations, mSsid,
+            mPassword, mScanIterations, mWifiSleepTime));
         mOutputWriter = new BufferedWriter(new FileWriter(new File(
                 Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
         mAct.turnScreenOn();
@@ -248,6 +253,7 @@
         assertTrue("Wi-Fi is connected, but no data connection.", mAct.pingTest(null));
 
         int i;
+        long sum = 0;
         for (i = 0; i < mReconnectIterations; i++) {
             // 1. Put device into sleep mode
             // 2. Wait for the device to sleep for sometime, verify wi-fi is off and mobile is on.
@@ -261,7 +267,7 @@
             PowerManager pm =
                 (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
             assertFalse(pm.isScreenOn());
-            sleep(WIFI_IDLE_MS, "Interruped while wait for wifi to be idle");
+            sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY, "Interruped while wait for wifi to be idle");
             assertTrue("Wait for Wi-Fi to idle timeout",
                     mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
                     6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT));
@@ -269,9 +275,9 @@
                 // use long timeout as the pppd startup may take several retries.
                 assertTrue("Wait for cellular connection timeout",
                         mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                        ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                        2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
             }
-            sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode");
+            sleep(mWifiSleepTime, "Interrupted while device is in sleep mode");
             // Verify the wi-fi is still off and data connection is on
             assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
                     mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
@@ -284,12 +290,18 @@
 
             // Turn screen on again
             mAct.turnScreenOn();
+            // Measure the time for Wi-Fi to get connected
+            long startTime = System.currentTimeMillis();
             assertTrue("Wait for Wi-Fi enable timeout after wake up",
                     mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                     ConnectivityManagerTestActivity.SHORT_TIMEOUT));
             assertTrue("Wait for Wi-Fi connection timeout after wake up",
                     mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                    6 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            long connectionTime = System.currentTimeMillis() - startTime;
+            sum += connectionTime;
+            log("average reconnection time is: " + sum/(i+1));
+
             assertTrue("Reconnect to Wi-Fi network, but no data connection.", mAct.pingTest(null));
         }
         if (i == mReconnectIterations) {
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
index 58f158c..60b6dc1 100644
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ b/core/tests/bluetoothtests/AndroidManifest.xml
@@ -19,6 +19,8 @@
 
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
index abd7d9a..755e7c4 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
@@ -32,6 +32,8 @@
 public class BluetoothStressTest extends InstrumentationTestCase {
     private static final String TAG = "BluetoothStressTest";
     private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
+    /** The amount of time to sleep between issuing start/stop SCO in ms. */
+    private static final long SCO_SLEEP_TIME = 2 * 1000;
 
     private BluetoothTestUtils mTestUtils;
 
@@ -380,11 +382,20 @@
         for (int i = 0; i < iterations; i++) {
             mTestUtils.writeOutput("startStopSco iteration " + (i + 1) + " of " + iterations);
             mTestUtils.startSco(adapter, device);
+            sleep(SCO_SLEEP_TIME);
             mTestUtils.stopSco(adapter, device);
+            sleep(SCO_SLEEP_TIME);
         }
 
         mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.HEADSET, null);
         mTestUtils.unpair(adapter, device);
         mTestUtils.disable(adapter);
     }
+
+    private void sleep(long time) {
+        try {
+            Thread.sleep(time);
+        } catch (InterruptedException e) {
+        }
+    }
 }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index 42e5cd1..4858be8 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -1425,7 +1425,7 @@
     }
 
     private StartStopScoReceiver getStartStopScoReceiver(int expectedFlags) {
-        String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED};
+        String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED};
         StartStopScoReceiver receiver = new StartStopScoReceiver(expectedFlags);
         addReceiver(receiver, actions);
         return receiver;
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index 3521296..ec12124 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -26,6 +26,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
+import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityManager;
@@ -54,28 +55,31 @@
     // Timeout before give up wait for the system to process an accessibility setting change.       
     private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
 
+    // Timeout for the accessibility state of an Activity to be fully initialized.
+    private static final int TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS = 100;
+
     // Handle to a connection to the AccessibilityManagerService
-    private static IAccessibilityServiceConnection sConnection;
+    private static int sConnectionId = View.NO_ID;
 
     // The last received accessibility event
-    private static volatile AccessibilityEvent sLastFocusAccessibilityEvent;
+    private volatile AccessibilityEvent mLastAccessibilityEvent;
 
     public InterrogationActivityTest() {
         super(InterrogationActivity.class);
     }
 
+    @Override
+    public void setUp() throws Exception {
+        ensureConnection();
+        bringUpActivityWithInitalizedAccessbility();
+    }
+
     @LargeTest
     public void testFindAccessibilityNodeInfoByViewId() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertNotNull(button);
             assertEquals(0, button.getChildCount());
 
@@ -120,15 +124,9 @@
     public void testFindAccessibilityNodeInfoByViewText() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view by text
-            List<AccessibilityNodeInfo> buttons =  AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfosByViewTextInActiveWindow(connection, "butto");
+            List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId, "butto");
             assertEquals(9, buttons.size());
         } finally {
             if (DEBUG) {
@@ -143,15 +141,11 @@
     public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
+            bringUpActivityWithInitalizedAccessbility();
 
             // find a view by text
-            List<AccessibilityNodeInfo> buttons =  AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfosByViewTextInActiveWindow(connection,
+            List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfosByViewTextInActiveWindow(sConnectionId,
                         "contentDescription");
             assertEquals(1, buttons.size());
         } finally {
@@ -167,12 +161,6 @@
     public void testTraverseAllViews() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // make list of expected nodes
             List<String> classNameAndTextList = new ArrayList<String>();
             classNameAndTextList.add("android.widget.LinearLayout");
@@ -190,7 +178,7 @@
             classNameAndTextList.add("android.widget.ButtonButton9");
 
             AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.root);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.root);
             assertNotNull("We must find the existing root.", root);
 
             Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -227,23 +215,17 @@
     public void testPerformAccessibilityActionFocus() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view and make sure it is not focused
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isFocused());
 
             // focus the view
             assertTrue(button.performAction(ACTION_FOCUS));
 
             // find the view again and make sure it is focused
-            button =  AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertTrue(button.isFocused());
         } finally {
             if (DEBUG) {
@@ -257,15 +239,9 @@
     public void testPerformAccessibilityActionClearFocus() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view and make sure it is not focused
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isFocused());
 
             // focus the view
@@ -273,7 +249,7 @@
 
             // find the view again and make sure it is focused
             button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertTrue(button.isFocused());
 
             // unfocus the view
@@ -281,7 +257,7 @@
 
             // find the view again and make sure it is not focused
             button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isFocused());
         } finally {
             if (DEBUG) {
@@ -296,15 +272,9 @@
     public void testPerformAccessibilityActionSelect() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view and make sure it is not selected
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isSelected());
 
             // select the view
@@ -312,7 +282,7 @@
 
             // find the view again and make sure it is selected
             button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertTrue(button.isSelected());
         } finally {
             if (DEBUG) {
@@ -326,15 +296,9 @@
     public void testPerformAccessibilityActionClearSelection() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view and make sure it is not selected
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isSelected());
 
             // select the view
@@ -342,15 +306,15 @@
 
             // find the view again and make sure it is selected
             button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertTrue(button.isSelected());
 
             // unselect the view
             assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
 
             // find the view again and make sure it is not selected
-            button =  AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isSelected());
         } finally {
             if (DEBUG) {
@@ -365,30 +329,24 @@
     public void testAccessibilityEventGetSource() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();  
-
             // find a view and make sure it is not focused
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             assertFalse(button.isSelected());
 
             // focus the view
             assertTrue(button.performAction(ACTION_FOCUS));
 
-            synchronized (sConnection) {
+            synchronized (this) {
                 try {
-                    sConnection.wait(500);
+                    wait(TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS);
                 } catch (InterruptedException ie) {
                     /* ignore */
                 }
             }
 
             // check that last event source
-            AccessibilityNodeInfo source = sLastFocusAccessibilityEvent.getSource();
+            AccessibilityNodeInfo source = mLastAccessibilityEvent.getSource();
             assertNotNull(source);
 
             // bounds
@@ -430,15 +388,9 @@
     public void testObjectContract() throws Exception {
         final long startTimeMillis = SystemClock.uptimeMillis();
         try {
-            // hook into the system first
-            IAccessibilityServiceConnection connection = getConnection();
-
-            // bring up the activity
-            getActivity();
-
             // find a view and make sure it is not focused
             AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
-                .findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
             AccessibilityNodeInfo parent = button.getParent();
             final int childCount = parent.getChildCount();
             for (int i = 0; i < childCount; i++) {
@@ -459,24 +411,57 @@
         }
     }
 
-    @Override
-    protected void scrubClass(Class<?> testCaseClass) {
-        /* intentionally do not scrub */
+    private void bringUpActivityWithInitalizedAccessbility() {
+        mLastAccessibilityEvent = null;
+        // bring up the activity
+        getActivity();
+
+        final long startTimeMillis = SystemClock.uptimeMillis();
+        while (true) {
+            if (mLastAccessibilityEvent != null) {
+                final int eventType = mLastAccessibilityEvent.getEventType();
+                if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+                    return;
+                }
+            }
+            final long remainingTimeMillis = TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS
+                    - (SystemClock.uptimeMillis() - startTimeMillis);
+            if (remainingTimeMillis <= 0) {
+                return;
+            }
+            synchronized (this) {
+                try {
+                    wait(remainingTimeMillis);
+                } catch (InterruptedException e) {
+                    /* ignore */
+                }
+            }
+        }
     }
 
-    private IAccessibilityServiceConnection getConnection() throws Exception {
-        if (sConnection == null) {
+    private void ensureConnection() throws Exception {
+        if (sConnectionId == View.NO_ID) {
             IEventListener listener = new IEventListener.Stub() {
-                public void setConnection(IAccessibilityServiceConnection connection) {}
+                public void setConnection(IAccessibilityServiceConnection connection,
+                        int connectionId) {
+                    sConnectionId = connectionId;
+                    if (connection != null) {
+                        AccessibilityInteractionClient.getInstance().addConnection(connectionId,
+                                connection);
+                    } else {
+                        AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
+                    }
+                    synchronized (this) {
+                        notifyAll();
+                    }
+                }
 
                 public void onInterrupt() {}
 
                 public void onAccessibilityEvent(AccessibilityEvent event) {
-                    if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
-                        sLastFocusAccessibilityEvent = AccessibilityEvent.obtain(event);
-                    }
-                    synchronized (sConnection) {
-                        sConnection.notifyAll();
+                    mLastAccessibilityEvent = AccessibilityEvent.obtain(event);
+                    synchronized (this) {
+                        notifyAll();
                     }
                 }
             };
@@ -485,28 +470,11 @@
                 AccessibilityManager.getInstance(getInstrumentation().getContext());
 
             synchronized (this) {
-                if (!accessibilityManager.isEnabled()) {
-                    // Make sure we wake ourselves as the desired state is propagated.
-                    accessibilityManager.addAccessibilityStateChangeListener(
-                            new AccessibilityManager.AccessibilityStateChangeListener() {
-                                public void onAccessibilityStateChanged(boolean enabled) {
-                                    synchronized (this) {
-                                        notifyAll();
-                                    }
-                                }
-                            });
-                    IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
+                IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
                         ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
-                    sConnection = manager.registerEventListener(listener);
-
-                    wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
-                } else {
-                    IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
-                          ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
-                    sConnection = manager.registerEventListener(listener);
-                }
+                manager.registerEventListener(listener);
+                wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
             }
         }
-        return sConnection;
     }
 }
diff --git a/data/fonts/DroidSansArmenian.ttf b/data/fonts/DroidSansArmenian.ttf
index 62f67e0..6fafa54 100644
--- a/data/fonts/DroidSansArmenian.ttf
+++ b/data/fonts/DroidSansArmenian.ttf
Binary files differ
diff --git a/data/fonts/DroidSansGeorgian.ttf b/data/fonts/DroidSansGeorgian.ttf
index 743ae66..3a2e9fb 100644
--- a/data/fonts/DroidSansGeorgian.ttf
+++ b/data/fonts/DroidSansGeorgian.ttf
Binary files differ
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 10de6ac..fdd9040 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -159,7 +159,7 @@
 # key 137 "KEY_CUT"
 # key 138 "KEY_HELP"
 key 139   MENU              WAKE_DROPPED
-# key 140 "KEY_CALC"
+key 140   CALCULATOR
 # key 141 "KEY_SETUP"
 key 142   POWER             WAKE
 key 143   POWER             WAKE
@@ -190,7 +190,7 @@
 key 168   MEDIA_REWIND
 key 169   CALL
 # key 170 "KEY_ISO"
-# key 171 "KEY_CONFIG"
+key 171   MUSIC
 key 172   HOME
 # key 173 "KEY_REFRESH"
 # key 174 "KEY_EXIT"
@@ -232,7 +232,7 @@
 # key 210 "KEY_PRINT"
 # key 211 "KEY_HP"
 key 212   CAMERA
-# key 213 "KEY_SOUND"
+key 213   MUSIC
 # key 214 "KEY_QUESTION"
 key 215   ENVELOPE
 # key 216 "KEY_CHAT"
@@ -344,7 +344,7 @@
 # key 394 "KEY_DIRECTORY"
 # key 395 "KEY_LIST"
 # key 396 "KEY_MEMO"
-# key 397 "KEY_CALENDAR"
+key 397   CALENDAR
 # key 398 "KEY_RED"
 # key 399 "KEY_GREEN"
 # key 400 "KEY_YELLOW"
@@ -364,6 +364,7 @@
 # key 414 "KEY_TEEN"
 # key 415 "KEY_TWEN"
 
+key 429   CONTACTS
 
 # key 448 "KEY_DEL_EOL"
 # key 449 "KEY_DEL_EOS"
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index cbb4b29..a84eb4e 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -39,12 +39,12 @@
 site, registering test accounts, and handling refunds when necessary.</p>
 
 <p>You must have an Android Market publisher account to register test accounts. And you must have a
-Google Checkout Merchant account to create a product list and issue refunds to your users. If you
+Google Checkout merchant account to create a product list and issue refunds to your users. If you
 already have a publisher account on Android Market, you can use your existing account. You do not
 need to register for a new account to support in-app billing. If you do not have a publisher
 account, you can register as an Android Market developer and set up a publisher account at the
 Android Market <a href="http://market.android.com/publish">publisher site</a>. If you do not have a
-Google Checkout Merchant account, you can register for one at the <a
+Google Checkout merchant account, you can register for one at the <a
 href="http://checkout.google.com">Google Checkout site</a>.</p>
 
 <h2 id="billing-list-setup">Creating a Product List</h2>
@@ -57,7 +57,7 @@
 <p>You can access an application's product list by clicking the <strong>In-App Products</strong>
 link that appears under each of the applications that are listed for your publisher account (see
 figure 1). The <strong>In-App Products</strong> link appears only if you have a Google Checkout
-Merchant account and an application's manifest includes the <code>com.android.vending.BILLING</code>
+merchant account and an application's manifest includes the <code>com.android.vending.BILLING</code>
 permission.</p>
 
 <img src="{@docRoot}images/billing_product_list_entry.png" height="548" id="figure1" />
@@ -71,20 +71,37 @@
 you are selling in your application. It does not store any digital content. You are responsible for
 storing and delivering the digital content that you sell in your applications.</p>
 
-<img src="{@docRoot}images/billing_product_list.png" height="560" id="figure2" />
+<img src="{@docRoot}images/billing_product_list.png" height="658" id="figure2" />
 <p class="img-caption">
   <strong>Figure 2.</strong> An application's product list.
 </p>
 
-<p>You can create a product list for a published application or a draft application that's been
-uploaded and saved to the Android Market site. However, you must have a Google Checkout Merchant
+<p>You can create a product list for any published application or any draft application that's been
+uploaded and saved to the Android Market site. However, you must have a Google Checkout merchant
 account and the application's manifest must include the <code>com.android.vending.BILLING</code>
 permission. If an application's manifest does not include this permission, you will be able to edit
 existing items in the product list but you will not be able to add new items to the list. For more
-information, see <a href="#billing-permission">Modifying your application's AndroidManifest.xml
-file</a>.</p>
+information about this permission, see
+<a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-permission">Updating Your
+Application's Manifest</a>.</p>
 
-<p>To create a product list for an application, follow these steps:</p>
+<p>In addition, an application package can have only one product list. If you create a product
+list for an application, and you use the <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">multiple APK feature</a> to distribute
+more than one APK for that application, the product list applies to all APK versions that are
+associated with the application listing. You cannot create individual product lists for each APK if
+you are using the multiple APK feature.</p>
+
+<p>You can add items to a product list two ways: you can add items one at a time by using the In-app
+Products UI (see figure 3), or you can add a batch of items by importing the items from a
+comma-separated values (CSV) file (see figure 2). Adding items one at a time is useful if your
+application has only a few in-app items or you are adding only a few items to a
+product list for testing purposes. The CSV file method is useful if your application has a large
+number of in-app items.</p>
+
+<h3 id="billing-form-add">Adding items one at a time to a product list</h3>
+
+<p>To add an item to a product list using the In-app Products UI, follow these steps:</p>
 
 <ol>
   <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
@@ -92,7 +109,7 @@
   <strong>In-app Products</strong>.</li>
   <li>On the In-app Products List page, click <strong>Add in-app product</strong>.</li>
   <li>On the Create New In-app Product page (see figure 3), provide details about the item you are
-  selling and then click <strong>Save</strong>.</li>
+  selling and then click <strong>Save</strong> or <strong>Publish</strong>.</li>
 </ol>
 
 <img src="{@docRoot}images/billing_list_form.png" height="840" id="figure3" />
@@ -109,25 +126,31 @@
     (0-9), underlines (_), and dots (.). The product ID "android.test" is reserved, as are all
     product IDs that start with "android.test."</p>
     <p>In addition, you cannot modify an item's product ID after it is created, and you cannot reuse
-    a product ID, even if you delete the item previously using the product ID.</p>
+    a product ID.</p>
   </li>
-  <li><strong>Purchase type</strong>
-    <p>The purchase type can be "managed per user account" or "unmanaged." You can specify an item's
-    purchase type only through the publisher site and you can never change an item's purchase type
-    once you specify it. For more information, see <a href="#billing_purchase_type">Choosing a
-    purchase type</a> later in this document.</p>
+  <li><strong>Purchase Type</strong>
+    <p>The purchase type can be <strong>Managed per user account</strong> or <strong>
+    Unmanaged</strong>. You can never change an item's purchase type after you set it. For more
+    information, see <a href="#billing-purchase-type">Choosing a purchase type</a> later in this
+    document.</p>
   </li>
   <li><strong>Publishing State</strong>
-    <p>An item's publishing state can be "published" or "unpublished." However, to be visible to a
-    user during checkout, an item's publishing state must be set to "published" and the item's
-    application must be published on Android Market.</p>
+    <p>An item's publishing state can be <strong>Published</strong> or <strong>Unpublished
+    </strong>. To be visible to a user during checkout, an item's publishing state must be set to
+    <strong>Published</strong> and the item's application must be published on Android Market.</p>
     <p class="note"><strong>Note:</strong> This is not true for test accounts. An item is visible to
     a test account if the application is not published and the item is published. See <a
     href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-real">Testing In-app
     Billing</a> for more information.</p>
   </li>
   <li><strong>Language</strong>
-    <p>A product list inherits its language from the parent application.</p>
+    <p>The language setting determines which languages are used to display the item title and
+    item description during checkout. A product list inherits its default language from the
+    parent application. You can add more languages by clicking <strong>add language</strong>. You
+    can also choose to have the title and description automatically translated from the default
+    language by selecting the <strong>Fill fields with auto translation</strong> checkbox (see
+    figure 4). If you do not use the auto translation feature, you must provide the translated
+    versions of the title and description.</p>
   </li>
   <li><strong>Title</strong>
     <p>The title is a short descriptor for the item. For example, "Sleeping potion." Titles must be
@@ -141,9 +164,20 @@
     visible to users during checkout. Descriptions can be up to 80 characters in length.</p>
   </li>
   <li><strong>Price</strong>
-    <p>Every item must have a price greater than zero; you cannot set a price of "0" (free).</p>
+    <p>You must provide a default price in your home currency. You can also provide prices in other
+    currencies, but you can do this only if a currency's corresponding country is listed as a
+    target country for your application. You can specify target countries on the Edit Application
+    page in the Android Market developer console.</p>
+    <p>To specify prices in other currencies, you can manually enter the price for each
+    currency or you can click <strong>Auto Fill</strong> and let Android Market do a one-time
+    conversion from your home currency to the currencies you are targeting (see figure 4).</p>
   </li>
 </ul>
+<img src="{@docRoot}images/billing_list_form_2.png" height="1226" id="figure4" />
+<p class="img-caption">
+  <strong>Figure 4.</strong> Specifying additional currencies and additional languages for the
+  item title and description.
+</p>
 
 <p>For more information about product IDs and product lists, see <a
 href="http://market.android.com/support/bin/answer.py?answer=1072599">Creating In-App Product
@@ -154,6 +188,197 @@
 <p class="note"><strong>Note</strong>: Be sure to plan your product ID namespace. You cannot reuse
 or modify product IDs after you save them.</p>
 
+<h3 id="billing-bulk-add">Adding a batch of items to a product list</h3>
+
+<p>To add a batch of items to a product list using a CSV file, you first need to create your CSV
+file. The data values that you specify in the CSV file represent the same data values you specify
+manually through the In-app Products UI (see <a href="#billing-form-add">Adding items one at a time
+to a product list</a>). The CSV file uses commas (,) and semi-colons (;) to separate data values.
+Commas are used to separate primary data values, and semi-colons are used to separate subvalues. For
+example, the syntax for the CSV file is as follows:</p>
+
+<p>"<em>product_id</em>","<em>publish_state</em>","<em>purchase_type</em>","<em>autotranslate</em>
+","<em>locale</em>; <em>title</em>; <em>description</em>","<em>autofill</em>","<em>country</em>;
+<em>price</em>"
+</p>
+
+<p>Descriptions and usage details are provided below.</p>
+
+<ul>
+  <li><em>product_id</em>
+    <p>This is equivalent to the In-app Product ID setting in the In-app Products UI. If you specify
+    a <em>product_id</em> that already exists in a product list, and you choose to overwrite
+    the product list while importing the CSV file, the data for the existing item is overwritten with
+    the values specified in the CSV file. The overwrite feature does not delete items that are on a
+    product list but not present in the CSV file.</p>
+  </li>
+  <li><em>publish_state</em>
+    <p>This is equivalent to the Publishing State setting in the In-app Products UI. Can be <code>
+    published</code> or <code>unpublished</code>.</p>
+  </li>
+  <li><em>purchase_type</em>
+    <p>This is equivalent to the Purchase Type setting in the In-app Products UI. Can be <code>
+    managed_by_android</code>, which is equivalent to <strong>Managed per user account
+    </strong> in the In-app Products UI, or <code>managed_by_publisher</code>, which is equivalent
+    to <strong>Unmanaged</strong> in the In-app Products UI.</p>
+  </li>
+  <li><em>autotranslate</em>
+    <p>This is equivalent to selecting the <strong>Fill fields with auto translation</strong>
+    checkbox in the In-app Products UI. Can be <code>true</code> or <code>false</code>.</p>
+  </li>
+  <li><em>locale</em>
+    <p>This is equivalent to the Language setting in the In-app Products UI. You must have an entry
+    for the default locale. The default locale must be the first entry in the list of
+    locales, and it must include a <em>title</em> and <em>description</em>. If you want to provide
+    translated versions of the <em>title</em> and <em>description</em> in addition to the default,
+    you must use the following syntax rules:</p>
+    <p>If <em>autotranslate</em> is <code>true</code>, you must specify the default locale,
+    default title, default description, and other locales using the following format:</p>
+    <p>"true,"<em>default_locale</em>; <em>default_locale_title</em>;
+    <em>default_locale_description</em>; <em>locale_2</em>;    <em>locale_3</em>, ..."</p>
+    <p>If <em>autotranslate</em> is <code>false</code>, you must specify the default locale,
+    default title, and default description as well as the translated titles and descriptions using
+    the following format:</p>
+    <p>"false,"<em>default_locale</em>; <em>default_locale_title</em>;
+    <em>default_locale_description</em>; <em>locale_2</em>; <em>locale_2_title</em>;
+    <em>local_2_description</em>; <em>locale_3</em>; <em>locale_3_title</em>;
+     <em>locale_3_description</em>; ..."</p>
+    <p>See table 1 for a list of the language codes you can use with the <em>locale</em> field.</p>
+  </li>
+  <li><em>title</em>
+    <p>This is equivalent to the Title setting in the In-app Products UI. If the <em>title</em>
+    contains a semicolon, it must be escaped with a backslash (for example, "\;"). A backslash
+    should also be escaped with a backslash (for example, "\\">.</p>
+  </li>
+  <li><em>description</em>
+    <p>This is equivalent to the Description in the In-app Products UI. If the <em>description</em>
+    contains a semicolon, it must be escaped with a backslash (for example, "\;"). A backslash
+    should also be escaped with a backslash (for example, "\\">.</p>
+  </li>
+  <li><em>autofill</em>
+    <p>This is equivalent to clicking <strong>Auto Fill</strong> in the In-app Products UI. Can be
+    <code>true</code> or <code>false</code>. The syntax for specifying the <em>country</em>
+    and <em>price</em> varies depending on which <em>autofill</em> setting you use.</p>
+    <p>If <em>autofill</em> is set to <code>true</code>, you need to specify only the default
+    price in your home currency and you must use this syntax:</p>
+    <p>"true","<em>default_price_in_home_currency</em>"
+    <p>If <em>autofill</em> is set to <code>false</code>, you need to specify a <em>country</em>
+    and a <em>price</em> for each currency and you must use the following syntax:</p>
+    <p>"false", "<em>home_country</em>; <em>default_price_in_home_currency</em>; <em>country_2</em>;
+    <em>country_2_price</em>; <em>country_3</em>; <em>country_3_price</em>; ..."</p>
+  </li>
+  <li><em>country</em>
+    <p>The country for which you are specifying a price. You can only list countries that your
+    application is targeting. The country codes are two-letter uppercase
+    ISO country codes (such as "US") as defined by
+    <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-2</a>.</p>
+  </li>
+  <li><em>price</em>
+    <p>This is equivalent to the Price in the In-app Products UI. The price must be specified in
+    micro-units. To convert a currency value to micro-units, you multiply the real value by 1,000,000.
+    For example, if you want to sell an in-app item for $1.99 you specify 1990000 in the
+    <em>price</em> field.</p>
+  </li>
+</ul>
+
+<p class="table-caption" id="language-table"><strong>Table 1.</strong> Language codes you can use
+with the <em>locale</em> field.</p>
+
+<table>
+
+<tr>
+<th>Language</th>
+<th>Code</th>
+<th>Language</th>
+<th>Code</th>
+</tr>
+<tr>
+<td>Chinese</td>
+<td>zh_TW</td>
+<td>Italian</td>
+<td>it_IT</td>
+</tr>
+<tr>
+<td>Czech</td>
+<td>cs_CZ</td>
+<td>Japanese</td>
+<td>ja_JP</td>
+</tr>
+<tr>
+<td>Danish</td>
+<td>da_DK</td>
+<td>Korean</td>
+<td>ko_KR</td>
+</tr>
+<tr>
+<td>Dutch</td>
+<td>nl_NL</td>
+<td>Norwegian</td>
+<td>no_NO</td>
+</tr>
+<tr>
+<td>English</td>
+<td>en_US</td>
+<td>Polish</td>
+<td>pl_PL</td>
+</tr>
+<tr>
+<td>French</td>
+<td>fr_FR</td>
+<td>Portuguese</td>
+<td>pt_PT</td>
+</tr>
+<tr>
+<td>Finnish</td>
+<td>fi_FI</td>
+<td>Russian</td>
+<td>ru_RU</td>
+</tr>
+<tr>
+<td>German</td>
+<td>de_DE</td>
+<td>Spanish</td>
+<td>es_ES</td>
+</tr>
+<tr>
+<td>Hebrew</td>
+<td>iw_IL</td>
+<td>Swedish</td>
+<td>sv_SE</td>
+</tr>
+<tr>
+<td>Hindi</td>
+<td>hi_IN</td>
+<td>--</td>
+<td>--</td>
+</tr>
+</table>
+
+<p>To import the items that are specified in your CSV file, do the following:</p>
+
+<ol>
+  <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
+  <li>In the <strong>All Android Market listings</strong> panel, under the application name, click
+  <strong>In-app Products</strong>.</li>
+  <li>On the In-app Products List page, click <strong>Choose File</strong> and select your CSV
+file.
+    <p>The CSV file must be on your local computer or on a local disk that is connected to your
+    computer.</p>
+  </li>
+  <li>Select the <strong>Overwrite</strong> checkbox if you want to overwrite existing items in
+  your product list.
+    <p>This option overwrites values of existing items only if the value of the <em>product_id</em>
+    in the CSV file matches the In-app Product ID for an existing item in the product list.
+    Overwriting does not delete items that are on a product list but not present in the CSV
+    file.</p>
+  </li>
+  <li>On the In-app Products List page, click <strong>Import from CSV</strong>.</li>
+</ol>
+
+<p>You can also export an existing product list to a CSV file by clicking <strong>Export to CSV
+</strong> on the In-app Product List page. This is useful if you have manually added items to
+a product list and you want to start managing the product list through a CSV file.</p>
+
 <h3 id="billing-purchase-type">Choosing a Purchase Type</h3>
 
 <p>An item's purchase type controls how Android Market manages the purchase of the item. There are
@@ -194,7 +419,7 @@
 
 <p>In-app billing does not allow users to send a refund request to Android Market. Refunds for
 in-app purchases must be directed to you (the application developer). You can then process the
-refund through your Google Checkout Merchant account. When you do this, Android Market receives a
+refund through your Google Checkout merchant account. When you do this, Android Market receives a
 refund notification from Google Checkout, and Android Market sends a refund message to your
 application. For more information, see <a
 href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling
@@ -236,15 +461,15 @@
   <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
   <li>On the upper left part of the page, under your name, click <strong>Edit profile</strong>.</li>
   <li>On the Edit Profile page, scroll down to the Licensing &amp; In-app Billing panel (see figure
-  4).</li>
+  5).</li>
   <li>In Test Accounts, add the email addresses for the test accounts you want to register,
   separating each account with a comma.</li>
   <li>Click <strong>Save</strong> to save your profile changes.</li>
 </ol>
 
-<img src="{@docRoot}images/billing_public_key.png" height="510" id="figure4" />
+<img src="{@docRoot}images/billing_public_key.png" height="510" id="figure5" />
 <p class="img-caption">
-  <strong>Figure 4.</strong> The Licensing and In-app Billing panel of your account's Edit Profile
+  <strong>Figure 5.</strong> The Licensing and In-app Billing panel of your account's Edit Profile
   page lets you register test accounts.
 </p>
 
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index de20e00..f63f3c4 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -250,13 +250,15 @@
 sizes, widget layouts must adapt to different Home screen grid cell sizes.</p>
 
 <p>Below is an example layout that a music widget showing text information and two buttons can use.
-It builds upon the previous discussion of adding margins depending on OS version.</p>
+It builds upon the previous discussion of adding margins depending on OS version. Note that the
+most robust and resilient way to add margins to the widget is to wrap the widget frame and contents
+in a padded {@link android.widget.FrameLayout}.</p>
 
 <pre>
 &lt;FrameLayout
   android:layout_width="match_parent"
   android:layout_height="match_parent"
-  android:layout_margin="@dimen/widget_margin"&gt;
+  android:padding="@dimen/widget_margin"&gt;
 
   &lt;LinearLayout
     android:layout_width="match_parent"
@@ -295,16 +297,16 @@
 
 
 <p>When a user adds the widget to their home screen, on an example Android 4.0 device where each
-grid cell is 80dp &times; 100dp in size and 16dp of margins are automatically applied on all sizes,
+grid cell is 80dp &times; 100dp in size and 8dp of margins are automatically applied on all sizes,
 the widget will be stretched, like so:</p>
 
 
 <img src="{@docRoot}images/widget_design/music_example_stretched.png"
-  alt="Music widget sitting on an example 80dp x 100dp grid with 16dp of automatic margins
+  alt="Music widget sitting on an example 80dp x 100dp grid with 8dp of automatic margins
   added by the system" id="music_example_stretched">
 
 <p class="img-caption"><strong>Figure 7.</strong> Music widget sitting on an example 80dp x 100dp
-grid with 16dp of automatic margins added by the system.</p>
+grid with 8dp of automatic margins added by the system.</p>
 
 
 <h2 id="templates">Using the App Widget Templates Pack</h2>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 61337b7..2cb23c1 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -346,7 +346,7 @@
 &lt;FrameLayout
   android:layout_width="match_parent"
   android:layout_height="match_parent"
-  <strong>android:layout_margin="@dimen/widget_margin"&gt;</strong>
+  <strong>android:padding="@dimen/widget_margin"&gt;</strong>
 
   &lt;LinearLayout
     android:layout_width="match_parent"
@@ -363,7 +363,7 @@
   <li>Create two dimensions resources, one in <code>res/values/</code> to provide the pre-Android 4.0 custom margins, and one in <code>res/values-v14/</code> to provide no extra padding for Android 4.0 widgets:
 
     <p><strong>res/values/dimens.xml</strong>:<br>
-    <pre>&lt;dimen name="widget_margin"&gt;15dp&lt;/dimen&gt;</pre></p>
+    <pre>&lt;dimen name="widget_margin"&gt;8dp&lt;/dimen&gt;</pre></p>
 
     <p><strong>res/values-v14/dimens.xml</strong>:<br>
     <pre>&lt;dimen name="widget_margin"&gt;0dp&lt;/dimen&gt;</pre></p>
diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index 5abffb3..5cf1a59 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -130,9 +130,8 @@
 <p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main
 Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p>
 
-<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
-for a guide to extending a View class, and <a href="2d-graphics.html">2D Graphics: Drawables</a> for
-information on using Drawable objects like images from your resources and other primitive shapes.</p>
+<p>For information about extending the {@link android.view.View} class, read
+<a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>.</p>
 
 <p>For a sample application, see the Snake game, in the SDK samples folder:
 <code>&lt;your-sdk-directory>/samples/Snake/</code>.</p>
@@ -188,7 +187,7 @@
 
 <p>This document discusses the basics of using Drawable objects to draw graphics and how to use a
 couple subclasses of the Drawable class. For information on using Drawables to do frame-by-frame
-animation, see <a href="{@docRoot}guide/topics/animation/drawable-animation.html">Drawable
+animation, see <a href="{@docRoot}guide/topics/graphics/drawable-animation.html">Drawable
 Animation</a>.</p>
 
 <p>A {@link android.graphics.drawable.Drawable} is a general abstraction for "something that can be
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 877bded..b962f96 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -29,6 +29,15 @@
       </ol>
     </li>
     <li><a href="#saving-media">Saving Media Files</a></li>
+    <li><a href="#camera-features">Camera Features</a>
+      <ol>
+        <li><a href="#check-feature">Checking feature availability</a></li>
+        <li><a href="#using-features">Using camera features</a></li>
+        <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
+        <li><a href="#face-detection">Face detection</a></li>
+        <li><a href="#time-lapse-video">Time lapse video</a></li>
+      </ol>
+    </li>
   </ol>
   <h2>Key Classes</h2>
   <ol>
@@ -39,8 +48,7 @@
   </ol>
   <h2>See also</h2>
   <ol>
-    <li><a href="{@docRoot}reference/android/hardware/Camera.html">Camera</a></li>
-    <li><a href="{@docRoot}reference/android/media/MediaRecorder.html">MediaRecorder</a></li>
+    <li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
     <li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
   </ol>
   </div>
@@ -64,7 +72,7 @@
 
   <li><strong>Quick Picture or Customized Camera</strong> - How will your application use the
 camera? Are you just interested in snapping a quick picture or video clip, or will your application
-provide a new way to use cameras? For a getting a quick snap or clip, consider 
+provide a new way to use cameras? For a getting a quick snap or clip, consider
 <a href="#intents">Using Existing Camera Apps</a>. For developing a customized camera feature, check
 out the <a href="#custom-camera">Building a Camera App</a> section.</li>
 
@@ -85,7 +93,7 @@
 <dl>
   <dt>{@link android.hardware.Camera}</dt>
   <dd>This class is the primary API for controlling device cameras. This class is used to take
-pictures or videos when you are building a camera application.</a>.</dd>
+pictures or videos when you are building a camera application.</dd>
 
   <dt>{@link android.view.SurfaceView}</dt>
   <dd>This class is used to present a live camera preview to the user.</dd>
@@ -120,8 +128,8 @@
 <pre>
 &lt;uses-feature android:name=&quot;android.hardware.camera&quot; /&gt;
 </pre>
-  <p>For a list of camera features, see the manifest <a
-href="{@docRoot}guide/topics/manifest/uses-feature-element.html#features-reference">Features
+  <p>For a list of camera features, see the manifest
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features">Features
 Reference</a>.</p>
   <p>Adding camera features to your manifest causes Android Market to prevent your application from
 being installed to devices that do not include a camera or do not support the camera features you
@@ -148,6 +156,15 @@
 &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
 </pre>
   </li>
+  <li><strong>Location Permission</strong> - If your application tags images with GPS location
+information, you must request location permission:
+<pre>
+&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
+</pre>
+<p>For more information about getting user location, see
+<a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
+Location</a>.</p>
+  </li>
 </ul>
 
 
@@ -224,8 +241,8 @@
 your application, and you must intercept the {@link
 android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
 method to receive the result of the intent and continue your application execution. For information
-on how to receive the completed intent, see <a href="#intent-receive">Receiving Camera Intent
-Result</a>.</p>
+on how to receive the completed intent, see <a href="#intent-receive">Receiving camera intent
+result</a>.</p>
 
 
 <h3 id="intent-video">Video capture intent</h3>
@@ -360,8 +377,8 @@
 
 <p>Camera hardware is a shared resource that must be carefully managed so your application does
 not collide with other applications that may also want to use it. The following sections discusses
-how to detect camera hardware, how to request access to a camera and how to release it when your
-application is done using it.</p>
+how to detect camera hardware, how to request access to a camera, how to capture pictures or video
+and how to release the camera when your application is done using it.</p>
 
 <p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera}
 object by calling the {@link android.hardware.Camera#release() Camera.release()} when your
@@ -492,7 +509,8 @@
           // ignore: tried to stop a non-existent preview
         }
 
-        // make any resize, rotate or reformatting changes here
+        // set preview size and make any resize, rotate or
+        // reformatting changes here
 
         // start preview with new settings
         try {
@@ -506,6 +524,12 @@
 }
 </pre>
 
+<p>If you want to set a specific size for your camera preview, set this in the {@code
+surfaceChanged()} method as noted in the comments above. When setting preview size, you
+<em>must use</em> values from {@link android.hardware.Camera.Parameters#getSupportedPreviewSizes}.
+<em>Do not</em> set arbitrary values in the {@link
+android.hardware.Camera.Parameters#setPreviewSize setPreviewSize()} method.</p>
+
 
 <h3 id="preview-layout">Placing preview in a layout</h3>
 <p>A camera preview class, such as the example shown in the previous section, must be placed in the
@@ -780,6 +804,10 @@
 since users typically prefer to see a preview before starting a recording, that process is not
 discussed here.</p>
 
+<p class="note"><strong>Tip:</strong> If your application is typically used for recording video, set
+{@link android.hardware.Camera.Parameters#setRecordingHint} to {@code true} prior to starting your
+preview. This setting can help reduce the time it takes to start recording.</p>
+
 <h4 id="configuring-mediarecorder">Configuring MediaRecorder</h4>
 <p>When using the {@link android.media.MediaRecorder} class to record video, you must perform
 configuration steps in a <em>specific order</em> and then call the {@link
@@ -851,7 +879,7 @@
   <li>{@link android.media.MediaRecorder#setAudioSamplingRate(int) setAudioSamplingRate()}</li>
 </ul>
 
-<h4 id="start-stop-mediarecorder">Starting and Stopping MediaRecorder</h4>
+<h4 id="start-stop-mediarecorder">Starting and stopping MediaRecorder</h4>
 <p>When starting and stopping video recording using the {@link android.media.MediaRecorder} class,
 you must follow a specific order, as listed below.</p>
 
@@ -938,7 +966,7 @@
     private MediaRecorder mMediaRecorder;
 
     ...
-    
+
     &#64;Override
     protected void onPause() {
         super.onPause();
@@ -1052,4 +1080,425 @@
 href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</p>
 
 <p>For more information about saving files on an Android device, see <a
-href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p>
\ No newline at end of file
+href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p>
+
+
+<h2 id="camera-features">Camera Features</h2>
+<p>Android supports a wide array of camera features you can control with your camera application,
+such as picture format, flash mode, focus settings, and many more. This section lists the common
+camera features, and briefly discusses how to use them. Most camera features can be accessed and set
+using the through {@link android.hardware.Camera.Parameters} object. However, there are several
+important features that require more than simple settings in {@link
+android.hardware.Camera.Parameters}. These features are covered in the following sections:<p>
+
+<ul>
+  <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
+  <li><a href="#face-detection">Face detection</a></li>
+  <li><a href="#time-lapse-video">Time lapse video</a></li>
+</ul>
+
+<p>For general information about how to use features that are controlled through {@link
+android.hardware.Camera.Parameters}, review the <a href="#using-features">Using camera
+features</a> section. For more detailed information about how to use features controlled through the
+camera parameters object, follow the links in the feature list below to the API reference
+documentation.</p>
+
+<p class="table-caption" id="table1">
+  <strong>Table 1.</strong> Common camera features sorted by the Android API Level in which they
+were introduced.</p>
+<table>
+  <tr>
+    <th>Feature</th>  <th>API Level</th>  <th>Description</th>
+  </tr>
+  <tr>
+    <td><a href="#face-detection">Face Detection</a></td>
+    <td>14</td>
+    <td>Identify human faces within a picture and use them for focus, metering and white
+balance</td>
+  </tr>
+  <tr>
+    <td><a href="#metering-focus-areas">Metering Areas</a></td>
+    <td>14</td>
+    <td>Specify one or more areas within an image for calculating white balance</td>
+  </tr>
+  <tr>
+    <td><a href="#metering-focus-areas">Focus Areas</a></td>
+    <td>14</td>
+    <td>Set one or more areas within an image to use for focus</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock White Balance Lock}</td>
+    <td>14</td>
+    <td>Stop or start automatic white balance adjustments</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setAutoExposureLock Exposure Lock}</td>
+    <td>14</td>
+    <td>Stop or start automatic exposure adjustments</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera#takePicture Video Snapshot}</td>
+    <td>14</td>
+    <td>Take a picture while shooting video (frame grab)</td>
+  </tr>
+  <tr>
+    <td><a href="#time-lapse-video">Time Lapse Video</a></td>
+    <td>11</td>
+    <td>Record frames with set delays to record a time lapse video</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera#open(int) Multiple Cameras}</td>
+    <td>9</td>
+    <td>Support for more than one camera on a device, including front-facing and back-facing
+cameras</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#getFocusDistances Focus Distance}</td>
+    <td>9</td>
+    <td>Reports distances between the camera and objects that appear to be in focus</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setZoom Zoom}</td>
+    <td>8</td>
+    <td>Set image magnification</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setExposureCompensation Exposure
+Compensation}</td>
+    <td>8</td>
+    <td>Increase or decrease the light exposure level</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setGpsLatitude GPS Data}</td>
+    <td>5</td>
+    <td>Include or omit geographic location data with the image</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setWhiteBalance White Balance}</td>
+    <td>5</td>
+    <td>Set the white balance mode, which affects color values in the captured image</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setFocusMode Focus Mode}</td>
+    <td>5</td>
+    <td>Set how the camera focuses on a subject such as automatic, fixed, macro or infinity</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setSceneMode Scene Mode}</td>
+    <td>5</td>
+    <td>Apply a preset mode for specific types of photography situations such as night, beach, snow
+or candlelight scenes</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setJpegQuality JPEG Quality}</td>
+    <td>5</td>
+    <td>Set the compression level for a JPEG image, which increases or decreases image output file
+quality and size</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setFlashMode Flash Mode}</td>
+    <td>5</td>
+    <td>Turn flash on, off, or use automatic setting</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setColorEffect Color Effects}</td>
+    <td>5</td>
+    <td>Apply a color effect to the captured image such as black and white, sepia tone or negative.
+</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setAntibanding Anti-Banding}</td>
+    <td>5</td>
+    <td>Reduces the effect of banding in color gradients due to JPEG compression</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setPictureFormat Picture Format}</td>
+    <td>1</td>
+    <td>Specify the file format for the picture</td>
+  </tr>
+  <tr>
+    <td>{@link android.hardware.Camera.Parameters#setPictureSize Picture Size}</td>
+    <td>1</td>
+    <td>Specify the pixel dimensions of the saved picture</td>
+  </tr>
+</table>
+
+<p class="note"><strong>Note:</strong> These features are not supported on all devices due to
+hardware differences and software implementation. For information on checking the availability
+of features on the device where your application is running, see <a href="#check-feature">Checking
+feature availability</a>.</p>
+
+
+<h3 id="check-feature">Checking feature availability</h3>
+<p>The first thing to understand when setting out to use camera features on Android devices is that
+not all camera features are supported on all devices. In addition, devices that support a particular
+feature may support them to different levels or with different options. Therefore, part of your
+decision process as you develop a camera application is to decide what camera features you want to
+support and to what level. After making that decision, you should plan on including code in your
+camera application that checks to see if device hardware supports those features and fails
+gracefully if a feature is not available.</p>
+
+<p>You can check the availabilty of camera features by getting an instance of a camera’s parameters
+object, and checking the relevant methods. The following code sample shows you how to obtain a
+{@link android.hardware.Camera.Parameters} object and check if the camera supports the autofocus
+feature:</p>
+
+<pre>
+// get Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+
+List&lt;String&gt; focusModes = params.getSupportedFocusModes();
+if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
+  // Autofocus mode is supported
+}
+</pre>
+
+<p>You can use the technique shown above for most camera features. The
+{@link android.hardware.Camera.Parameters} object provides a {@code getSupported...()}, {@code
+is...Supported()} or {@code getMax...()} method to determine if (and to what extent) a feature is
+supported.</p>
+
+<p>If your application requires certain camera features in order to function properly, you can
+require them through additions to your application manifest. When you declare the use of specific
+camera features, such as flash and auto-focus, the Android Market restricts your application from
+being installed on devices which do not support these features. For a list of camera features that
+can be declared in your app manifest, see the manifest
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features"> Features
+Reference</a>.</p>
+
+<h3 id="using-features">Using camera features</h3>
+<p>Most camera features are activated and controlled using a {@link
+android.hardware.Camera.Parameters} object. You obtain this object by first getting an instance of
+the {@link android.hardware.Camera} object, calling the {@link
+android.hardware.Camera#getParameters getParameters()} method, changing the returned parameter
+object and then setting it back into the camera object, as demonstrated in the following example
+code:</p>
+
+<pre>
+// get Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+// set the focus mode
+params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
+// set Camera parameters
+mCamera.setParameters(params);
+</pre>
+
+<p>This technique works for nearly all camera features, and most parameters can be changed at any
+time after you have obtained an instance of the {@link android.hardware.Camera} object. Changes to
+parameters are typically visible to the user immediately in the application’s camera preview.
+On the software side, parameter changes may take several frames to actually take effect as the
+camera hardware processes the new instructions and then sends updated image data.</p>
+
+<p class="caution"><strong>Important:</strong> Some camera features cannot be changed at will. In
+particular, changing the size or orientation of the camera preview requires that you first stop the
+preview, change the preview size, and then restart the preview. Starting with Android 4.0 (API
+Level 14) preview orientation can be changed without restarting the preview.</p>
+
+<p>Other camera features require more code in order to implement, including:</p>
+<ul>
+  <li>Metering and focus areas</li>
+  <li>Face detection</li>
+  <li>Time lapse video</li>
+</ul>
+<p>A quick outline of how to implement these features is provided in the following sections.</p>
+
+
+<h3 id="metering-focus-areas">Metering and focus areas</h3>
+<p>In some photographic scenarios, automatic focusing and light metering may not produce the
+desired results. Starting with Android 4.0 (API Level 14), your camera application can provide
+additional controls to allow your app or users to specify areas in an image to use for determining
+focus or light level settings and pass these values to the camera hardware for use in capturing
+images or video.</p>
+
+<p>Areas for metering and focus work very similarly to other camera features, in that you control
+them through methods in the {@link android.hardware.Camera.Parameters} object. The following code
+demonstrates setting two light metering areas for an instance of
+{@link android.hardware.Camera}:</p>
+
+<pre>
+// Create an instance of Camera
+mCamera = getCameraInstance();
+
+// set Camera parameters
+Camera.Parameters params = mCamera.getParameters();
+
+if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
+    List&lt;Camera.Area&gt; meteringAreas = new ArrayList&lt;Camera.Area&gt;();
+
+    Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
+    meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
+    Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
+    meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
+    params.setMeteringAreas(meteringAreas);
+}
+
+mCamera.setParameters(params);
+</pre>
+
+<p>The {@link android.hardware.Camera.Area} object contains two data parameters: A {@link
+android.graphics.Rect} object for specifying an area within the camera’s field of view and a weight
+value, which tells the camera what level of importance this area should be given in light metering
+or focus calculations.</p>
+
+<p>The {@link android.graphics.Rect} field in a {@link android.hardware.Camera.Area} object
+describes a rectangular shape mapped on a 2000 x 2000 unit grid. The coordinates -1000, -1000
+represent the top, left corner of the camera image, and coordinates 1000, 1000 represent the
+bottom, right corner of the camera image, as shown in the illustration below.</p>
+
+<img src='images/camera-area-coordinates.png' />
+<p class="img-caption">
+  <strong>Figure 1.</strong> The red lines illustrate the coordinate system for specifying a
+{@link android.hardware.Camera.Area} within a camera preview. The blue box shows the location and
+shape of an camera area with the {@link android.graphics.Rect} values 333,333,667,667.
+</p>
+
+<p>The bounds of this coordinate system always correspond to the outer edge of the image visible in
+the camera preview and do not shrink or expand with the zoom level. Similarly, rotation of the image
+preview using {@link android.hardware.Camera#setDisplayOrientation Camera.setDisplayOrientation()}
+does not remap the coordinate system.</p>
+
+
+<h3 id="face-detection">Face detection</h3>
+<p>For pictures that include people, faces are usually the most important part of the picture, and
+should be used for determining both focus and white balance when capturing an image. The Android 4.0
+(API Level 14) framework provides APIs for identifying faces and calculating picture settings using
+face recognition technology.</p>
+
+<p class="note"><strong>Note:</strong> While the face detection feature is running,
+{@link android.hardware.Camera.Parameters#setWhiteBalance},
+{@link android.hardware.Camera.Parameters#setFocusAreas} and
+{@link android.hardware.Camera.Parameters#setMeteringAreas} have no effect.</p>
+
+<p>Using the face detection feature in your camera application requires a few general steps:</p>
+<ul>
+  <li>Check that face detection is supported on the device</li>
+  <li>Create a face detection listener</li>
+  <li>Add the face detection listener to your camera object</li>
+  <li>Start face detection after preview (and after <em>every</em> preview restart)</li>
+</ul>
+
+<p>The face detection feature is not supported on all devices. You can check that this feature is
+supported by calling {@link android.hardware.Camera.Parameters#getMaxNumDetectedFaces}. An
+example of this check is shown in the {@code startFaceDetection()} sample method below.</p>
+
+<p>In order to be notified and respond to the detection of a face, your camera application must set
+a listener for face detection events. In order to do this, you must create a listener class that
+implements the {@link android.hardware.Camera.FaceDetectionListener} interface as shown in the
+example code below.</p>
+
+<pre>
+class MyFaceDetectionListener implements Camera.FaceDetectionListener {
+
+    &#064;Override
+    public void onFaceDetection(Face[] faces, Camera camera) {
+        if (faces.length > 0){
+            Log.d("FaceDetection", "face detected: "+ faces.length +
+                    " Face 1 Location X: " + faces[0].rect.centerX() +
+                    "Y: " + faces[0].rect.centerY() );
+        }
+    }
+}
+</pre>
+
+<p>After creating this class, you then set it into your application’s
+{@link android.hardware.Camera} object, as shown in the example code below:</p>
+
+<pre>
+mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
+</pre>
+
+<p>Your application must start the face detection function each time you start (or restart) the
+camera preview. Create a method for starting face detection so you can call it as needed, as shown
+in the example code below.</p>
+
+<pre>
+public void startFaceDetection(){
+    // Try starting Face Detection
+    Camera.Parameters params = mCamera.getParameters();
+
+    // start face detection only *after* preview has started
+    if (params.getMaxNumDetectedFaces() > 0){
+        // camera supports face detection, so can start it:
+        mCamera.startFaceDetection();
+    }
+}
+</pre>
+
+<p>You must start face detection <em>each time</em> you start (or restart) the camera preview. If
+you use the preview class shown in <a href="#camera-preview">Creating a preview class</a>, add your
+{@link android.hardware.Camera#startFaceDetection startFaceDetection()} method to both the
+{@link android.view.SurfaceHolder.Callback#surfaceCreated surfaceCreated()} and {@link
+android.view.SurfaceHolder.Callback#surfaceChanged surfaceChanged()} methods in your preview class,
+as shown in the sample code below.</p>
+
+<pre>
+public void surfaceCreated(SurfaceHolder holder) {
+    try {
+        mCamera.setPreviewDisplay(holder);
+        mCamera.startPreview();
+
+        startFaceDetection(); // start face detection feature
+
+    } catch (IOException e) {
+        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
+    }
+}
+
+public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+
+    if (mHolder.getSurface() == null){
+        // preview surface does not exist
+        Log.d(TAG, "mHolder.getSurface() == null");
+        return;
+    }
+
+    try {
+        mCamera.stopPreview();
+
+    } catch (Exception e){
+        // ignore: tried to stop a non-existent preview
+        Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
+    }
+
+    try {
+        mCamera.setPreviewDisplay(mHolder);
+        mCamera.startPreview();
+
+        startFaceDetection(); // re-start face detection feature
+
+    } catch (Exception e){
+        // ignore: tried to stop a non-existent preview
+        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+    }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Remember to call this method <em>after</em> calling
+{@link android.hardware.Camera#startPreview startPreview()}. Do not attempt to start face detection
+in the {@link android.app.Activity#onCreate onCreate()} method of your camera app’s main activity,
+as the preview is not available by this point in your application's the execution.</p>
+
+
+<h3 id="time-lapse-video">Time lapse video</h3>
+<p>Time lapse video allows users to create video clips that combine pictures taken a few seconds or
+minutes apart. This feature uses {@link android.media.MediaRecorder} to record the images for a time
+lapse sequence. </p>
+
+<p>To record a time lapse video with {@link android.media.MediaRecorder}, you must configure the
+recorder object as if you are recording a normal video, setting the captured frames per second to a
+low number and using one of the time lapse quality settings, as shown in the code example below.</p>
+
+<pre>
+// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
+mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
+...
+// Step 5.5: Set the video capture rate to a low number
+mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
+</pre>
+
+<p>These settings must be done as part of a larger configuration procedure for {@link
+android.media.MediaRecorder}. For  a full configuration code example, see <a
+href="#configuring-mediarecorder">Configuring MediaRecorder</a>. Once the configuration is complete,
+you start the video recording as if you were recording a normal video clip. For more information
+about configuring and running {@link android.media.MediaRecorder}, see <a
+href="#capture-video">Capturing videos</a>.</p>
diff --git a/docs/html/guide/topics/media/images/camera-area-coordinates.png b/docs/html/guide/topics/media/images/camera-area-coordinates.png
new file mode 100644
index 0000000..9876453
--- /dev/null
+++ b/docs/html/guide/topics/media/images/camera-area-coordinates.png
Binary files differ
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index 7c1754f..0e0412a 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -6,7 +6,7 @@
 
 <h2>Topics</h2>
 <ol>
-<li><a href="{@docRoot}guide/topics/media/mediaplayer.html">MediaPlayer</a></li>
+<li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
 <li><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></li>
 <li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li>
 <li><a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a></li>
@@ -46,7 +46,8 @@
 and playback.</p>
 
 <dl>
-  <dt><strong><a href="{@docRoot}guide/topics/media/mediaplayer.html">MediaPlayer</a></strong></dt>
+  <dt><strong><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></strong>
+  </dt>
   <dd>How to play audio and video in your application.</dd>
 
   <dt><strong><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></strong></dt>
diff --git a/docs/html/guide/topics/providers/calendar-provider.jd b/docs/html/guide/topics/providers/calendar-provider.jd
index 3ab5125..d30dda4 100644
--- a/docs/html/guide/topics/providers/calendar-provider.jd
+++ b/docs/html/guide/topics/providers/calendar-provider.jd
@@ -280,11 +280,9 @@
 {@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
 in the selection. That is because a given account is
 only considered unique given both its <code>ACCOUNT_NAME</code> and its
-<code>ACCOUNT_TYPE</code>. The <code>ACCOUNT_TYPE</code> refers to the way that
-the account is being  synced. It is often but not always the domain. For
-example, an account could be  synced through a corporate pop3 sync adapter, in which
-case the <code>ACCOUNT_TYPE</code> would not be a domain. There is also a
-special type of account called {@link
+<code>ACCOUNT_TYPE</code>. The <code>ACCOUNT_TYPE</code> is the string corresponding to the
+account authenticator that was used when the account was registered with the
+{@link android.accounts.AccountManager}. There is also a special type of account called {@link
 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} for calendars not
 associated with a device account. {@link
 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} accounts do not get
diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd
index eb77310..148705c 100644
--- a/docs/html/guide/topics/renderscript/index.jd
+++ b/docs/html/guide/topics/renderscript/index.jd
@@ -151,10 +151,9 @@
     defining two-, three-, or four-vectors.</li>
   </ul>
 
-  <p>The <a href="{@docRoot}guide/topics/renderscript/rs-api/files.html">RenderScript header files</a>
-  and LLVM front-end libraries are located in the <code>include</code> and
-  <code>clang-include</code> directories in the
-  <code>&lt;sdk_root&gt;/platforms/android-11/renderscript</code> directory of the Android SDK. The
+  <p>The RenderScript header files and LLVM front-end libraries are located in the <code>include/</code> and
+  <code>clang-include/</code> directories in the
+  <code>&lt;sdk_root&gt;/platforms/android-11/renderscript/</code> directory of the Android SDK. The
   headers are automatically included for you, except for the RenderScript graphics specific header file, which
   you can include as follows:</p>
   <pre>
diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd
index 2948244..7b5b3dc 100644
--- a/docs/html/guide/topics/ui/menus.jd
+++ b/docs/html/guide/topics/ui/menus.jd
@@ -198,10 +198,11 @@
 }
 </pre>
 
-<div class="figure" style="width:500px">
-<img src="{@docRoot}images/ui/actionbar.png" height="34" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> Screenshot of the Action Bar in the Email
-application, with two action items from the Options Menu, plus the overflow menu.</p>
+<div class="figure" style="width:450px">
+<img src="{@docRoot}images/ui/actionbar.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> Action bar from the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app, including
+navigation tabs and a camera action item (plus the overflow menu button).</p>
 </div>
 
 <p>You can also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int)
diff --git a/docs/html/images/billing_list_form_2.png b/docs/html/images/billing_list_form_2.png
new file mode 100755
index 0000000..d321a20
--- /dev/null
+++ b/docs/html/images/billing_list_form_2.png
Binary files differ
diff --git a/docs/html/images/billing_product_list.png b/docs/html/images/billing_product_list.png
index 49a7e79..a89f21b 100755
--- a/docs/html/images/billing_product_list.png
+++ b/docs/html/images/billing_product_list.png
Binary files differ
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index 07a0e43..4d0abec 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -57,7 +57,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A9.8,90.2" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A10.1,89.9" />
 
 <table>
 <tr>
@@ -66,14 +66,14 @@
 </tr>
 <tr>
 <td>1.1</th>
-<td>9.8%</td>
+<td>10.1%</td>
 </tr>
 <tr>
 <td>2.0</th>
-<td>90.2%</td>
+<td>89.9%</td>
 </tr>
 </table>
 
-<p><em>Data collected during a 7-day period ending on November 3, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on December 1, 2011</em></p>
 </div>
 
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 8041096..72370bb 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -52,7 +52,7 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="470"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:0.9,1.4,10.7,40.7,0.5,43.9,0.1,0.9,0.9&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:0.8,1.3,9.6,35.3,0.5,50.1,0.1,1.1,1.2&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
 
 <table>
 <tr>
@@ -61,21 +61,21 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>0.9%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td>    <td>4</td><td>1.4%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>10.7%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>40.7%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>0.8%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td>    <td>4</td><td>1.3%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>9.6%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>35.3%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3 -<br/>
                              Android 2.3.2</a></td><td rowspan="2">Gingerbread</td>    <td>9</td><td>0.5%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 -<br/>
-      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>43.9%</td></tr>
+      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>50.1%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0</a></td>
                                                    <td rowspan="3">Honeycomb</td>      <td>11</td><td>0.1%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>0.9%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>0.9%</td></tr> 
+<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>1.1%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>1.2%</td></tr> 
 </table>
 
-<p><em>Data collected during a 14-day period ending on November 3, 2011</em></p>
+<p><em>Data collected during a 14-day period ending on December 1, 2011</em></p>
 <!--
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
 -->
@@ -104,9 +104,9 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.6,99.5,99.4,99.3,99.2,99.0,98.8,98.7,98.5,98.5,98.2,98.1,98.0|97.3,97.5,97.5,97.5,97.7,97.6,97.5,97.5,97.5,97.5,97.1,97.1,97.1|94.3,94.8,95.0,95.2,95.5,95.5,95.5,95.6,95.7,95.8,95.6,95.9,95.7|69.8,71.5,73.9,75.4,77.6,79.0,80.2,81.1,82.4,83.3,83.8,84.9,85.0|4.0,6.1,9.5,13.6,17.8,20.6,24.3,27.5,31.2,34.7,38.3,41.3,44.0|3.0,5.1,8.4,12.6,16.8,20.0,23.7,26.9,30.6,34.1,37.8,40.8,43.5&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid 2.3.3,131d02,5,3,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A|06/01|06/15|07/01|07/15|08/01|08/15|09/01|09/15|10/01|10/15|11/01|11/15|12/01|1%3A|2011||||||||||||2011|2%3A|0%25|25%25|50%25|75%25|100%25|3%3A|0%25|25%25|50%25|75%25|100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.4,99.3,99.2,99.0,98.8,98.7,98.5,98.5,98.2,98.1,98.0,99.9,99.9|97.5,97.5,97.7,97.6,97.5,97.5,97.5,97.5,97.1,97.1,97.0,99.1,99.1|95.0,95.2,95.5,95.5,95.5,95.6,95.7,95.8,95.6,95.9,95.7,97.7,97.8|73.9,75.4,77.6,79.0,80.2,81.1,82.4,83.3,83.8,84.9,85.1,87.5,88.2|9.5,13.6,17.8,20.6,24.3,27.5,31.2,34.7,38.3,41.3,44.0,48.9,52.9|8.4,12.6,16.8,20.0,23.7,26.9,30.6,34.1,37.8,40.8,43.5,48.4,52.4|0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,2.3|0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.2&chm=b,c3df9b,0,1,0|b,b8dc82,1,2,0|tAndroid%202.1,608920,2,0,15,,t::-5|b,addb67,2,3,0|tAndroid%202.2,517617,3,0,15,,t::-5|b,a3db4b,3,4,0|b,98dc2e,4,5,0|tAndroid%202.3.3,334d0a,5,1,15,,t::-5|b,8cd41b,5,6,0|b,7ec113,6,7,0|B,6fad0c,7,8,0&chg=7,25&chdl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.1|Android%203.2&chco=add274,a2d15a,97d13e,8bcb28,7dba1e,6ea715,5f920e,507d08" />
 
-<p><em>Last historical dataset collected during a 14-day period ending on November 3, 2011</em></p>
+<p><em>Last historical dataset collected during a 14-day period ending on December 1, 2011</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd
index ec3034d..79d59d9 100644
--- a/docs/html/resources/dashboard/screens.jd
+++ b/docs/html/resources/dashboard/screens.jd
@@ -60,7 +60,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A2.9,0.1,3.1,70.8,1.0,17.7,3.0,1.3" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A3.1,0.1,3.1,71.0,1.0,17.5,2.9,1.3" />
 
 <table>
 <tr>
@@ -73,13 +73,13 @@
 <tr><th scope="row">small</th> 
 <td>1.3%</td>     <!-- small/ldpi -->
 <td></td>     <!-- small/mdpi -->
-<td>3.0%</td> <!-- small/hdpi -->
+<td>2.9%</td> <!-- small/hdpi -->
 <td></td>     <!-- small/xhdpi -->
 </tr> 
 <tr><th scope="row">normal</th> 
 <td>1.0%</td>  <!-- normal/ldpi -->
-<td>17.7%</td> <!-- normal/mdpi -->
-<td>70.8%</td> <!-- normal/hdpi -->
+<td>17.5%</td> <!-- normal/mdpi -->
+<td>71%</td> <!-- normal/hdpi -->
 <td></td>      <!-- normal/xhdpi -->
 </tr> 
 <tr><th scope="row">large</th> 
@@ -90,12 +90,12 @@
 </tr> 
 <tr><th scope="row">xlarge</th> 
 <td></td>     <!-- xlarge/ldpi -->
-<td>2.9%</td> <!-- xlarge/mdpi -->
+<td>3.1%</td> <!-- xlarge/mdpi -->
 <td></td>     <!-- xlarge/hdpi -->
 <td></td>     <!-- xlarge/xhdpi -->
 </tr> 
 </table>
 
-<p><em>Data collected during a 7-day period ending on November 3, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on December 1, 2011</em></p>
 </div>
 
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index a35e684..18f1547 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -718,6 +718,16 @@
     }
   },
   {
+    tags: ['sample', 'communication', 'new'],
+    path: 'samples/ToyVpn/index.html',
+    title: {
+      en: 'Toy VPN Client'
+    },
+    description: {
+      en: 'A sample application that illustrates the creation of a custom VPN client.'
+    }
+  },
+  {
     tags: ['sample', 'newfeature'],
     path: 'samples/USB/index.html',
     title: {
diff --git a/docs/html/resources/samples/images/vpn-confirmation.png b/docs/html/resources/samples/images/vpn-confirmation.png
new file mode 100755
index 0000000..ae2e583
--- /dev/null
+++ b/docs/html/resources/samples/images/vpn-confirmation.png
Binary files differ
diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd
index e886bdf..7161b03 100644
--- a/docs/html/sdk/android-4.0.jd
+++ b/docs/html/sdk/android-4.0.jd
@@ -65,26 +65,42 @@
 <p>To determine what revision of the Android {@sdkPlatformVersion} platform you
 have installed, refer to the "Installed Packages" listing in the Android SDK Manager.</p>
 
+<p class="caution"><strong>Important:</strong> To download the new Android
+4.0 system components from the Android SDK Manager, you must first update the
+SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not,
+the Android 4.0 system components will not be available for download.</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 2</a> <em>(December 2011)</em>
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em;">
+    <p>Maintenance update. The system version is 4.0.2.</p>
+    <dl>
+      <dt>Dependencies:</dt>
+      <dd>SDK Tools r14 or higher is required.</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>(October 2011)</em>
   </a></p>
 
   <div class="toggle-content-toggleme" style="padding-left:2em;">
-
-<dl>
-<dt>Initial release. SDK Tools r14 or higher is required.
-  <p class="caution"><strong>Important:</strong> To download the new Android
-  4.0 system components from the Android SDK Manager, you must first update the
-  SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not,
-  the Android 4.0 system components will not be available for download.</p>
-</dt>
-</dl>
-
+    <p>Initial release. The system version is 4.0.1.</p>
+    <dl>
+      <dt>Dependencies:</dt>
+      <dd>SDK Tools r14 or higher is required.</dd>
+    </dl>
   </div>
 </div>
 
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 50b20ce..2445bff 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,8 +1,8 @@
 page.title=ADT Plugin for Eclipse
-adt.zip.version=15.0.1
-adt.zip.download=ADT-15.0.1.zip
-adt.zip.bytes=6752327
-adt.zip.checksum=2c12a71d7124aa512b8ee016e19c0e69
+adt.zip.version=16.0.0
+adt.zip.download=ADT-16.0.0.zip
+adt.zip.bytes=6999205
+adt.zip.checksum=b7e512572580291279469845386b31b6
 
 @jd:body
 
@@ -109,18 +109,49 @@
 </style>
 
 
-
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
 width="9px" />
+ADT 16.0.0</a> <em>(December 2011)</em>
+  <div class="toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Eclipse Helios (Version 3.6) or higher is required for ADT
+16.0.0.</li>
+      <li>ADT 16.0.0 is designed for use with <a
+href="{@docRoot}sdk/tools-notes.html">SDK Tools r16</a>. If you haven't already installed SDK Tools
+r16 into your SDK, use the Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General improvements:</dt>
+  <dd>
+    <ul>
+      <li>Added Lint tools to detect common errors in Android projects. (<a
+href="http://tools.android.com/recent/lint">more info</a>)</li>
+    </ul>
+  </dd>
+</dl>
+
+</div>
+</div>
+
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+width="9px" />
 ADT 15.0.1</a> <em>(November 2011)</em>
   <div class="toggleme">
 <dl>
   <dt>Dependencies:</dt>
   
   <dd>ADT 15.0.1 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r15</a>.
-  If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK and AVD Manager to
+  If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK Manager to
   do so.</dd>
   
   <dt>Bug fixes:</dt>
@@ -154,7 +185,7 @@
 <dt>Dependencies:</dt>
 
 <dd>ADT 15.0.0 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r15</a>.
-If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK and AVD Manager to
+If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK Manager to
 do so.</dd>
 
 <dt>Bug fixes:</dt>
@@ -185,10 +216,10 @@
 <dt>Dependencies:</dt>
 
 <dd>ADT 14.0.0 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r14</a>.
-If you haven't already installed SDK Tools r14 into your SDK, use the Android SDK and AVD Manager to
+If you haven't already installed SDK Tools r14 into your SDK, use the Android SDK Manager to
 do so.</dd>
 
-<dt>Build system</dt>
+<dt>Build system:</dt>
 <dd>
   <ul>
     <li>Changed <code>default.properties</code> to <code>project.properties</code> and
@@ -211,7 +242,7 @@
 site</a>.</p>
 </dd>
 
-<dt>General improvements</dt>
+<dt>General improvements:</dt>
 <dd>
   <ul>
 
@@ -236,7 +267,7 @@
 </ul>
 </dd>
 
-<dt>XML and Java editors</dt>
+<dt>XML and Java editors:</dt>
 <dd>
   <ul>
     <li>Added a new XML formatter that formats all XML files according to the
@@ -255,7 +286,7 @@
   </ul>
 </dd>
 
-<dt>Layout editor</dt>
+<dt>Layout editor:</dt>
 <dd>
   <ul>
     <li>Added tooltip feedback for dragging and resizing operations. For
@@ -281,7 +312,7 @@
   </ul>
 </dd>
 
-<dt>Bug fixes</dt>
+<dt>Bug fixes:</dt>
 <dd>Fixed many bugs and added <a
 href="http://tools.android.com/recent/miscellaneousrecentfixes">minor improvements</a>, in
 particular some <a href="http://tools.android.com/recent/linuxfixes">critical bug fixes on
@@ -324,7 +355,7 @@
 </ul>
 </dd>
 
-<dt>Build system</dt>
+<dt>Build system:</dt>
 <dd>
 <ul>
   <li id="build-option">A new option lets you disable the packaging step in the automatic
@@ -336,7 +367,7 @@
 </ul>
 </dd>
 
-<dt>Bug fixes</dt>
+<dt>Bug fixes:</dt>
 <dd>Many bug fixes are part of this release
 (<a href="http://tools.android.com/recent/adt12bugfixroundup">more info</a>).</dd>
 
@@ -928,7 +959,7 @@
 see <a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</p>
 </dd>
 
-<dt>General Notes:</dt>
+<dt>General notes:</dt>
 <dd>
 <ul>
 <li>AVD Launch dialog now shows scale value.</li>
@@ -974,7 +1005,7 @@
 </ul>
 </dd>
 
-<dt>DDMS Integration:</dt>
+<dt>DDMS integration:</dt>
 <dd>
 <ul>
 <li>Includes the improvements from the standlone DDMS, revision 3.</li>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 193066b..65a1f46 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,21 +1,21 @@
 page.title=Android SDK
 sdk.redirect=0
 
-sdk.win_installer=installer_r15-windows.exe
-sdk.win_installer_bytes=33902520
-sdk.win_installer_checksum=ee8481cb86a6646a4d963d5142902c5c
+sdk.win_installer=installer_r16-windows.exe
+sdk.win_installer_bytes=29561554
+sdk.win_installer_checksum=3521dda4904886b05980590f83cf3469
 
-sdk.win_download=android-sdk_r15-windows.zip
-sdk.win_bytes=33895447
-sdk.win_checksum=cc2aadf7120d12b574981461736a96e9
+sdk.win_download=android-sdk_r16-windows.zip
+sdk.win_bytes=29562413
+sdk.win_checksum=6b926d0c0a871f1a946e65259984701a
 
-sdk.mac_download=android-sdk_r15-macosx.zip
-sdk.mac_bytes=30469921
-sdk.mac_checksum=03d2cdd3565771e8c7a438f1c40cc8a5
+sdk.mac_download=android-sdk_r16-macosx.zip
+sdk.mac_bytes=26158334
+sdk.mac_checksum=d1dc2b6f13eed5e3ce5cf26c4e4c47aa
 
-sdk.linux_download=android-sdk_r15-linux.tgz
-sdk.linux_bytes=26124434
-sdk.linux_checksum=f529681fd1eda11c6e1e1d44b42c1432
+sdk.linux_download=android-sdk_r16-linux.tgz
+sdk.linux_bytes=22048174
+sdk.linux_checksum=3ba457f731d51da3741c29c8830a4583
 
 @jd:body
 
diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd
index f12d0aa..c970f6c 100644
--- a/docs/html/sdk/requirements.jd
+++ b/docs/html/sdk/requirements.jd
@@ -24,8 +24,8 @@
 
 <h4 style="margin-top:.25em"><em>Eclipse IDE</em></h4>
     <ul>
-      <li>Eclipse 3.5 (Galileo) or greater 
-<p class="note"><strong>Note:</strong> Eclipse 3.4 (Ganymede) is no longer
+      <li>Eclipse 3.6 (Helios) or greater
+<p class="note"><strong>Note:</strong> Eclipse 3.5 (Galileo) is no longer
 supported with the latest version of ADT.</p></li>
       <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included
 in most Eclipse IDE packages) </li>
@@ -37,7 +37,7 @@
 packages: </p>
          <ul>
            <li>Eclipse IDE for Java Developers</li>
-           <li>Eclipse Classic (versions 3.5.1 and higher)</li>
+           <li>Eclipse Classic</li>
            <li>Eclipse IDE for Java EE Developers</li>
          </ul>
       </li>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 0ae2c6d..791e7aa 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -150,7 +150,7 @@
       </li>
     </ul>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r15</a> <span
+      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r16</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">Support Package, r4</a>
@@ -169,7 +169,7 @@
       <span style="display:none" class="zh-TW"></span>
       </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 15.0.1
+      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 16.0.0
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
       <span style="display:none" class="fr"></span>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index cd03d9f..9a63467 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -9,7 +9,7 @@
 latest revision of the SDK Tools in the <code>&lt;sdk&gt;/tools</code> directory.</p>
 
 <p>If you are already using the SDK and you want to update to the latest version
-of the SDK Tools, use the <em>Android SDK and AVD Manager</em> to get the
+of the SDK Tools, use the <em>Android SDK Manager</em> to get the
 update, rather than downloading a new SDK starter package. For more information
 about how to update, see <a
 href="{@docRoot}sdk/adding-components.html#UpdatingComponents">Updating SDK
@@ -20,8 +20,7 @@
 
 <p>The sections below provide notes about successive releases of
 the SDK Tools, as denoted by revision number. To determine what revision of the SDK
-Tools you are using, refer to the "Installed Packages" listing in the Android SDK
-and AVD Manager. </p>
+Tools you are using, refer to the "Installed Packages" listing in the Android SDK Manager. </p>
 
 <p>For a summary of all known issues in SDK Tools, see <a
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
@@ -69,7 +68,57 @@
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
-    width="9px" />SDK Tools, Revision 15</a> <em>(October 2011)</em>
+    width="9px" />
+    SDK Tools, Revision 16</a> <em>(December 2011)</em>
+
+  <div class="toggleme">
+    <p class="caution"><strong>Important:</strong> To download the new Android
+    4.0 system components from the Android SDK Manager, you must first update the
+    SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not,
+    the Android 4.0 system components will not be available for download.</p>
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+  <ul>
+    <li>Android SDK Platform-tools revision 9 or later.</li>
+    <li>If you are developing in Eclipse with ADT, note that the SDK Tools r16 is designed for use
+    with ADT 16.0.0 and later. If you haven't already, we highly recommend updating your
+    <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin</a> to 16.0.0.</li>
+    <li>If you are developing outside Eclipse, you must have <a href="http://ant.apache.org/">Apache
+    Ant</a> 1.8 or later.</li>
+</ul>
+</dd>
+<dt>General notes:</dt>
+<dd>
+  <ul>
+    <li>Added Lint tools to detect common errors in Android projects. (<a
+href="http://tools.android.com/recent/lint">more info</a>)</li>
+    <li>Added sensor emulation support, which allows the emulator to read sensor data from a
+physical Android device.</li>
+    <li>Added support for using a webcam to emulate a camera on Mac OS X.</li>
+  </ul>
+</dd>
+<dt>Bug fixes:</dt>
+<dd>
+  <ul>
+    <li>Snapshots now work for Android 4.0 system images.</li>
+    <li>Fixed several small issues for the build file.
+    (<a href="http://code.google.com/p/android/issues/detail?id=21023">Issue 21023</a>,
+    <a href="http://code.google.com/p/android/issues/detail?id=21267">Issue 21267</a>,
+    <a href="http://code.google.com/p/android/issues/detail?id=21465">Issue 21465</a>,
+    <a href="http://code.google.com/p/android/issues/detail?id=21525">Issue 21525</a>).</li>
+  </ul>
+</dd>
+</dl>
+</div>
+</div>
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+    width="9px" />
+    SDK Tools, Revision 15</a> <em>(October 2011)</em>
 
   <div class="toggleme">
     <p class="caution"><strong>Important:</strong> To download the new Android
@@ -116,7 +165,8 @@
 <div class="toggleable closed">
   <a href="#" onclick="return toggleDiv(this)">
     <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
-    width="9px" />SDK Tools, Revision 14</a> <em>(October 2011)</em>
+    width="9px" />
+    SDK Tools, Revision 14</a> <em>(October 2011)</em>
 
   <div class="toggleme">
     <p class="note"><strong>Important:</strong> To download the new Android
@@ -137,10 +187,11 @@
 <dt>General notes:</dt>
 <dd>
   <ul>
-    <li>Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras when one webcam is present,
-    and to emulate both rear-facing and front-facing cameras when two webcams are present. Webcam suport is for Windows and Linux only.
+    <li>Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras when
+    one webcam is present, and to emulate both rear-facing and front-facing cameras when two
+    webcams are present. Webcam support is for Windows and Linux only.
     Mac support will come in a later release.</li>
-     <li>Changed <code>default.properties</code> to <code>project.properties</code> and
+    <li>Changed <code>default.properties</code> to <code>project.properties</code> and
     <code>build.properties</code> to <code>ant.properties</code>. Any existing
     projects that you build with Ant must be updated with the <code>android update project</code>
     command.</li>
@@ -428,7 +479,7 @@
 for more information.</li>
 <li>Fixes location control in DDMS to work in any locale not using '.' as a
 decimal point.</li>
-</li>
+</ul>
 </ul>
 </dd>
 </dl>
diff --git a/docs/html/shareables/adl/2011Q3_Introduction_to_Honeycomb_APIs.pdf b/docs/html/shareables/adl/2011Q3_Introduction_to_Honeycomb_APIs.pdf
old mode 100644
new mode 100755
index da954d8..e56d2377
--- a/docs/html/shareables/adl/2011Q3_Introduction_to_Honeycomb_APIs.pdf
+++ b/docs/html/shareables/adl/2011Q3_Introduction_to_Honeycomb_APIs.pdf
Binary files differ
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 27d863d..a8c7672 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -60,10 +60,16 @@
         virtual void onFrameAvailable() = 0;
     };
 
-    // tex indicates the name OpenGL texture to which images are to be streamed.
-    // This texture name cannot be changed once the SurfaceTexture is created.
+    // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
+    // name of the OpenGL ES texture to which images are to be streamed. This
+    // texture name cannot be changed once the SurfaceTexture is created.
+    // allowSynchronousMode specifies whether or not synchronous mode can be
+    // enabled. texTarget specifies the OpenGL ES texture target to which the
+    // texture will be bound in updateTexImage. useFenceSync specifies whether
+    // fences should be used to synchronize access to buffers if that behavior
+    // is enabled at compile-time.
     SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
-            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES);
+            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true);
 
     virtual ~SurfaceTexture();
 
@@ -202,6 +208,10 @@
     // getCurrentScalingMode returns the scaling mode of the current buffer
     uint32_t getCurrentScalingMode() const;
 
+    // isSynchronousMode returns whether the SurfaceTexture is currently in
+    // synchronous mode.
+    bool isSynchronousMode() 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
@@ -272,7 +282,8 @@
               mTransform(0),
               mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
               mTimestamp(0),
-              mFrameNumber(0) {
+              mFrameNumber(0),
+              mFence(EGL_NO_SYNC_KHR) {
             mCrop.makeInvalid();
         }
 
@@ -345,6 +356,11 @@
         // mFrameNumber is the number of the queued frame for this slot.
         uint64_t mFrameNumber;
 
+        // mFence is the EGL sync object that must signal before the buffer
+        // associated with this buffer slot may be dequeued. It is initialized
+        // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
+        // on a compile-time option) set to a new sync object in updateTexImage.
+        EGLSyncKHR mFence;
     };
 
     // mSlots is the array of buffer slots that must be mirrored on the client
@@ -468,6 +484,12 @@
     // It is set by the setName method.
     String8 mName;
 
+    // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
+    // extension should be used to prevent buffers from being dequeued before
+    // it's safe for them to be written. It gets set at construction time and
+    // never changes.
+    const bool mUseFenceSync;
+
     // 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 57f9e15..971a1b8 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -40,6 +40,7 @@
 
 protected:
     SurfaceTextureClient();
+    virtual ~SurfaceTextureClient();
     void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture);
 
 private:
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index cc63356..19646b0 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -52,15 +52,20 @@
     static const char *const kKeyResumeAtPTS;
 
     // When signalling a discontinuity you can optionally
-    // signal that this is a "hard" discontinuity, i.e. the format
-    // or configuration of subsequent stream data differs from that
-    // currently active. To do so, include a non-zero int32_t value
-    // under the key "kKeyFormatChange" when issuing the DISCONTINUITY
+    // specify the type(s) of discontinuity, i.e. if the
+    // audio format has changed, the video format has changed,
+    // time has jumped or any combination thereof.
+    // To do so, include a non-zero int32_t value
+    // under the key "kKeyDiscontinuityMask" when issuing the DISCONTINUITY
     // command.
-    // The new logical stream must start with proper codec initialization
+    // If there is a change in audio/video format, The new logical stream
+    // must start with proper codec initialization
     // information for playback to continue, i.e. SPS and PPS in the case
     // of AVC video etc.
-    static const char *const kKeyFormatChange;
+    // If this key is not present, only a time discontinuity is assumed.
+    // The value should be a bitmask of values from
+    // ATSParser::DiscontinuityType.
+    static const char *const kKeyDiscontinuityMask;
 
     virtual void issueCommand(
             Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 5822877..3963d9c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -166,6 +166,8 @@
 
     bool allYourBuffersAreBelongToUs();
 
+    size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+
     void deferMessage(const sp<AMessage> &msg);
     void processDeferredMessages();
 
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 8c1c593..446720b 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -153,6 +153,9 @@
     bool mStarted;
     int32_t mNumFramesEncoded;
 
+    // Time between capture of two frames.
+    int64_t mTimeBetweenFrameCaptureUs;
+
     CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
                  int32_t cameraId,
                  Size videoSize, int32_t frameRate,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e264c7..b060691 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -57,10 +57,6 @@
     int32_t mVideoWidth;
     int32_t mVideoHeight;
 
-    // Time between capture of two frames during time lapse recording
-    // Negative value indicates that timelapse is disabled.
-    int64_t mTimeBetweenTimeLapseFrameCaptureUs;
-
     // Time between two frames in final video (1/frameRate)
     int64_t mTimeBetweenTimeLapseVideoFramesUs;
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index c21d19d..84f8282 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -336,6 +336,10 @@
 
     int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
 
+    status_t parseAVCCodecSpecificData(
+            const void *data, size_t size,
+            unsigned *profile, unsigned *level);
+
     OMXCodec(const OMXCodec &);
     OMXCodec &operator=(const OMXCodec &);
 };
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index b9deafc..6ab01f4 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -63,6 +63,7 @@
         USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
         USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
         USAGE_HW_COMPOSER       = GRALLOC_USAGE_HW_COMPOSER,
+        USAGE_HW_VIDEO_ENCODER  = GRALLOC_USAGE_HW_VIDEO_ENCODER,
         USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
     };
 
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 2efe8ca..c5bd0c5 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -231,6 +231,10 @@
     { "LANGUAGE_SWITCH", 204 },
     { "MANNER_MODE", 205 },
     { "3D_MODE", 206 },
+    { "CONTACTS", 207 },
+    { "CALENDAR", 208 },
+    { "MUSIC", 209 },
+    { "CALCULATOR", 210 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5ccf87f..5d34787 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -773,6 +773,7 @@
         bwr.read_buffer = (long unsigned int)mIn.data();
     } else {
         bwr.read_size = 0;
+        bwr.read_buffer = 0;
     }
 
     IF_LOG_COMMANDS() {
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index ed319f5..9767568 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -32,6 +32,10 @@
 
 LOCAL_MODULE:= libgui
 
+ifeq ($(TARGET_BOARD_PLATFORM), tegra)
+	LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 3c0d475..fcd287c 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -36,8 +36,28 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 
+// This compile option causes SurfaceTexture to return the buffer that is currently
+// attached to the GL texture from dequeueBuffer when no other buffers are
+// available.  It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
+// implicit cross-process synchronization to prevent the buffer from being
+// written to before the buffer has (a) been detached from the GL texture and
+// (b) all GL reads from the buffer have completed.
+#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
+#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    true
+#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
+#else
+#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    false
+#endif
 
-#define ALLOW_DEQUEUE_CURRENT_BUFFER    false
+// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
+// to synchronize access to the buffers.  It will cause dequeueBuffer to stall,
+// waiting for the GL reads for the buffer being dequeued to complete before
+// allowing the buffer to be dequeued.
+#ifdef USE_FENCE_SYNC
+#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
+#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
+#endif
+#endif
 
 // Macros for including the SurfaceTexture name in log messages
 #define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
@@ -95,7 +115,7 @@
 }
 
 SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
-        GLenum texTarget) :
+        GLenum texTarget, bool useFenceSync) :
     mDefaultWidth(1),
     mDefaultHeight(1),
     mPixelFormat(PIXEL_FORMAT_RGBA_8888),
@@ -112,6 +132,11 @@
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false),
+#ifdef USE_FENCE_SYNC
+    mUseFenceSync(useFenceSync),
+#else
+    mUseFenceSync(false),
+#endif
     mTexTarget(texTarget),
     mFrameCounter(0) {
     // Choose a name using the PID and a process-unique ID.
@@ -257,190 +282,225 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mMutex);
-
     status_t returnFlags(OK);
+    EGLDisplay dpy = EGL_NO_DISPLAY;
+    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
 
-    int found = -1;
-    int foundSync = -1;
-    int dequeuedCount = 0;
-    bool tryAgain = true;
-    while (tryAgain) {
-        if (mAbandoned) {
-            ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
-            return NO_INIT;
-        }
+    { // Scope for the lock
+        Mutex::Autolock lock(mMutex);
 
-        // We need to wait for the FIFO to drain if the number of buffer
-        // needs to change.
-        //
-        // The condition "number of buffers 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.
-
-        const int minBufferCountNeeded = mSynchronousMode ?
-                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
-
-        const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
-                ((mServerBufferCount != mBufferCount) ||
-                        (mServerBufferCount < minBufferCountNeeded));
-
-        if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
-            // wait for the FIFO to drain
-            mDequeueCondition.wait(mMutex);
-            // NOTE: we continue here because we need to reevaluate our
-            // whole state (eg: we could be abandoned or disconnected)
-            continue;
-        }
-
-        if (numberOfBuffersNeedsToChange) {
-            // here we're guaranteed that mQueue is empty
-            freeAllBuffersLocked();
-            mBufferCount = mServerBufferCount;
-            if (mBufferCount < minBufferCountNeeded)
-                mBufferCount = minBufferCountNeeded;
-            mCurrentTexture = 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++;
+        int found = -1;
+        int foundSync = -1;
+        int dequeuedCount = 0;
+        bool tryAgain = true;
+        while (tryAgain) {
+            if (mAbandoned) {
+                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+                return NO_INIT;
             }
 
-            // if buffer is FREE it CANNOT be current
-            LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
-                    "dequeueBuffer: buffer %d is both FREE and current!", i);
+            // We need to wait for the FIFO to drain if the number of buffer
+            // needs to change.
+            //
+            // The condition "number of buffers 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.
 
-            if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
-                if (state == BufferSlot::FREE || i == mCurrentTexture) {
-                    foundSync = i;
-                    if (i != mCurrentTexture) {
-                        found = i;
-                        break;
-                    }
+            const int minBufferCountNeeded = mSynchronousMode ?
+                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+            const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
+                    ((mServerBufferCount != mBufferCount) ||
+                            (mServerBufferCount < minBufferCountNeeded));
+
+            if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
+                // wait for the FIFO to drain
+                mDequeueCondition.wait(mMutex);
+                // NOTE: we continue here because we need to reevaluate our
+                // whole state (eg: we could be abandoned or disconnected)
+                continue;
+            }
+
+            if (numberOfBuffersNeedsToChange) {
+                // here we're guaranteed that mQueue is empty
+                freeAllBuffersLocked();
+                mBufferCount = mServerBufferCount;
+                if (mBufferCount < minBufferCountNeeded)
+                    mBufferCount = minBufferCountNeeded;
+                mCurrentTexture = 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++;
                 }
-            } else {
-                if (state == BufferSlot::FREE) {
-                    /** For Asynchronous mode, we need to return the oldest of free buffers
-                    * There is only one instance when the Framecounter overflows, this logic
-                    * might return the earlier buffer to client. Which is a negligible impact
-                    **/
-                    if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
+
+                // if buffer is FREE it CANNOT be current
+                LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
+                        "dequeueBuffer: buffer %d is both FREE and current!",
+                        i);
+
+                if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
+                    if (state == BufferSlot::FREE || i == mCurrentTexture) {
                         foundSync = i;
-                        found = i;
+                        if (i != mCurrentTexture) {
+                            found = i;
+                            break;
+                        }
+                    }
+                } else {
+                    if (state == BufferSlot::FREE) {
+                        /* We return the oldest of the free buffers to avoid
+                         * stalling the producer if possible.  This is because
+                         * the consumer may still have pending reads of the
+                         * buffers in flight.
+                         */
+                        bool isOlder = mSlots[i].mFrameNumber <
+                                mSlots[found].mFrameNumber;
+                        if (found < 0 || isOlder) {
+                            foundSync = i;
+                            found = i;
+                        }
                     }
                 }
             }
-        }
 
-        // clients are not allowed to dequeue more than one buffer
-        // if they didn't set a buffer count.
-        if (!mClientBufferCount && dequeuedCount) {
-            ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
-                    "setting the buffer count");
-            return -EINVAL;
-        }
+            // clients are not allowed to dequeue more than one buffer
+            // if they didn't set a buffer count.
+            if (!mClientBufferCount && dequeuedCount) {
+                ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
+                        "setting the buffer count");
+                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 = mCurrentTexture != 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))) {
-                ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
-                        "(dequeued=%d)",
-                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
-                        dequeuedCount);
-                return -EBUSY;
+            // 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 = mCurrentTexture != 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))) {
+                    ST_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 some buffers to be consumed
+            tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+            if (tryAgain) {
+                mDequeueCondition.wait(mMutex);
             }
         }
 
-        // we're in synchronous mode and didn't find a buffer, we need to wait
-        // for some buffers to be consumed
-        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
-        if (tryAgain) {
-            mDequeueCondition.wait(mMutex);
+        if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+            // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+            found = foundSync;
         }
-    }
 
-    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
-        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
-        found = foundSync;
-    }
-
-    if (found == INVALID_BUFFER_SLOT) {
-        // This should not happen.
-        ST_LOGE("dequeueBuffer: no available buffer slots");
-        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) {
-            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
-                    "failed");
-            return error;
+        if (found == INVALID_BUFFER_SLOT) {
+            // This should not happen.
+            ST_LOGE("dequeueBuffer: no available buffer slots");
+            return -EBUSY;
         }
-        if (updateFormat) {
-            mPixelFormat = format;
+
+        const int buf = found;
+        *outBuf = found;
+
+        const bool useDefaultSize = !w && !h;
+        if (useDefaultSize) {
+            // use the default size
+            w = mDefaultWidth;
+            h = mDefaultHeight;
         }
-        mSlots[buf].mGraphicBuffer = graphicBuffer;
-        mSlots[buf].mRequestBufferCalled = false;
-        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
-            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
-            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
-            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+
+        const bool updateFormat = (format != 0);
+        if (!updateFormat) {
+            // keep the current (or default) format
+            format = mPixelFormat;
         }
-        returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+
+        // 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) {
+                ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
+                        "failed");
+                return error;
+            }
+            if (updateFormat) {
+                mPixelFormat = format;
+            }
+            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mRequestBufferCalled = false;
+            mSlots[buf].mFence = EGL_NO_SYNC_KHR;
+            if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
+                eglDestroyImageKHR(mSlots[buf].mEglDisplay,
+                        mSlots[buf].mEglImage);
+                mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
+                mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+            }
+            if (mCurrentTexture == buf) {
+                // The current texture no longer references the buffer in this slot
+                // since we just allocated a new buffer.
+                mCurrentTexture = INVALID_BUFFER_SLOT;
+            }
+            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+        }
+
+        dpy = mSlots[buf].mEglDisplay;
+        fence = mSlots[buf].mFence;
+        mSlots[buf].mFence = EGL_NO_SYNC_KHR;
     }
+
+    if (fence != EGL_NO_SYNC_KHR) {
+        EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
+        // If something goes wrong, log the error, but return the buffer without
+        // synchronizing access to it.  It's too late at this point to abort the
+        // dequeue operation.
+        if (result == EGL_FALSE) {
+            LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
+        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+            LOGE("dequeueBuffer: timeout waiting for fence");
+        }
+        eglDestroySyncKHR(dpy, fence);
+    }
+
     ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf,
             mSlots[buf].mGraphicBuffer->handle, returnFlags);
+
     return returnFlags;
 }
 
@@ -637,8 +697,9 @@
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        ST_LOGE("disconnect: SurfaceTexture has been abandoned!");
-        return NO_INIT;
+        // it is not really an error to disconnect after the surface
+        // has been abandoned, it should just be a no-op.
+        return NO_ERROR;
     }
 
     int err = NO_ERROR;
@@ -702,8 +763,8 @@
 
         // Update the GL texture object.
         EGLImageKHR image = mSlots[buf].mEglImage;
+        EGLDisplay dpy = eglGetCurrentDisplay();
         if (image == EGL_NO_IMAGE_KHR) {
-            EGLDisplay dpy = eglGetCurrentDisplay();
             if (mSlots[buf].mGraphicBuffer == 0) {
                 ST_LOGE("buffer at slot %d is null", buf);
                 return BAD_VALUE;
@@ -736,16 +797,32 @@
             return -EINVAL;
         }
 
-        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
-                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf,
-                mSlots[buf].mGraphicBuffer->handle);
+        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
+            if (mUseFenceSync) {
+                EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
+                        NULL);
+                if (fence == EGL_NO_SYNC_KHR) {
+                    LOGE("updateTexImage: error creating fence: %#x",
+                            eglGetError());
+                    return -EINVAL;
+                }
+                glFlush();
+                mSlots[mCurrentTexture].mFence = fence;
+            }
+        }
+
+        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
+                mCurrentTexture,
+                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
+                buf, mSlots[buf].mGraphicBuffer->handle);
 
         if (mCurrentTexture != INVALID_BUFFER_SLOT) {
             // The current buffer becomes FREE if it was still in the queued
             // state. If it has already been given to the client
             // (synchronous mode), then it stays in DEQUEUED state.
-            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
+            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
                 mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
+            }
         }
 
         // Update the SurfaceTexture state.
@@ -1000,6 +1077,11 @@
     return mCurrentScalingMode;
 }
 
+bool SurfaceTexture::isSynchronousMode() const {
+    Mutex::Autolock lock(mMutex);
+    return mSynchronousMode;
+}
+
 int SurfaceTexture::query(int what, int* outValue)
 {
     Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 98fa171..48070d6 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -36,6 +36,12 @@
     SurfaceTextureClient::init();
 }
 
+SurfaceTextureClient::~SurfaceTextureClient() {
+    if (mConnectedToCpu) {
+        SurfaceTextureClient::disconnect(NATIVE_WINDOW_API_CPU);
+    }
+}
+
 void SurfaceTextureClient::init() {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 93ebfb9..c313904 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -396,7 +396,8 @@
             1.0f, 1.0f,
         };
 
-        glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
+        glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
+                triangleVertices);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
         glEnableVertexAttribArray(mPositionHandle);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
@@ -410,13 +411,17 @@
         // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
         // they're setting the defautls for that target, but when hacking things
         // to use GL_TEXTURE_2D they are needed to achieve the same behavior.
-        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER,
+                GL_LINEAR);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
-        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER,
+                GL_LINEAR);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
-        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
+                GL_CLAMP_TO_EDGE);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
-        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
+                GL_CLAMP_TO_EDGE);
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
 
         GLfloat texMatrix[16];
@@ -531,6 +536,20 @@
     }
 }
 
+void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
+        uint8_t g, uint8_t b, uint8_t a) {
+    const size_t PIXEL_SIZE = 4;
+    for (int y = 0; y < h; y++) {
+        for (int x = 0; x < h; x++) {
+            off_t offset = (y * stride + x) * PIXEL_SIZE;
+            buf[offset + 0] = r;
+            buf[offset + 1] = g;
+            buf[offset + 2] = b;
+            buf[offset + 3] = a;
+        }
+    }
+}
+
 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
     const int texWidth = 64;
     const int texHeight = 66;
@@ -640,8 +659,8 @@
 
     for (int i = 0; i < 5; i++) {
         const android_native_rect_t& crop(crops[i]);
-        SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", crop.left,
-                crop.top, crop.right, crop.bottom).string());
+        SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }",
+                crop.left, crop.top, crop.right, crop.bottom).string());
 
         ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
 
@@ -650,13 +669,15 @@
         ASSERT_TRUE(anb != NULL);
 
         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
+                buf->getNativeBuffer()));
 
         uint8_t* img = NULL;
         buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
         fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
         buf->unlock();
-        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
+                buf->getNativeBuffer()));
 
         mST->updateTexImage();
 
@@ -708,7 +729,8 @@
 
     class ProducerThread : public Thread {
     public:
-        ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+        ProducerThread(const sp<ANativeWindow>& anw,
+                const TestPixel* testPixels):
                 mANW(anw),
                 mTestPixels(testPixels) {
         }
@@ -940,82 +962,6 @@
     EXPECT_TRUE(checkPixel( 3, 52,  35, 231,  35,  35));
 }
 
-TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) {
-    const int texWidth = 64;
-    const int texHeight = 64;
-
-    mST->setDefaultBufferSize(texWidth, texHeight);
-
-    // Do the producer side of things
-    EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
-            mANW.get(), NULL);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
-
-    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
-            mEglContext));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    glClearColor(0.6, 0.6, 0.6, 0.6);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(4, 4, 4, 4);
-    glClearColor(1.0, 0.0, 0.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    glScissor(24, 48, 4, 4);
-    glClearColor(0.0, 1.0, 0.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    glScissor(37, 17, 4, 4);
-    glClearColor(0.0, 0.0, 1.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    eglSwapBuffers(mEglDisplay, stcEglSurface);
-
-    // Do the consumer side of things
-    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-            mEglContext));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    glDisable(GL_SCISSOR_TEST);
-
-    mST->updateTexImage();
-
-    // We must wait until updateTexImage has been called to destroy the
-    // EGLSurface because we're in synchronous mode.
-    eglDestroySurface(mEglDisplay, stcEglSurface);
-
-    glClearColor(0.2, 0.2, 0.2, 0.2);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    glViewport(0, 0, texWidth, texHeight);
-    drawTexture();
-
-    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
-
-    EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
-    EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
-    EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
-    EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
-    EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
-}
-
 TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
     class ProducerThread : public Thread {
     public:
@@ -1093,13 +1039,284 @@
             reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
 }
 
+TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
+    int texHeight = 16;
+    ANativeWindowBuffer* anb;
+
+    GLint maxTextureSize;
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+
+    // make sure it works with small textures
+    mST->setDefaultBufferSize(16, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(16, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+    // make sure it works with GL_MAX_TEXTURE_SIZE
+    mST->setDefaultBufferSize(maxTextureSize, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(maxTextureSize, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+    // make sure it fails with GL_MAX_TEXTURE_SIZE+1
+    mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(maxTextureSize+1, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    ASSERT_NE(NO_ERROR, mST->updateTexImage());
+}
+
 /*
- * This test is for testing GL -> GL texture streaming via SurfaceTexture.  It
- * contains functionality to create a producer thread that will perform GL
- * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
- * Additionally it supports interlocking the producer and consumer threads so
- * that a specific sequence of calls can be deterministically created by the
- * test.
+ * This test fixture is for testing GL -> GL texture streaming.  It creates an
+ * EGLSurface and an EGLContext for the image producer to use.
+ */
+class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+protected:
+    SurfaceTextureGLToGLTest():
+            mProducerEglSurface(EGL_NO_SURFACE),
+            mProducerEglContext(EGL_NO_CONTEXT) {
+    }
+
+    virtual void SetUp() {
+        SurfaceTextureGLTest::SetUp();
+
+        EGLConfig myConfig = {0};
+        EGLint numConfigs = 0;
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
+                1, &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
+                mANW.get(), NULL);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
+
+        mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
+                EGL_NO_CONTEXT, getContextAttribs());
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
+    }
+
+    virtual void TearDown() {
+        if (mProducerEglContext != EGL_NO_CONTEXT) {
+            eglDestroyContext(mEglDisplay, mProducerEglContext);
+        }
+        if (mProducerEglSurface != EGL_NO_SURFACE) {
+            eglDestroySurface(mEglDisplay, mProducerEglSurface);
+        }
+        SurfaceTextureGLTest::TearDown();
+    }
+
+    EGLSurface mProducerEglSurface;
+    EGLContext mProducerEglContext;
+};
+
+TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) {
+    const int texWidth = 64;
+    const int texHeight = 64;
+
+    mST->setDefaultBufferSize(texWidth, texHeight);
+
+    // Do the producer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // This is needed to ensure we pick up a buffer of the correct size.
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    glClearColor(0.6, 0.6, 0.6, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(4, 4, 4, 4);
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(24, 48, 4, 4);
+    glClearColor(0.0, 1.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(37, 17, 4, 4);
+    glClearColor(0.0, 0.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    // Do the consumer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    glDisable(GL_SCISSOR_TEST);
+
+    mST->updateTexImage(); // Skip the first frame, which was empty
+    mST->updateTexImage();
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glViewport(0, 0, texWidth, texHeight);
+    drawTexture();
+
+    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+    EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
+    EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
+    EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
+    EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
+    sp<GraphicBuffer> buffers[3];
+
+    // This test requires async mode to run on a single thread.
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    for (int i = 0; i < 3; i++) {
+        // Produce a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+                mProducerEglSurface, mProducerEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        glClear(GL_COLOR_BUFFER_BIT);
+        eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+        // Consume a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+                mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        mST->updateTexImage();
+        buffers[i] = mST->getCurrentBuffer();
+    }
+
+    // Destroy the GL texture object to release its ref on buffers[2].
+    GLuint texID = TEX_ID;
+    glDeleteTextures(1, &texID);
+
+    // Destroy the EGLSurface
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // Release the ref that the SurfaceTexture has on buffers[2].
+    mST->abandon();
+
+    EXPECT_EQ(1, buffers[0]->getStrongCount());
+    EXPECT_EQ(1, buffers[1]->getStrongCount());
+
+    // Depending on how lazily the GL driver dequeues buffers, we may end up
+    // with either two or three total buffers.  If there are three, make sure
+    // the last one was properly down-ref'd.
+    if (buffers[2] != buffers[0]) {
+        EXPECT_EQ(1, buffers[2]->getStrongCount());
+    }
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
+    sp<GraphicBuffer> buffers[3];
+
+    // This test requires async mode to run on a single thread.
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    for (int i = 0; i < 3; i++) {
+        // Produce a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+                mProducerEglSurface, mProducerEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        // Consume a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+                mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+        buffers[i] = mST->getCurrentBuffer();
+    }
+
+    // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has
+    // on buffers[2].
+    mST->abandon();
+
+    // Destroy the GL texture object to release its ref on buffers[2].
+    GLuint texID = TEX_ID;
+    glDeleteTextures(1, &texID);
+
+    // Destroy the EGLSurface.
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(1, buffers[0]->getStrongCount());
+    EXPECT_EQ(1, buffers[1]->getStrongCount());
+
+    // Depending on how lazily the GL driver dequeues buffers, we may end up
+    // with either two or three total buffers.  If there are three, make sure
+    // the last one was properly down-ref'd.
+    if (buffers[2] != buffers[0]) {
+        EXPECT_EQ(1, buffers[2]->getStrongCount());
+    }
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
+    // This test requires 3 buffers to run on a single thread.
+    mST->setBufferCountServer(3);
+
+    ASSERT_TRUE(mST->isSynchronousMode());
+
+    for (int i = 0; i < 10; i++) {
+        // Produce a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+                mProducerEglSurface, mProducerEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        glClear(GL_COLOR_BUFFER_BIT);
+        EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        // Consume a frame
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+                mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+    }
+
+    ASSERT_TRUE(mST->isSynchronousMode());
+}
+
+/*
+ * This test fixture is for testing GL -> GL texture streaming from one thread
+ * to another.  It contains functionality to create a producer thread that will
+ * perform GL rendering to an ANativeWindow that feeds frames to a
+ * SurfaceTexture.  Additionally it supports interlocking the producer and
+ * consumer threads so that a specific sequence of calls can be
+ * deterministically created by the test.
  *
  * The intended usage is as follows:
  *
@@ -1122,7 +1339,7 @@
  * }
  *
  */
-class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest {
 protected:
 
     // ProducerThread is an abstract base class to simplify the creation of
@@ -1223,30 +1440,8 @@
         Condition mFrameFinishCondition;
     };
 
-    SurfaceTextureGLToGLTest():
-            mProducerEglSurface(EGL_NO_SURFACE),
-            mProducerEglContext(EGL_NO_CONTEXT) {
-    }
-
     virtual void SetUp() {
-        SurfaceTextureGLTest::SetUp();
-
-        EGLConfig myConfig = {0};
-        EGLint numConfigs = 0;
-        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
-                1, &numConfigs));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
-                mANW.get(), NULL);
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
-
-        mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
-                EGL_NO_CONTEXT, getContextAttribs());
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
-
+        SurfaceTextureGLToGLTest::SetUp();
         mFC = new FrameCondition();
         mST->setFrameAvailableListener(mFC);
     }
@@ -1255,15 +1450,9 @@
         if (mProducerThread != NULL) {
             mProducerThread->requestExitAndWait();
         }
-        if (mProducerEglContext != EGL_NO_CONTEXT) {
-            eglDestroyContext(mEglDisplay, mProducerEglContext);
-        }
-        if (mProducerEglSurface != EGL_NO_SURFACE) {
-            eglDestroySurface(mEglDisplay, mProducerEglSurface);
-        }
         mProducerThread.clear();
         mFC.clear();
-        SurfaceTextureGLTest::TearDown();
+        SurfaceTextureGLToGLTest::TearDown();
     }
 
     void runProducerThread(const sp<ProducerThread> producerThread) {
@@ -1274,13 +1463,12 @@
         producerThread->run();
     }
 
-    EGLSurface mProducerEglSurface;
-    EGLContext mProducerEglContext;
     sp<ProducerThread> mProducerThread;
     sp<FrameCondition> mFC;
 };
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+        UpdateTexImageBeforeFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1298,7 +1486,8 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+        UpdateTexImageAfterFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1316,7 +1505,8 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+        RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1344,7 +1534,8 @@
     }
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+        RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1373,7 +1564,8 @@
 }
 
 // XXX: This test is disabled because it is currently hanging on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
+TEST_F(SurfaceTextureGLThreadToGLTest,
+        DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
     enum { NUM_ITERATIONS = 64 };
 
     class PT : public ProducerThread {
@@ -1438,118 +1630,101 @@
     }
 }
 
-TEST_F(SurfaceTextureGLTest, EglDestroySurfaceUnrefsBuffers) {
-    EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
-            mANW.get(), NULL);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
+class SurfaceTextureFBOTest : public SurfaceTextureGLTest {
+protected:
 
-    sp<GraphicBuffer> buffers[3];
+    virtual void SetUp() {
+        SurfaceTextureGLTest::SetUp();
 
-    for (int i = 0; i < 3; i++) {
-        // Produce a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        glClear(GL_COLOR_BUFFER_BIT);
-        eglSwapBuffers(mEglDisplay, stcEglSurface);
+        glGenFramebuffers(1, &mFbo);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
 
-        // Consume a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        mST->updateTexImage();
-        buffers[i] = mST->getCurrentBuffer();
+        glGenTextures(1, &mFboTex);
+        glBindTexture(GL_TEXTURE_2D, mFboTex);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(),
+                getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        glBindTexture(GL_TEXTURE_2D, 0);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+
+        glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                GL_TEXTURE_2D, mFboTex, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
     }
 
-    // Destroy the GL texture object to release its ref on buffers[2].
-    GLuint texID = TEX_ID;
-    glDeleteTextures(1, &texID);
+    virtual void TearDown() {
+        SurfaceTextureGLTest::TearDown();
 
-    // Destroy the EGLSurface
-    EXPECT_TRUE(eglDestroySurface(mEglDisplay, stcEglSurface));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        glDeleteTextures(1, &mFboTex);
+        glDeleteFramebuffers(1, &mFbo);
+    }
 
-    // Release the ref that the SurfaceTexture has on buffers[2].
-    mST->abandon();
+    GLuint mFbo;
+    GLuint mFboTex;
+};
 
-    EXPECT_EQ(1, buffers[0]->getStrongCount());
-    EXPECT_EQ(1, buffers[1]->getStrongCount());
-    EXPECT_EQ(1, buffers[2]->getStrongCount());
-}
+// This test is intended to verify that proper synchronization is done when
+// rendering into an FBO.
+TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) {
+    const int texWidth = 64;
+    const int texHeight = 64;
 
-TEST_F(SurfaceTextureGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
-    EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
-            mANW.get(), NULL);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
-    sp<GraphicBuffer> buffers[3];
+    android_native_buffer_t* anb;
+    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_TRUE(anb != NULL);
 
-    for (int i = 0; i < 3; i++) {
-        // Produce a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        glClear(GL_COLOR_BUFFER_BIT);
-        EXPECT_TRUE(eglSwapBuffers(mEglDisplay, stcEglSurface));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
 
-        // Consume a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    // Fill the buffer with green
+    uint8_t* img = NULL;
+    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255,
+            0, 255);
+    buf->unlock();
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+
+    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+    drawTexture();
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    for (int i = 0; i < 4; i++) {
+        SCOPED_TRACE(String8::format("frame %d", i).string());
+
+        ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+        ASSERT_TRUE(anb != NULL);
+
+        buf = new GraphicBuffer(anb, false);
+        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
+                buf->getNativeBuffer()));
+
+        // Fill the buffer with red
+        ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
+                (void**)(&img)));
+        fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0,
+                0, 255);
+        ASSERT_EQ(NO_ERROR, buf->unlock());
+        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
+                buf->getNativeBuffer()));
+
         ASSERT_EQ(NO_ERROR, mST->updateTexImage());
-        buffers[i] = mST->getCurrentBuffer();
+
+        drawTexture();
+
+        EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255));
     }
 
-    // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has
-    // on buffers[2].
-    mST->abandon();
+    glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
 
-    // Destroy the GL texture object to release its ref on buffers[2].
-    GLuint texID = TEX_ID;
-    glDeleteTextures(1, &texID);
-
-    // Destroy the EGLSurface.
-    EXPECT_TRUE(eglDestroySurface(mEglDisplay, stcEglSurface));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    EXPECT_EQ(1, buffers[0]->getStrongCount());
-    EXPECT_EQ(1, buffers[1]->getStrongCount());
-    EXPECT_EQ(1, buffers[2]->getStrongCount());
-}
-
-TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
-    int texHeight = 16;
-    ANativeWindowBuffer* anb;
-
-    GLint maxTextureSize;
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
-
-    // make sure it works with small textures
-    mST->setDefaultBufferSize(16, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(16, anb->width);
-    EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
-    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
-
-    // make sure it works with GL_MAX_TEXTURE_SIZE
-    mST->setDefaultBufferSize(maxTextureSize, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(maxTextureSize, anb->width);
-    EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
-    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
-
-    // make sure it fails with GL_MAX_TEXTURE_SIZE+1
-    mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(maxTextureSize+1, anb->width);
-    EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
-    ASSERT_NE(NO_ERROR, mST->updateTexImage());
+    EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255));
 }
 
 } // namespace android
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index a077cbc5..158f785 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -163,7 +163,6 @@
         render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
                 0, 0, NULL);
     }
-
 }
 
 void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
@@ -615,7 +614,8 @@
 void FontRenderer::appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2,
         float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
         float x4, float y4, float z4, float u4, float v4) {
-    if (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom) {
+    if (mClip &&
+            (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) {
         return;
     }
 
@@ -723,11 +723,16 @@
         return image;
     }
 
+    mClip = NULL;
+    mBounds = NULL;
+
     Rect bounds;
     mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
+
     uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
     uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
     uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight];
+
     for (uint32_t i = 0; i < paddedWidth * paddedHeight; i++) {
         dataBuffer[i] = 0;
     }
@@ -765,8 +770,11 @@
     mDrawn = false;
     mBounds = bounds;
     mClip = clip;
+
     mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y);
+
     mBounds = NULL;
+    mClip = NULL;
 
     if (mCurrentQuadIndex != 0) {
         issueDrawCommand();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 32595e4..4d22646 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -201,14 +201,16 @@
 }
 
 void OpenGLRenderer::resume() {
-    glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
+    sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
+
+    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
 
     glEnable(GL_SCISSOR_TEST);
     dirtyClip();
 
     glDisable(GL_DITHER);
 
-    glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     mCaches.blend = true;
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index d51154d..aff7b93 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -213,7 +213,8 @@
     Layer* layer;
 
     /**
-     * Only set when the flag kFlagIsFboLayer is set.
+     * Target FBO used for rendering. Set to 0 when rendering directly
+     * into the framebuffer.
      */
     GLuint fbo;
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 2e7f213..cd7b3a7 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -21,6 +21,7 @@
 
 #ifndef ANDROID_RS_SERIALIZE
 #include <bcinfo/BitcodeTranslator.h>
+#include <bcinfo/BitcodeWrapper.h>
 #endif
 
 using namespace android;
@@ -196,7 +197,24 @@
 
     //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
 #ifndef ANDROID_RS_SERIALIZE
-    uint32_t sdkVersion = rsc->getTargetSdkVersion();
+    uint32_t sdkVersion = 0;
+    bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
+    if (!bcWrapper.unwrap()) {
+        LOGE("Bitcode is not in proper container format (raw or wrapper)");
+        return false;
+    }
+
+    rsAssert(bcWrapper.getHeaderVersion() == 0);
+    if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
+        sdkVersion = bcWrapper.getTargetAPI();
+    }
+
+    if (sdkVersion == 0) {
+        // This signals that we didn't have a wrapper containing information
+        // about the bitcode.
+        sdkVersion = rsc->getTargetSdkVersion();
+    }
+
     if (BT) {
         delete BT;
     }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 5e7a7eb..37aacab 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -508,8 +508,8 @@
 
         // Play sounds on STREAM_RING only and if lock screen is not on.
         if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
-                ((STREAM_VOLUME_ALIAS[streamType] != AudioSystem.STREAM_RING) ||
-                 (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) {
+                ((STREAM_VOLUME_ALIAS[streamType] != AudioSystem.STREAM_RING)
+                 || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
 
@@ -1576,49 +1576,83 @@
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            synchronized (mScoClients) {
-                // Discard timeout message
-                mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
-                mBluetoothHeadset = (BluetoothHeadset) proxy;
-                List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
+            BluetoothDevice btDevice;
+            List<BluetoothDevice> deviceList;
+            switch(profile) {
+            case BluetoothProfile.A2DP:
+                BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
+                deviceList = a2dp.getConnectedDevices();
                 if (deviceList.size() > 0) {
-                    mBluetoothHeadsetDevice = deviceList.get(0);
-                } else {
-                    mBluetoothHeadsetDevice = null;
+                    btDevice = deviceList.get(0);
+                    handleA2dpConnectionStateChange(btDevice, a2dp.getConnectionState(btDevice));
                 }
-                // Refresh SCO audio state
-                checkScoAudioState();
-                // Continue pending action if any
-                if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
-                        mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
-                        mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
-                    boolean status = false;
-                    if (mBluetoothHeadsetDevice != null) {
-                        switch (mScoAudioState) {
-                        case SCO_STATE_ACTIVATE_REQ:
-                            mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
-                            status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
-                                    mBluetoothHeadsetDevice);
-                            break;
-                        case SCO_STATE_DEACTIVATE_REQ:
-                            status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
-                                    mBluetoothHeadsetDevice);
-                            break;
-                        case SCO_STATE_DEACTIVATE_EXT_REQ:
-                            status = mBluetoothHeadset.stopVoiceRecognition(
-                                    mBluetoothHeadsetDevice);
+                break;
+
+            case BluetoothProfile.HEADSET:
+                synchronized (mScoClients) {
+                    // Discard timeout message
+                    mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
+                    mBluetoothHeadset = (BluetoothHeadset) proxy;
+                    deviceList = mBluetoothHeadset.getConnectedDevices();
+                    if (deviceList.size() > 0) {
+                        mBluetoothHeadsetDevice = deviceList.get(0);
+                    } else {
+                        mBluetoothHeadsetDevice = null;
+                    }
+                    // Refresh SCO audio state
+                    checkScoAudioState();
+                    // Continue pending action if any
+                    if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
+                            mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
+                            mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
+                        boolean status = false;
+                        if (mBluetoothHeadsetDevice != null) {
+                            switch (mScoAudioState) {
+                            case SCO_STATE_ACTIVATE_REQ:
+                                mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+                                status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
+                                        mBluetoothHeadsetDevice);
+                                break;
+                            case SCO_STATE_DEACTIVATE_REQ:
+                                status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
+                                        mBluetoothHeadsetDevice);
+                                break;
+                            case SCO_STATE_DEACTIVATE_EXT_REQ:
+                                status = mBluetoothHeadset.stopVoiceRecognition(
+                                        mBluetoothHeadsetDevice);
+                            }
+                        }
+                        if (!status) {
+                            sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 0,
+                                    SENDMSG_REPLACE, 0, 0, null, 0);
                         }
                     }
-                    if (!status) {
-                        sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 0,
-                                SENDMSG_REPLACE, 0, 0, null, 0);
-                    }
                 }
+                break;
+
+            default:
+                break;
             }
         }
         public void onServiceDisconnected(int profile) {
-            synchronized (mScoClients) {
-                mBluetoothHeadset = null;
+            switch(profile) {
+            case BluetoothProfile.A2DP:
+                synchronized (mConnectedDevices) {
+                    if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
+                        makeA2dpDeviceUnavailableNow(
+                                mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+                    }
+                }
+                break;
+
+            case BluetoothProfile.HEADSET:
+                synchronized (mScoClients) {
+                    mBluetoothHeadset = null;
+                }
+                break;
+
+            default:
+                break;
             }
         }
     };
@@ -2197,15 +2231,17 @@
                     AudioSystem.setParameters("restarting=true");
 
                     // Restore device connection states
-                    Set set = mConnectedDevices.entrySet();
-                    Iterator i = set.iterator();
-                    while(i.hasNext()){
-                        Map.Entry device = (Map.Entry)i.next();
-                        AudioSystem.setDeviceConnectionState(((Integer)device.getKey()).intValue(),
-                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                             (String)device.getValue());
+                    synchronized (mConnectedDevices) {
+                        Set set = mConnectedDevices.entrySet();
+                        Iterator i = set.iterator();
+                        while(i.hasNext()){
+                            Map.Entry device = (Map.Entry)i.next();
+                            AudioSystem.setDeviceConnectionState(
+                                                            ((Integer)device.getKey()).intValue(),
+                                                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                            (String)device.getValue());
+                        }
                     }
-
                     // Restore call state
                     AudioSystem.setPhoneState(mMode);
 
@@ -2244,7 +2280,9 @@
 
                 case MSG_BTA2DP_DOCK_TIMEOUT:
                     // msg.obj  == address of BTA2DP device
-                    makeA2dpDeviceUnavailableNow( (String) msg.obj );
+                    synchronized (mConnectedDevices) {
+                        makeA2dpDeviceUnavailableNow( (String) msg.obj );
+                    }
                     break;
 
                 case MSG_SET_FORCE_USE:
@@ -2304,6 +2342,7 @@
         }
     }
 
+    // must be called synchronized on mConnectedDevices
     private void makeA2dpDeviceAvailable(String address) {
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_AVAILABLE,
@@ -2314,6 +2353,7 @@
                 address);
     }
 
+    // must be called synchronized on mConnectedDevices
     private void makeA2dpDeviceUnavailableNow(String address) {
         Intent noisyIntent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
         mContext.sendBroadcast(noisyIntent);
@@ -2323,6 +2363,7 @@
         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
     }
 
+    // must be called synchronized on mConnectedDevices
     private void makeA2dpDeviceUnavailableLater(String address) {
         // prevent any activity on the A2DP audio output to avoid unwanted
         // reconnection of the sink.
@@ -2335,14 +2376,60 @@
 
     }
 
+    // must be called synchronized on mConnectedDevices
     private void cancelA2dpDeviceTimeout() {
         mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
     }
 
+    // must be called synchronized on mConnectedDevices
     private boolean hasScheduledA2dpDockTimeout() {
         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
     }
 
+    private void handleA2dpConnectionStateChange(BluetoothDevice btDevice, int state)
+    {
+        if (btDevice == null) {
+            return;
+        }
+        String address = btDevice.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
+        synchronized (mConnectedDevices) {
+            boolean isConnected =
+                (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
+                 mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address));
+
+            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                if (btDevice.isBluetoothDock()) {
+                    if (state == BluetoothProfile.STATE_DISCONNECTED) {
+                        // introduction of a delay for transient disconnections of docks when
+                        // power is rapidly turned off/on, this message will be canceled if
+                        // we reconnect the dock under a preset delay
+                        makeA2dpDeviceUnavailableLater(address);
+                        // the next time isConnected is evaluated, it will be false for the dock
+                    }
+                } else {
+                    makeA2dpDeviceUnavailableNow(address);
+                }
+            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                if (btDevice.isBluetoothDock()) {
+                    // this could be a reconnection after a transient disconnection
+                    cancelA2dpDeviceTimeout();
+                    mDockAddress = address;
+                } else {
+                    // this could be a connection of another A2DP device before the timeout of
+                    // a dock: cancel the dock timeout, and make the dock unavailable now
+                    if(hasScheduledA2dpDockTimeout()) {
+                        cancelA2dpDeviceTimeout();
+                        makeA2dpDeviceUnavailableNow(mDockAddress);
+                    }
+                }
+                makeA2dpDeviceAvailable(address);
+            }
+        }
+    }
+
     /* cache of the address of the last dock the device was connected to */
     private String mDockAddress;
 
@@ -2380,44 +2467,8 @@
                 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (btDevice == null) {
-                    return;
-                }
-                String address = btDevice.getAddress();
-                if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-                    address = "";
-                }
-                boolean isConnected =
-                    (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
-                     mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address));
 
-                if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
-                    if (btDevice.isBluetoothDock()) {
-                        if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                            // introduction of a delay for transient disconnections of docks when
-                            // power is rapidly turned off/on, this message will be canceled if
-                            // we reconnect the dock under a preset delay
-                            makeA2dpDeviceUnavailableLater(address);
-                            // the next time isConnected is evaluated, it will be false for the dock
-                        }
-                    } else {
-                        makeA2dpDeviceUnavailableNow(address);
-                    }
-                } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                    if (btDevice.isBluetoothDock()) {
-                        // this could be a reconnection after a transient disconnection
-                        cancelA2dpDeviceTimeout();
-                        mDockAddress = address;
-                    } else {
-                        // this could be a connection of another A2DP device before the timeout of
-                        // a dock: cancel the dock timeout, and make the dock unavailable now
-                        if(hasScheduledA2dpDockTimeout()) {
-                            cancelA2dpDeviceTimeout();
-                            makeA2dpDeviceUnavailableNow(mDockAddress);
-                        }
-                    }
-                    makeA2dpDeviceAvailable(address);
-                }
+                handleA2dpConnectionStateChange(btDevice, state);
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
@@ -2446,103 +2497,126 @@
                 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
                     address = "";
                 }
-                boolean isConnected = (mConnectedDevices.containsKey(device) &&
-                                       mConnectedDevices.get(device).equals(address));
 
-                synchronized (mScoClients) {
-                    if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
-                        AudioSystem.setDeviceConnectionState(device,
+                synchronized (mConnectedDevices) {
+                    boolean isConnected = (mConnectedDevices.containsKey(device) &&
+                                           mConnectedDevices.get(device).equals(address));
+
+                    synchronized (mScoClients) {
+                        if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                            AudioSystem.setDeviceConnectionState(device,
                                                              AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                                              address);
-                        mConnectedDevices.remove(device);
-                        mBluetoothHeadsetDevice = null;
-                        resetBluetoothSco();
-                    } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                        AudioSystem.setDeviceConnectionState(device,
-                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                             address);
-                        mConnectedDevices.put(new Integer(device), address);
-                        mBluetoothHeadsetDevice = btDevice;
+                            mConnectedDevices.remove(device);
+                            mBluetoothHeadsetDevice = null;
+                            resetBluetoothSco();
+                        } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                            AudioSystem.setDeviceConnectionState(device,
+                                                                 AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                                 address);
+                            mConnectedDevices.put(new Integer(device), address);
+                            mBluetoothHeadsetDevice = btDevice;
+                        }
                     }
                 }
             } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
                 int state = intent.getIntExtra("state", 0);
                 int microphone = intent.getIntExtra("microphone", 0);
 
-                if (microphone != 0) {
-                    boolean isConnected =
-                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
-                    if (state == 0 && isConnected) {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                                AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                "");
-                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
-                    } else if (state == 1 && !isConnected)  {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                                AudioSystem.DEVICE_STATE_AVAILABLE,
-                                "");
-                        mConnectedDevices.put(
-                                new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), "");
-                    }
-                } else {
-                    boolean isConnected =
-                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
-                    if (state == 0 && isConnected) {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
-                                AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                "");
-                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
-                    } else if (state == 1 && !isConnected)  {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
-                                AudioSystem.DEVICE_STATE_AVAILABLE,
-                                "");
-                        mConnectedDevices.put(
-                                new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), "");
+                synchronized (mConnectedDevices) {
+                    if (microphone != 0) {
+                        boolean isConnected =
+                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+                        if (state == 0 && isConnected) {
+                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                    "");
+                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+                        } else if (state == 1 && !isConnected)  {
+                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                                    AudioSystem.DEVICE_STATE_AVAILABLE,
+                                    "");
+                            mConnectedDevices.put(
+                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), "");
+                        }
+                    } else {
+                        boolean isConnected =
+                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+                        if (state == 0 && isConnected) {
+                            AudioSystem.setDeviceConnectionState(
+                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                    "");
+                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+                        } else if (state == 1 && !isConnected)  {
+                            AudioSystem.setDeviceConnectionState(
+                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                                    AudioSystem.DEVICE_STATE_AVAILABLE,
+                                    "");
+                            mConnectedDevices.put(
+                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), "");
+                        }
                     }
                 }
             } else if (action.equals(Intent.ACTION_USB_ANLG_HEADSET_PLUG)) {
                 int state = intent.getIntExtra("state", 0);
                 Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = "+state);
-                boolean isConnected =
-                    mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
-                if (state == 0 && isConnected) {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
-                    mConnectedDevices.remove(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
-                } else if (state == 1 && !isConnected)  {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_AVAILABLE, "");
-                    mConnectedDevices.put(
-                            new Integer(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET), "");
+                synchronized (mConnectedDevices) {
+                    boolean isConnected =
+                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+                    if (state == 0 && isConnected) {
+                        AudioSystem.setDeviceConnectionState(
+                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
+                                                        AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                                        "");
+                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+                    } else if (state == 1 && !isConnected)  {
+                        AudioSystem.setDeviceConnectionState(
+                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
+                                                        AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                        "");
+                        mConnectedDevices.put(
+                                new Integer(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET), "");
+                    }
                 }
             } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) {
                 int state = intent.getIntExtra("state", 0);
                 Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state);
-                boolean isConnected =
-                    mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
-                if (state == 0 && isConnected) {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
-                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
-                    mConnectedDevices.remove(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
-                } else if (state == 1 && !isConnected)  {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
-                                                         AudioSystem.DEVICE_STATE_AVAILABLE, "");
-                    mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_AUX_DIGITAL), "");
+                synchronized (mConnectedDevices) {
+                    boolean isConnected =
+                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
+                    if (state == 0 && isConnected) {
+                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
+                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                                             "");
+                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
+                    } else if (state == 1 && !isConnected)  {
+                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
+                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                             "");
+                        mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_AUX_DIGITAL), "");
+                    }
                 }
             } else if (action.equals(Intent.ACTION_USB_DGTL_HEADSET_PLUG)) {
                 int state = intent.getIntExtra("state", 0);
                 Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_DGTL_HEADSET_PLUG, state = "+state);
-                boolean isConnected =
-                    mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
-                if (state == 0 && isConnected) {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
-                    mConnectedDevices.remove(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
-                } else if (state == 1 && !isConnected)  {
-                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_AVAILABLE, "");
-                    mConnectedDevices.put(
-                            new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), "");
+                synchronized (mConnectedDevices) {
+                    boolean isConnected =
+                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
+                    if (state == 0 && isConnected) {
+                        AudioSystem.setDeviceConnectionState(
+                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
+                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                                         "");
+                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
+                    } else if (state == 1 && !isConnected)  {
+                        AudioSystem.setDeviceConnectionState(
+                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
+                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                         "");
+                        mConnectedDevices.put(
+                                new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), "");
+                    }
                 }
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
@@ -2596,7 +2670,7 @@
                         0, 0, null, 0);
 
                 mKeyguardManager =
-                    (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
+                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
                 mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
                 resetBluetoothSco();
                 getBluetoothHeadset();
@@ -2606,6 +2680,12 @@
                 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                 mContext.sendStickyBroadcast(newIntent);
+
+                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+                if (adapter != null) {
+                    adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+                                            BluetoothProfile.A2DP);
+                }
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     // a package is being removed, not replaced
@@ -3407,7 +3487,7 @@
         updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
     }
 
-    /** 
+    /**
      * see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
      * precondition: mediaIntent != null, target != null
      */
@@ -3423,7 +3503,7 @@
         }
     }
 
-    /** 
+    /**
      * see AudioManager.unregisterMediaButtonIntent(PendingIntent mediaIntent)
      * precondition: mediaIntent != null, eventReceiver != null
      */
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 03ae62a..4756078 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -1845,7 +1845,7 @@
 
     @SuppressWarnings("unused")
     private void onPreviewProgressUpdate(int progress, boolean isFinished,
-                  boolean updateOverlay, String filename, int renderingMode) {
+                  boolean updateOverlay, String filename, int renderingMode, int error) {
         if (mPreviewProgressListener != null) {
             if (mIsFirstProgress) {
                 mPreviewProgressListener.onStart(mVideoEditor);
@@ -1870,6 +1870,8 @@
 
             if (isFinished) {
                 mPreviewProgressListener.onStop(mVideoEditor);
+            } else if (error != 0) {
+                mPreviewProgressListener.onError(mVideoEditor, error);
             } else {
                 mPreviewProgressListener.onProgress(mVideoEditor, progress, overlayData);
             }
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
index 424e436..08d27d4 100755
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ b/media/java/android/media/videoeditor/VideoEditor.java
@@ -107,6 +107,17 @@
          * @param videoEditor The VideoEditor instance
          */
         public void onStop(VideoEditor videoEditor);
+
+        /**
+         * This method notifies the listener when error has occurred during
+         * previewing a project.
+         *
+         * @param videoEditor The VideoEditor instance
+         * @param error The error that has occurred
+         * FIXME: We should pass well-defined error code to the application;
+         * but for now, we just pass whatever error code reported by the native layer.
+         */
+        public void onError(VideoEditor videoEditor, int error);
     }
 
     /**
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
old mode 100644
new mode 100755
index 4e271c7..19db1c0
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -38,6 +38,7 @@
 
 import java.io.File;
 import java.util.HashMap;
+import java.util.Locale;
 
 /**
  * {@hide}
@@ -50,7 +51,15 @@
     private final IContentProvider mMediaProvider;
     private final String mVolumeName;
     private final Uri mObjectsUri;
-    private final String mMediaStoragePath; // path to primary storage
+    // path to primary storage
+    private final String mMediaStoragePath;
+    // if not null, restrict all queries to these subdirectories
+    private final String[] mSubDirectories;
+    // where clause for restricting queries to files in mSubDirectories
+    private String mSubDirectoriesWhere;
+    // where arguments for restricting queries to files in mSubDirectories
+    private String[] mSubDirectoriesWhereArgs;
+
     private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>();
 
     // cached property groups for single properties
@@ -111,7 +120,8 @@
         System.loadLibrary("media_jni");
     }
 
-    public MtpDatabase(Context context, String volumeName, String storagePath) {
+    public MtpDatabase(Context context, String volumeName, String storagePath,
+            String[] subDirectories) {
         native_setup();
 
         mContext = context;
@@ -120,6 +130,45 @@
         mMediaStoragePath = storagePath;
         mObjectsUri = Files.getMtpObjectsUri(volumeName);
         mMediaScanner = new MediaScanner(context);
+
+        mSubDirectories = subDirectories;
+        if (subDirectories != null) {
+            // Compute "where" string for restricting queries to subdirectories
+            StringBuilder builder = new StringBuilder();
+            builder.append("(");
+            int count = subDirectories.length;
+            for (int i = 0; i < count; i++) {
+                builder.append(Files.FileColumns.DATA + "=? OR "
+                        + Files.FileColumns.DATA + " LIKE ?");
+                if (i != count - 1) {
+                    builder.append(" OR ");
+                }
+            }
+            builder.append(")");
+            mSubDirectoriesWhere = builder.toString();
+
+            // Compute "where" arguments for restricting queries to subdirectories
+            mSubDirectoriesWhereArgs = new String[count * 2];
+            for (int i = 0, j = 0; i < count; i++) {
+                String path = subDirectories[i];
+                mSubDirectoriesWhereArgs[j++] = path;
+                mSubDirectoriesWhereArgs[j++] = path + "/%";
+            }
+        }
+
+        // Set locale to MediaScanner.
+        Locale locale = context.getResources().getConfiguration().locale;
+        if (locale != null) {
+            String language = locale.getLanguage();
+            String country = locale.getCountry();
+            if (language != null) {
+                if (country != null) {
+                    mMediaScanner.setLocale(language + "_" + country);
+                } else {
+                    mMediaScanner.setLocale(language);
+                }
+            }
+        }
         initDeviceProperties(context);
     }
 
@@ -175,9 +224,44 @@
         }
     }
 
+    // check to see if the path is contained in one of our storage subdirectories
+    // returns true if we have no special subdirectories
+    private boolean inStorageSubDirectory(String path) {
+        if (mSubDirectories == null) return true;
+        if (path == null) return false;
+
+        boolean allowed = false;
+        int pathLength = path.length();
+        for (int i = 0; i < mSubDirectories.length && !allowed; i++) {
+            String subdir = mSubDirectories[i];
+            int subdirLength = subdir.length();
+            if (subdirLength < pathLength &&
+                    path.charAt(subdirLength) == '/' &&
+                    path.startsWith(subdir)) {
+                allowed = true;
+            }
+        }
+        return allowed;
+    }
+
+    // check to see if the path matches one of our storage subdirectories
+    // returns true if we have no special subdirectories
+    private boolean isStorageSubDirectory(String path) {
+    if (mSubDirectories == null) return false;
+        for (int i = 0; i < mSubDirectories.length; i++) {
+            if (path.equals(mSubDirectories[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private int beginSendObject(String path, int format, int parent,
                          int storageId, long size, long modified) {
-        // first make sure the object does not exist
+        // if mSubDirectories is not null, do not allow copying files to any other locations
+        if (!inStorageSubDirectory(path)) return -1;
+
+        // make sure the object does not exist
         if (path != null) {
             Cursor c = null;
             try {
@@ -254,33 +338,40 @@
     }
 
     private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException {
+        String where;
+        String[] whereArgs;
+
         if (storageID == 0xFFFFFFFF) {
             // query all stores
             if (format == 0) {
                 // query all formats
                 if (parent == 0) {
                     // query all objects
-                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null);
+                    where = null;
+                    whereArgs = null;
+                } else {
+                    if (parent == 0xFFFFFFFF) {
+                        // all objects in root of store
+                        parent = 0;
+                    }
+                    where = PARENT_WHERE;
+                    whereArgs = new String[] { Integer.toString(parent) };
                 }
-                if (parent == 0xFFFFFFFF) {
-                    // all objects in root of store
-                    parent = 0;
-                }
-                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE,
-                        new String[] { Integer.toString(parent) }, null);
             } else {
                 // query specific format
                 if (parent == 0) {
                     // query all objects
-                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE,
-                            new String[] { Integer.toString(format) }, null);
+                    where = FORMAT_WHERE;
+                    whereArgs = new String[] { Integer.toString(format) };
+                } else {
+                    if (parent == 0xFFFFFFFF) {
+                        // all objects in root of store
+                        parent = 0;
+                    }
+                    where = FORMAT_PARENT_WHERE;
+                    whereArgs = new String[] { Integer.toString(format),
+                                               Integer.toString(parent) };
                 }
-                if (parent == 0xFFFFFFFF) {
-                    // all objects in root of store
-                    parent = 0;
-                }
-                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE,
-                        new String[] { Integer.toString(format), Integer.toString(parent) }, null);
             }
         } else {
             // query specific store
@@ -288,35 +379,61 @@
                 // query all formats
                 if (parent == 0) {
                     // query all objects
-                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE,
-                            new String[] { Integer.toString(storageID) }, null);
+                    where = STORAGE_WHERE;
+                    whereArgs = new String[] { Integer.toString(storageID) };
+                } else {
+                    if (parent == 0xFFFFFFFF) {
+                        // all objects in root of store
+                        parent = 0;
+                    }
+                    where = STORAGE_PARENT_WHERE;
+                    whereArgs = new String[] { Integer.toString(storageID),
+                                               Integer.toString(parent) };
                 }
-                if (parent == 0xFFFFFFFF) {
-                    // all objects in root of store
-                    parent = 0;
-                }
-                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE,
-                        new String[] { Integer.toString(storageID), Integer.toString(parent) },
-                        null);
             } else {
                 // query specific format
                 if (parent == 0) {
                     // query all objects
-                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE,
-                            new String[] {  Integer.toString(storageID), Integer.toString(format) },
-                            null);
+                    where = STORAGE_FORMAT_WHERE;
+                    whereArgs = new String[] {  Integer.toString(storageID),
+                                                Integer.toString(format) };
+                } else {
+                    if (parent == 0xFFFFFFFF) {
+                        // all objects in root of store
+                        parent = 0;
+                    }
+                    where = STORAGE_FORMAT_PARENT_WHERE;
+                    whereArgs = new String[] { Integer.toString(storageID),
+                                               Integer.toString(format),
+                                               Integer.toString(parent) };
                 }
-                if (parent == 0xFFFFFFFF) {
-                    // all objects in root of store
-                    parent = 0;
-                }
-                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE,
-                        new String[] { Integer.toString(storageID),
-                                       Integer.toString(format),
-                                       Integer.toString(parent) },
-                        null);
             }
         }
+
+        // if we are restricting queries to mSubDirectories, we need to add the restriction
+        // onto our "where" arguments
+        if (mSubDirectoriesWhere != null) {
+            if (where == null) {
+                where = mSubDirectoriesWhere;
+                whereArgs = mSubDirectoriesWhereArgs;
+            } else {
+                where = where + " AND " + mSubDirectoriesWhere;
+
+                // create new array to hold whereArgs and mSubDirectoriesWhereArgs
+                String[] newWhereArgs =
+                        new String[whereArgs.length + mSubDirectoriesWhereArgs.length];
+                int i, j;
+                for (i = 0; i < whereArgs.length; i++) {
+                    newWhereArgs[i] = whereArgs[i];
+                }
+                for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) {
+                    newWhereArgs[i] = mSubDirectoriesWhereArgs[j];
+                }
+                whereArgs = newWhereArgs;
+            }
+        }
+
+        return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null);
     }
 
     private int[] getObjectList(int storageID, int format, int parent) {
@@ -598,6 +715,11 @@
             return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
         }
 
+        // do not allow renaming any of the special subdirectories
+        if (isStorageSubDirectory(path)) {
+            return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
+        }
+
         // now rename the file.  make sure this succeeds before updating database
         File oldFile = new File(path);
         int lastSlash = path.lastIndexOf('/');
@@ -779,6 +901,11 @@
                 return MtpConstants.RESPONSE_GENERAL_ERROR;
             }
 
+            // do not allow deleting any of the special subdirectories
+            if (isStorageSubDirectory(path)) {
+                return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
+            }
+
             if (format == MtpConstants.FORMAT_ASSOCIATION) {
                 // recursive case - delete all children first
                 Uri uri = Files.getMtpObjectsUri(mVolumeName);
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index ed4e92e..3d6d857 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -477,7 +477,7 @@
         pEnv->CallVoidMethod(pContext->engine,
                 pContext->onPreviewProgressUpdateMethodId,
                 currentMs,isFinished, pContext->mIsUpdateOverlay,
-                tmpFileName, pContext->mOverlayRenderingMode);
+                tmpFileName, pContext->mOverlayRenderingMode, error);
 
         if (pContext->mIsUpdateOverlay) {
             pContext->mIsUpdateOverlay = false;
@@ -1630,7 +1630,7 @@
                                      "not initialized");
 
     pContext->onPreviewProgressUpdateMethodId = pEnv->GetMethodID(engineClass,
-            "onPreviewProgressUpdate",     "(IZZLjava/lang/String;I)V");
+            "onPreviewProgressUpdate",     "(IZZLjava/lang/String;II)V");
     // Check if the context is valid (required because the context is dereferenced).
     if (needToBeLoaded) {
         // Make sure that we are in a correct state.
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index b311f35..078be94 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -30,7 +30,7 @@
 const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
 
 // static
-const char *const IStreamListener::kKeyFormatChange = "format-change";
+const char *const IStreamListener::kKeyDiscontinuityMask = "discontinuity-mask";
 
 enum {
     // IStreamSource
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index 7a7aeb6..629b165 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -82,7 +82,7 @@
             // save the strings for later so they can be used for native encoding detection
             mNames->push_back(name);
             mValues->push_back(value);
-            return true;
+            return OK;
         }
         // else fall through
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2a5c0a6..93ab704 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -54,6 +54,7 @@
       mVideoEOS(false),
       mScanSourcesPending(false),
       mScanSourcesGeneration(0),
+      mTimeDiscontinuityPending(false),
       mFlushingAudio(NONE),
       mFlushingVideo(NONE),
       mResetInProgress(false),
@@ -462,11 +463,24 @@
         {
             LOGV("kWhatReset");
 
+            if (mRenderer != NULL) {
+                // There's an edge case where the renderer owns all output
+                // buffers and is paused, therefore the decoder will not read
+                // more input data and will never encounter the matching
+                // discontinuity. To avoid this, we resume the renderer.
+
+                if (mFlushingAudio == AWAITING_DISCONTINUITY
+                        || mFlushingVideo == AWAITING_DISCONTINUITY) {
+                    mRenderer->resume();
+                }
+            }
+
             if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
                 // We're currently flushing, postpone the reset until that's
                 // completed.
 
-                LOGV("postponing reset");
+                LOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
+                        mFlushingAudio, mFlushingVideo);
 
                 mResetPostponed = true;
                 break;
@@ -477,6 +491,8 @@
                 break;
             }
 
+            mTimeDiscontinuityPending = true;
+
             if (mAudioDecoder != NULL) {
                 flushDecoder(true /* audio */, true /* needShutdown */);
             }
@@ -540,7 +556,10 @@
 
     LOGV("both audio and video are flushed now.");
 
-    mRenderer->signalTimeDiscontinuity();
+    if (mTimeDiscontinuityPending) {
+        mRenderer->signalTimeDiscontinuity();
+        mTimeDiscontinuityPending = false;
+    }
 
     if (mAudioDecoder != NULL) {
         mAudioDecoder->signalResume();
@@ -663,10 +682,15 @@
                 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
 
                 bool formatChange =
-                    type == ATSParser::DISCONTINUITY_FORMATCHANGE;
+                    (audio &&
+                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
+                    || (!audio &&
+                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
 
-                LOGV("%s discontinuity (formatChange=%d)",
-                     audio ? "audio" : "video", formatChange);
+                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+                LOGI("%s discontinuity (formatChange=%d, time=%d)",
+                     audio ? "audio" : "video", formatChange, timeChange);
 
                 if (audio) {
                     mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -674,26 +698,45 @@
                     mSkipRenderingVideoUntilMediaTimeUs = -1;
                 }
 
-                sp<AMessage> extra;
-                if (accessUnit->meta()->findMessage("extra", &extra)
-                        && extra != NULL) {
-                    int64_t resumeAtMediaTimeUs;
-                    if (extra->findInt64(
-                                "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
-                        LOGI("suppressing rendering of %s until %lld us",
-                                audio ? "audio" : "video", resumeAtMediaTimeUs);
+                if (timeChange) {
+                    sp<AMessage> extra;
+                    if (accessUnit->meta()->findMessage("extra", &extra)
+                            && extra != NULL) {
+                        int64_t resumeAtMediaTimeUs;
+                        if (extra->findInt64(
+                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+                            LOGI("suppressing rendering of %s until %lld us",
+                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
 
-                        if (audio) {
-                            mSkipRenderingAudioUntilMediaTimeUs =
-                                resumeAtMediaTimeUs;
-                        } else {
-                            mSkipRenderingVideoUntilMediaTimeUs =
-                                resumeAtMediaTimeUs;
+                            if (audio) {
+                                mSkipRenderingAudioUntilMediaTimeUs =
+                                    resumeAtMediaTimeUs;
+                            } else {
+                                mSkipRenderingVideoUntilMediaTimeUs =
+                                    resumeAtMediaTimeUs;
+                            }
                         }
                     }
                 }
 
-                flushDecoder(audio, formatChange);
+                mTimeDiscontinuityPending =
+                    mTimeDiscontinuityPending || timeChange;
+
+                if (formatChange || timeChange) {
+                    flushDecoder(audio, formatChange);
+                } else {
+                    // This stream is unaffected by the discontinuity
+
+                    if (audio) {
+                        mFlushingAudio = FLUSHED;
+                    } else {
+                        mFlushingVideo = FLUSHED;
+                    }
+
+                    finishFlushIfPossible();
+
+                    return -EWOULDBLOCK;
+                }
             }
 
             reply->setInt32("err", err);
@@ -794,6 +837,11 @@
 }
 
 void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
+        LOGI("flushDecoder %s without decoder present",
+             audio ? "audio" : "video");
+    }
+
     // Make sure we don't continue to scan sources until we finish flushing.
     ++mScanSourcesGeneration;
     mScanSourcesPending = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index f23deea..ffc710e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -112,6 +112,10 @@
         SHUT_DOWN,
     };
 
+    // Once the current flush is complete this indicates whether the
+    // notion of time has changed.
+    bool mTimeDiscontinuityPending;
+
     FlushStatus mFlushingAudio;
     FlushStatus mFlushingVideo;
     bool mResetInProgress;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 640e9fa..0cb7f45 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -628,11 +628,16 @@
         mAudioSink->pause();
     }
 
+    LOGV("now paused audio queue has %d entries, video has %d entries",
+         mAudioQueue.size(), mVideoQueue.size());
+
     mPaused = true;
 }
 
 void NuPlayer::Renderer::onResume() {
-    CHECK(mPaused);
+    if (!mPaused) {
+        return;
+    }
 
     if (mHasAudio) {
         mAudioSink->start();
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e72adc4..a3f2bf6 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -38,7 +38,8 @@
       mFlags(0),
       mState(DISCONNECTED),
       mFinalResult(OK),
-      mDisconnectReplyID(0) {
+      mDisconnectReplyID(0),
+      mSeekGeneration(0) {
     if (headers) {
         mExtraHeaders = *headers;
 
@@ -146,14 +147,21 @@
 }
 
 status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
+    sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
+    msg->setInt32("generation", ++mSeekGeneration);
+    msg->setInt64("timeUs", seekTimeUs);
+    msg->post(200000ll);
+
+    return OK;
+}
+
+void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
     if (mState != CONNECTED) {
-        return UNKNOWN_ERROR;
+        return;
     }
 
     mState = SEEKING;
     mHandler->seek(seekTimeUs);
-
-    return OK;
 }
 
 bool NuPlayer::RTSPSource::isSeekable() {
@@ -168,6 +176,20 @@
         mDisconnectReplyID = replyID;
         finishDisconnectIfPossible();
         return;
+    } else if (msg->what() == kWhatPerformSeek) {
+        int32_t generation;
+        CHECK(msg->findInt32("generation", &generation));
+
+        if (generation != mSeekGeneration) {
+            // obsolete.
+            return;
+        }
+
+        int64_t seekTimeUs;
+        CHECK(msg->findInt64("timeUs", &seekTimeUs));
+
+        performSeek(seekTimeUs);
+        return;
     }
 
     CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -208,21 +230,32 @@
                 break;
             }
 
-            const TrackInfo &info = mTracks.editItemAt(trackIndex);
-            sp<AnotherPacketSource> source = info.mSource;
+            TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+            sp<AnotherPacketSource> source = info->mSource;
             if (source != NULL) {
-#if 1
                 uint32_t rtpTime;
                 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
 
+                if (!info->mNPTMappingValid) {
+                    // This is a live stream, we didn't receive any normal
+                    // playtime mapping. Assume the first packets correspond
+                    // to time 0.
+
+                    LOGV("This is a live stream, assuming time = 0");
+
+                    info->mRTPTime = rtpTime;
+                    info->mNormalPlaytimeUs = 0ll;
+                    info->mNPTMappingValid = true;
+                }
+
                 int64_t nptUs =
-                    ((double)rtpTime - (double)info.mRTPTime)
-                        / info.mTimeScale
+                    ((double)rtpTime - (double)info->mRTPTime)
+                        / info->mTimeScale
                         * 1000000ll
-                        + info.mNormalPlaytimeUs;
+                        + info->mNormalPlaytimeUs;
 
                 accessUnit->meta()->setInt64("timeUs", nptUs);
-#endif
 
                 source->queueAccessUnit(accessUnit);
             }
@@ -278,6 +311,7 @@
             TrackInfo *info = &mTracks.editItemAt(trackIndex);
             info->mRTPTime = rtpTime;
             info->mNormalPlaytimeUs = nptUs;
+            info->mNPTMappingValid = true;
             break;
         }
 
@@ -305,6 +339,7 @@
         info.mTimeScale = timeScale;
         info.mRTPTime = 0;
         info.mNormalPlaytimeUs = 0ll;
+        info.mNPTMappingValid = false;
 
         if ((isAudio && mAudioTrack == NULL)
                 || (isVideo && mVideoTrack == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 66eab72..59d06ad 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -56,6 +56,7 @@
     enum {
         kWhatNotify          = 'noti',
         kWhatDisconnect      = 'disc',
+        kWhatPerformSeek     = 'seek',
     };
 
     enum State {
@@ -76,6 +77,7 @@
         int32_t mTimeScale;
         uint32_t mRTPTime;
         int64_t mNormalPlaytimeUs;
+        bool mNPTMappingValid;
     };
 
     AString mURL;
@@ -95,12 +97,16 @@
     sp<AnotherPacketSource> mAudioTrack;
     sp<AnotherPacketSource> mVideoTrack;
 
+    int32_t mSeekGeneration;
+
     sp<AnotherPacketSource> getSource(bool audio);
 
     void onConnected();
     void onDisconnected(const sp<AMessage> &msg);
     void finishDisconnectIfPossible();
 
+    void performSeek(int64_t seekTimeUs);
+
     DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index f795654..2e63b3b 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -63,17 +63,22 @@
             mFinalResult = ERROR_END_OF_STREAM;
             break;
         } else if (n == INFO_DISCONTINUITY) {
-            ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
+            int32_t type = ATSParser::DISCONTINUITY_SEEK;
 
-            int32_t formatChange;
+            int32_t mask;
             if (extra != NULL
                     && extra->findInt32(
-                        IStreamListener::kKeyFormatChange, &formatChange)
-                    && formatChange != 0) {
-                type = ATSParser::DISCONTINUITY_FORMATCHANGE;
+                        IStreamListener::kKeyDiscontinuityMask, &mask)) {
+                if (mask == 0) {
+                    LOGE("Client specified an illegal discontinuity type.");
+                    return ERROR_UNSUPPORTED;
+                }
+
+                type = mask;
             }
 
-            mTSParser->signalDiscontinuity(type, extra);
+            mTSParser->signalDiscontinuity(
+                    (ATSParser::DiscontinuityType)type, extra);
         } else if (n < 0) {
             CHECK_EQ(n, -EWOULDBLOCK);
             break;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d947760..dbc9b7e 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -342,6 +342,7 @@
 }
 
 void ACodec::signalFlush() {
+    LOGV("[%s] signalFlush", mComponentName.c_str());
     (new AMessage(kWhatFlush, id()))->post();
 }
 
@@ -1092,6 +1093,20 @@
     return OK;
 }
 
+size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
+    size_t n = 0;
+
+    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+
+        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
+            ++n;
+        }
+    }
+
+    return n;
+}
+
 bool ACodec::allYourBuffersAreBelongToUs(
         OMX_U32 portIndex) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
@@ -2041,6 +2056,14 @@
 
         case kWhatFlush:
         {
+            LOGV("[%s] ExecutingState flushing now "
+                 "(codec owns %d/%d input, %d/%d output).",
+                    mCodec->mComponentName.c_str(),
+                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
+                    mCodec->mBuffers[kPortIndexInput].size(),
+                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
+                    mCodec->mBuffers[kPortIndexOutput].size());
+
             mActive = false;
 
             CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2180,6 +2203,12 @@
                          err);
 
                     mCodec->signalError();
+
+                    // This is technically not correct, since we were unable
+                    // to allocate output buffers and therefore the output port
+                    // remains disabled. It is necessary however to allow us
+                    // to shutdown the codec properly.
+                    mCodec->changeState(mCodec->mExecutingState);
                 }
 
                 return true;
@@ -2408,6 +2437,9 @@
 
 bool ACodec::FlushingState::onOMXEvent(
         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+    LOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
+            mCodec->mComponentName.c_str(), event, data1);
+
     switch (event) {
         case OMX_EventCmdComplete:
         {
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
index 0be2ca4..815f987 100644
--- a/media/libstagefright/AVIExtractor.cpp
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -1094,7 +1094,7 @@
     CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
 
     track->mMeta->setInt32(kKeyWidth, width);
-    track->mMeta->setInt32(kKeyHeight, width);
+    track->mMeta->setInt32(kKeyHeight, height);
     track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
 
     return OK;
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 0aeb515..690deac 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -9,7 +9,6 @@
         AACWriter.cpp                     \
         AMRExtractor.cpp                  \
         AMRWriter.cpp                     \
-        AVIExtractor.cpp                  \
         AudioPlayer.cpp                   \
         AudioSource.cpp                   \
         AwesomePlayer.cpp                 \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f6d054d..ba6ff10 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -335,11 +335,13 @@
         return UNKNOWN_ERROR;
     }
 
-    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
-    if (mDecryptHandle != NULL) {
-        CHECK(mDrmManagerClient);
-        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
+    if (extractor->getDrmFlag()) {
+        dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+        if (mDecryptHandle != NULL) {
+            CHECK(mDrmManagerClient);
+            if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
+            }
         }
     }
 
@@ -1949,6 +1951,8 @@
         mUri = newURI;
     }
 
+    AString sniffedMIME;
+
     if (!strncasecmp("http://", mUri.string(), 7)
             || !strncasecmp("https://", mUri.string(), 8)
             || isWidevineStreaming) {
@@ -1998,7 +2002,6 @@
 
         mConnectingDataSource.clear();
 
-
         String8 contentType = dataSource->getMIMEType();
 
         if (strncasecmp(contentType.string(), "audio/", 6)) {
@@ -2020,16 +2023,51 @@
 
                 mLock.unlock();
 
+                // Initially make sure we have at least 192 KB for the sniff
+                // to complete without blocking.
+                static const size_t kMinBytesForSniffing = 192 * 1024;
+
+                off64_t metaDataSize = -1ll;
                 for (;;) {
                     status_t finalStatus;
                     size_t cachedDataRemaining =
                         mCachedSource->approxDataRemaining(&finalStatus);
 
-                    if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+                    if (finalStatus != OK
+                            || (metaDataSize >= 0
+                                && cachedDataRemaining >= metaDataSize)
                             || (mFlags & PREPARE_CANCELLED)) {
                         break;
                     }
 
+                    LOGV("now cached %d bytes of data", cachedDataRemaining);
+
+                    if (metaDataSize < 0
+                            && cachedDataRemaining >= kMinBytesForSniffing) {
+                        String8 tmp;
+                        float confidence;
+                        sp<AMessage> meta;
+                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
+                            mLock.lock();
+                            return UNKNOWN_ERROR;
+                        }
+
+                        // We successfully identified the file's extractor to
+                        // be, remember this mime type so we don't have to
+                        // sniff it again when we call MediaExtractor::Create()
+                        // below.
+                        sniffedMIME = tmp.string();
+
+                        if (meta == NULL
+                                || !meta->findInt64(
+                                    "meta-data-size", &metaDataSize)) {
+                            metaDataSize = kHighWaterMarkBytes;
+                        }
+
+                        CHECK_GE(metaDataSize, 0ll);
+                        LOGV("metaDataSize = %lld bytes", metaDataSize);
+                    }
+
                     usleep(200000);
                 }
 
@@ -2055,7 +2093,7 @@
         String8 mimeType;
         float confidence;
         sp<AMessage> dummy;
-        bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
+        bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
 
         if (!success
                 || strcasecmp(
@@ -2063,23 +2101,29 @@
             return ERROR_UNSUPPORTED;
         }
 
+        dataSource->DrmInitialization();
+
         mWVMExtractor = new WVMExtractor(dataSource);
         mWVMExtractor->setAdaptiveStreamingMode(true);
+        mWVMExtractor->setDrmFlag(true);
         extractor = mWVMExtractor;
     } else {
-        extractor = MediaExtractor::Create(dataSource);
+        extractor = MediaExtractor::Create(
+                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
 
         if (extractor == NULL) {
             return UNKNOWN_ERROR;
         }
     }
 
-    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+    if (extractor->getDrmFlag()) {
+        dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
 
-    if (mDecryptHandle != NULL) {
-        CHECK(mDrmManagerClient);
-        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
+        if (mDecryptHandle != NULL) {
+            CHECK(mDrmManagerClient);
+            if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
+            }
         }
     }
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 256f3ba..57989c5 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -33,6 +33,8 @@
 
 namespace android {
 
+static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
+
 struct CameraSourceListener : public CameraListener {
     CameraSourceListener(const sp<CameraSource> &source);
 
@@ -156,6 +158,7 @@
       mLastFrameTimestampUs(0),
       mStarted(false),
       mNumFramesEncoded(0),
+      mTimeBetweenFrameCaptureUs(0),
       mFirstFrameTimeUs(0),
       mNumFramesDropped(0),
       mNumGlitches(0),
@@ -644,7 +647,8 @@
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
         if (NO_ERROR !=
-            mFrameCompleteCondition.waitRelative(mLock, 3000000000LL)) {
+            mFrameCompleteCondition.waitRelative(mLock,
+                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
             LOGW("Timed out waiting for outstanding frames being encoded: %d",
                 mFramesBeingEncoded.size());
         }
@@ -736,7 +740,8 @@
         Mutex::Autolock autoLock(mLock);
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
-                mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+                mFrameAvailableCondition.waitRelative(mLock,
+                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
                 if (mCameraRecordingProxy != 0 &&
                     !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
                     LOGW("camera recording proxy is gone");
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index e4de20a..eb456f4 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,12 +39,12 @@
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
-        int64_t timeBetweenTimeLapseFrameCaptureUs) {
+        int64_t timeBetweenFrameCaptureUs) {
 
     CameraSourceTimeLapse *source = new
             CameraSourceTimeLapse(camera, proxy, cameraId,
                 videoSize, videoFrameRate, surface,
-                timeBetweenTimeLapseFrameCaptureUs);
+                timeBetweenFrameCaptureUs);
 
     if (source != NULL) {
         if (source->initCheck() != OK) {
@@ -62,15 +62,15 @@
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
-        int64_t timeBetweenTimeLapseFrameCaptureUs)
+        int64_t timeBetweenFrameCaptureUs)
     : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
-      mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
       mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
       mLastTimeLapseFrameRealTimestampUs(0),
       mSkipCurrentFrame(false) {
 
+    mTimeBetweenFrameCaptureUs = timeBetweenFrameCaptureUs;
     LOGD("starting time lapse mode: %lld us",
-        mTimeBetweenTimeLapseFrameCaptureUs);
+        mTimeBetweenFrameCaptureUs);
 
     mVideoWidth = videoSize.width;
     mVideoHeight = videoSize.height;
@@ -271,14 +271,14 @@
     // 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)) {
+        (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
         // Skip all frames from last encoded frame until
-        // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+        // sufficient time (mTimeBetweenFrameCaptureUs) 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:
+        // Desired frame has arrived after mTimeBetweenFrameCaptureUs 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.
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 1f3d581..afc4a80 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -282,13 +282,13 @@
     if (decryptHandle != NULL) {
         if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
             *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
+            *confidence = 10.0f;
         } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
             *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
-        } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) {
-            *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
-            LOGW("SniffWVM: found match\n");
+            *confidence = 10.0f;
+        } else {
+            return false;
         }
-        *confidence = 10.0f;
 
         return true;
     }
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 70523c1..6134344 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "include/AMRExtractor.h"
-#include "include/AVIExtractor.h"
 #include "include/MP3Extractor.h"
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
@@ -27,6 +26,7 @@
 #include "include/DRMExtractor.h"
 #include "include/FLACExtractor.h"
 #include "include/AACExtractor.h"
+#include "include/WVMExtractor.h"
 
 #include "matroska/MatroskaExtractor.h"
 
@@ -113,8 +113,8 @@
     RegisterSniffer(SniffMPEG2TS);
     RegisterSniffer(SniffMP3);
     RegisterSniffer(SniffAAC);
-    RegisterSniffer(SniffAVI);
     RegisterSniffer(SniffMPEG2PS);
+    RegisterSniffer(SniffWVM);
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 1ebf0a8..f6b06c7 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -2301,51 +2302,121 @@
 
 // Attempt to actually parse the 'ftyp' atom and determine if a suitable
 // compatible brand is present.
+// Also try to identify where this file's metadata ends
+// (end of the 'moov' atom) and report it to the caller as part of
+// the metadata.
 static bool BetterSniffMPEG4(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
-    uint8_t header[12];
-    if (source->readAt(0, header, 12) != 12
-            || memcmp("ftyp", &header[4], 4)) {
-        return false;
-    }
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *meta) {
+    // We scan up to 128 bytes to identify this file as an MP4.
+    static const off64_t kMaxScanOffset = 128ll;
 
-    size_t atomSize = U32_AT(&header[0]);
-    if (atomSize < 16 || (atomSize % 4) != 0) {
-        return false;
-    }
+    off64_t offset = 0ll;
+    bool foundGoodFileType = false;
+    off64_t moovAtomEndOffset = -1ll;
+    bool done = false;
 
-    bool success = false;
-    if (isCompatibleBrand(U32_AT(&header[8]))) {
-        success = true;
-    } else {
-        size_t numCompatibleBrands = (atomSize - 16) / 4;
-        for (size_t i = 0; i < numCompatibleBrands; ++i) {
-            uint8_t tmp[4];
-            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
+    while (!done && offset < kMaxScanOffset) {
+        uint32_t hdr[2];
+        if (source->readAt(offset, hdr, 8) < 8) {
+            return false;
+        }
+
+        uint64_t chunkSize = ntohl(hdr[0]);
+        uint32_t chunkType = ntohl(hdr[1]);
+        off64_t chunkDataOffset = offset + 8;
+
+        if (chunkSize == 1) {
+            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
                 return false;
             }
 
-            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
-                success = true;
+            chunkSize = ntoh64(chunkSize);
+            chunkDataOffset += 8;
+
+            if (chunkSize < 16) {
+                // The smallest valid chunk is 16 bytes long in this case.
+                return false;
+            }
+        } else if (chunkSize < 8) {
+            // The smallest valid chunk is 8 bytes long.
+            return false;
+        }
+
+        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+
+        switch (chunkType) {
+            case FOURCC('f', 't', 'y', 'p'):
+            {
+                if (chunkDataSize < 8) {
+                    return false;
+                }
+
+                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
+                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
+                    if (i == 1) {
+                        // Skip this index, it refers to the minorVersion,
+                        // not a brand.
+                        continue;
+                    }
+
+                    uint32_t brand;
+                    if (source->readAt(
+                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
+                        return false;
+                    }
+
+                    brand = ntohl(brand);
+
+                    if (isCompatibleBrand(brand)) {
+                        foundGoodFileType = true;
+                        break;
+                    }
+                }
+
+                if (!foundGoodFileType) {
+                    return false;
+                }
+
                 break;
             }
+
+            case FOURCC('m', 'o', 'o', 'v'):
+            {
+                moovAtomEndOffset = offset + chunkSize;
+
+                done = true;
+                break;
+            }
+
+            default:
+                break;
         }
+
+        offset += chunkSize;
     }
 
-    if (!success) {
+    if (!foundGoodFileType) {
         return false;
     }
 
     *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
     *confidence = 0.4f;
 
+    if (moovAtomEndOffset >= 0) {
+        *meta = new AMessage;
+        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
+
+        LOGV("found metadata size: %lld", moovAtomEndOffset);
+    }
+
     return true;
 }
 
 bool SniffMPEG4(
         const sp<DataSource> &source, String8 *mimeType, float *confidence,
-        sp<AMessage> *) {
-    if (BetterSniffMPEG4(source, mimeType, confidence)) {
+        sp<AMessage> *meta) {
+    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
         return true;
     }
 
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 2221268..9eee6aa 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -19,7 +19,6 @@
 #include <utils/Log.h>
 
 #include "include/AMRExtractor.h"
-#include "include/AVIExtractor.h"
 #include "include/MP3Extractor.h"
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
@@ -110,10 +109,11 @@
         ret = new MatroskaExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
         ret = new MPEG2TSExtractor(source);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_AVI)) {
-        ret = new AVIExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) {
         ret = new WVMExtractor(source);
+        if (ret != NULL) {
+            isDrm = true;
+        }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
         ret = new AACExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index dfd3f4a..86b3fe4 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -520,6 +520,85 @@
     return NULL;
 }
 
+status_t OMXCodec::parseAVCCodecSpecificData(
+        const void *data, size_t size,
+        unsigned *profile, unsigned *level) {
+    const uint8_t *ptr = (const uint8_t *)data;
+
+    // verify minimum size and configurationVersion == 1.
+    if (size < 7 || ptr[0] != 1) {
+        return ERROR_MALFORMED;
+    }
+
+    *profile = ptr[1];
+    *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) {
+        if (size < 2) {
+            return ERROR_MALFORMED;
+        }
+
+        size_t length = U16_AT(ptr);
+
+        ptr += 2;
+        size -= 2;
+
+        if (size < length) {
+            return ERROR_MALFORMED;
+        }
+
+        addCodecSpecificData(ptr, length);
+
+        ptr += length;
+        size -= length;
+    }
+
+    if (size < 1) {
+        return ERROR_MALFORMED;
+    }
+
+    size_t numPictureParameterSets = *ptr;
+    ++ptr;
+    --size;
+
+    for (size_t i = 0; i < numPictureParameterSets; ++i) {
+        if (size < 2) {
+            return ERROR_MALFORMED;
+        }
+
+        size_t length = U16_AT(ptr);
+
+        ptr += 2;
+        size -= 2;
+
+        if (size < length) {
+            return ERROR_MALFORMED;
+        }
+
+        addCodecSpecificData(ptr, length);
+
+        ptr += length;
+        size -= length;
+    }
+
+    return OK;
+}
+
 status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
     LOGV("configureCodec protected=%d",
          (mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
@@ -542,66 +621,17 @@
         } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
             // Parse the AVCDecoderConfigurationRecord
 
-            const uint8_t *ptr = (const uint8_t *)data;
-
-            CHECK(size >= 7);
-            CHECK_EQ((unsigned)ptr[0], 1u);  // 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;
+            unsigned profile, level;
+            status_t err;
+            if ((err = parseAVCCodecSpecificData(
+                            data, size, &profile, &level)) != OK) {
+                LOGE("Malformed AVC codec specific data.");
+                return err;
             }
 
             CODEC_LOGI(
-                    "AVC profile = %d (%s), level = %d",
-                    (int)profile, AVCProfileToString(profile), level);
+                    "AVC profile = %u (%s), level = %u",
+                    profile, AVCProfileToString(profile), level);
 
             if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
                 && (profile != kAVCProfileBaseline || level > 30)) {
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index ebad321..bf31947 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -627,18 +627,19 @@
 
         ++left;
     }
+
+    if (left == mNumSyncSamples) {
+        if (flags == kFlagAfter) {
+            LOGE("tried to find a sync frame after the last one: %d", left);
+            return ERROR_OUT_OF_RANGE;
+        }
+    }
+
     if (left > 0) {
         --left;
     }
 
-    uint32_t x;
-    if (mDataSource->readAt(
-                mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
-        return ERROR_IO;
-    }
-
-    x = ntohl(x);
-    --x;
+    uint32_t x = mSyncSamples[left];
 
     if (left + 1 < mNumSyncSamples) {
         uint32_t y = mSyncSamples[left + 1];
@@ -679,13 +680,7 @@
             if (x > start_sample_index) {
                 CHECK(left > 0);
 
-                if (mDataSource->readAt(
-                            mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
-                    return ERROR_IO;
-                }
-
-                x = ntohl(x);
-                --x;
+                x = mSyncSamples[left - 1];
 
                 CHECK(x <= start_sample_index);
             }
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index bb6e4cd..2505096 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -94,7 +94,7 @@
     char buffer[20];
     sprintf(buffer, "%ld", temp);
     status_t status = client->addStringTag("duration", buffer);
-    if (status) {
+    if (status != OK) {
         return MEDIA_SCAN_RESULT_ERROR;
     }
     return MEDIA_SCAN_RESULT_OK;
@@ -178,7 +178,7 @@
         const char *value;
         if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
             status = client.addStringTag(kKeyMap[i].tag, value);
-            if (status) {
+            if (status != OK) {
                 return MEDIA_SCAN_RESULT_ERROR;
             }
         }
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 2b27ee2..86b33d1 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -336,7 +336,7 @@
         (uint32_t(buffer->height) != h) ||
         (uint32_t(buffer->format) != format) ||
         ((uint32_t(buffer->usage) & usage) != usage)) {
-            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+            usage |= GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
             status_t error;
             sp<GraphicBuffer> graphicBuffer(
                     mGraphicBufferAlloc->createGraphicBuffer(
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 26eda0c..79dedca 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -45,17 +45,12 @@
 static Mutex gWVMutex;
 
 WVMExtractor::WVMExtractor(const sp<DataSource> &source)
-    : mDataSource(source) {
-    {
-        Mutex::Autolock autoLock(gWVMutex);
-        if (gVendorLibHandle == NULL) {
-            gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
-        }
+    : mDataSource(source)
+{
+    Mutex::Autolock autoLock(gWVMutex);
 
-        if (gVendorLibHandle == NULL) {
-            LOGE("Failed to open libwvm.so");
-            return;
-        }
+    if (!getVendorLibHandle()) {
+        return;
     }
 
     typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
@@ -71,6 +66,19 @@
     }
 }
 
+bool WVMExtractor::getVendorLibHandle()
+{
+    if (gVendorLibHandle == NULL) {
+        gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+    }
+
+    if (gVendorLibHandle == NULL) {
+        LOGE("Failed to open libwvm.so");
+    }
+
+    return gVendorLibHandle != NULL;
+}
+
 WVMExtractor::~WVMExtractor() {
 }
 
@@ -113,5 +121,33 @@
     }
 }
 
+bool SniffWVM(
+    const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *) {
+
+    Mutex::Autolock autoLock(gWVMutex);
+
+    if (!WVMExtractor::getVendorLibHandle()) {
+        return false;
+    }
+
+    typedef WVMLoadableExtractor *(*SnifferFunc)(sp<DataSource>);
+    SnifferFunc snifferFunc =
+        (SnifferFunc) dlsym(gVendorLibHandle,
+                            "_ZN7android15IsWidevineMediaENS_2spINS_10DataSourceEEE");
+
+    if (snifferFunc) {
+        if ((*snifferFunc)(source)) {
+            *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
+            *confidence = 10.0f;
+            return true;
+        }
+    } else {
+        LOGE("IsWidevineMedia not found in libwvm.so");
+    }
+
+    return false;
+}
+
 } //namespace android
 
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index f07dd4f..5499c32 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -79,7 +79,13 @@
 }
 
 void ABitReader::putBits(uint32_t x, size_t n) {
-    CHECK_LE(mNumBitsLeft + n, 32u);
+    CHECK_LE(n, 32u);
+
+    while (mNumBitsLeft + n > 32) {
+        mNumBitsLeft -= 8;
+        --mData;
+        ++mSize;
+    }
 
     mReservoir = (mReservoir >> n) | (x << (32 - n));
     mNumBitsLeft += n;
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index deecd25..9f763f9 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -23,6 +23,8 @@
 
 namespace android {
 
+struct AMessage;
+class String8;
 class DataSource;
 
 class WVMLoadableExtractor : public MediaExtractor {
@@ -58,6 +60,8 @@
     // is used.
     void setAdaptiveStreamingMode(bool adaptive);
 
+    static bool getVendorLibHandle();
+
 protected:
     virtual ~WVMExtractor();
 
@@ -69,6 +73,10 @@
     WVMExtractor &operator=(const WVMExtractor &);
 };
 
+bool SniffWVM(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *);
+
 }  // namespace android
 
 #endif  // DRM_EXTRACTOR_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72f1282..6cec63a 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -123,6 +123,9 @@
 
     void extractAACFrames(const sp<ABuffer> &buffer);
 
+    bool isAudio() const;
+    bool isVideo() const;
+
     DISALLOW_EVIL_CONSTRUCTORS(Stream);
 };
 
@@ -401,7 +404,7 @@
         case STREAMTYPE_H264:
             mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::H264);
             break;
-        case STREAMTYPE_MPEG2_AUDIO_ATDS:
+        case STREAMTYPE_MPEG2_AUDIO_ADTS:
             mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
             break;
         case STREAMTYPE_MPEG1_AUDIO:
@@ -486,6 +489,31 @@
     return OK;
 }
 
+bool ATSParser::Stream::isVideo() const {
+    switch (mStreamType) {
+        case STREAMTYPE_H264:
+        case STREAMTYPE_MPEG1_VIDEO:
+        case STREAMTYPE_MPEG2_VIDEO:
+        case STREAMTYPE_MPEG4_VIDEO:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool ATSParser::Stream::isAudio() const {
+    switch (mStreamType) {
+        case STREAMTYPE_MPEG1_AUDIO:
+        case STREAMTYPE_MPEG2_AUDIO:
+        case STREAMTYPE_MPEG2_AUDIO_ADTS:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
 void ATSParser::Stream::signalDiscontinuity(
         DiscontinuityType type, const sp<AMessage> &extra) {
     if (mQueue == NULL) {
@@ -495,34 +523,34 @@
     mPayloadStarted = false;
     mBuffer->setRange(0, 0);
 
-    switch (type) {
-        case DISCONTINUITY_SEEK:
-        case DISCONTINUITY_FORMATCHANGE:
-        {
-            bool isASeek = (type == DISCONTINUITY_SEEK);
-
-            mQueue->clear(!isASeek);
-
-            uint64_t resumeAtPTS;
-            if (extra != NULL
-                    && extra->findInt64(
-                        IStreamListener::kKeyResumeAtPTS,
-                        (int64_t *)&resumeAtPTS)) {
-                int64_t resumeAtMediaTimeUs =
-                    mProgram->convertPTSToTimestamp(resumeAtPTS);
-
-                extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
-            }
-
-            if (mSource != NULL) {
-                mSource->queueDiscontinuity(type, extra);
-            }
-            break;
+    bool clearFormat = false;
+    if (isAudio()) {
+        if (type & DISCONTINUITY_AUDIO_FORMAT) {
+            clearFormat = true;
         }
+    } else {
+        if (type & DISCONTINUITY_VIDEO_FORMAT) {
+            clearFormat = true;
+        }
+    }
 
-        default:
-            TRESPASS();
-            break;
+    mQueue->clear(clearFormat);
+
+    if (type & DISCONTINUITY_TIME) {
+        uint64_t resumeAtPTS;
+        if (extra != NULL
+                && extra->findInt64(
+                    IStreamListener::kKeyResumeAtPTS,
+                    (int64_t *)&resumeAtPTS)) {
+            int64_t resumeAtMediaTimeUs =
+                mProgram->convertPTSToTimestamp(resumeAtPTS);
+
+            extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+        }
+    }
+
+    if (mSource != NULL) {
+        mSource->queueDiscontinuity(type, extra);
     }
 }
 
@@ -764,10 +792,7 @@
     switch (type) {
         case VIDEO:
         {
-            if (mStreamType == STREAMTYPE_H264
-                    || mStreamType == STREAMTYPE_MPEG1_VIDEO
-                    || mStreamType == STREAMTYPE_MPEG2_VIDEO
-                    || mStreamType == STREAMTYPE_MPEG4_VIDEO) {
+            if (isVideo()) {
                 return mSource;
             }
             break;
@@ -775,9 +800,7 @@
 
         case AUDIO:
         {
-            if (mStreamType == STREAMTYPE_MPEG1_AUDIO
-                    || mStreamType == STREAMTYPE_MPEG2_AUDIO
-                    || mStreamType == STREAMTYPE_MPEG2_AUDIO_ATDS) {
+            if (isAudio()) {
                 return mSource;
             }
             break;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 878e534..c8038d1 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -33,9 +33,18 @@
 
 struct ATSParser : public RefBase {
     enum DiscontinuityType {
-        DISCONTINUITY_NONE,
-        DISCONTINUITY_SEEK,
-        DISCONTINUITY_FORMATCHANGE
+        DISCONTINUITY_NONE              = 0,
+        DISCONTINUITY_TIME              = 1,
+        DISCONTINUITY_AUDIO_FORMAT      = 2,
+        DISCONTINUITY_VIDEO_FORMAT      = 4,
+
+        DISCONTINUITY_SEEK              = DISCONTINUITY_TIME,
+
+        // For legacy reasons this also implies a time discontinuity.
+        DISCONTINUITY_FORMATCHANGE      =
+            DISCONTINUITY_AUDIO_FORMAT
+                | DISCONTINUITY_VIDEO_FORMAT
+                | DISCONTINUITY_TIME,
     };
 
     enum Flags {
@@ -71,7 +80,7 @@
         STREAMTYPE_MPEG2_VIDEO          = 0x02,
         STREAMTYPE_MPEG1_AUDIO          = 0x03,
         STREAMTYPE_MPEG2_AUDIO          = 0x04,
-        STREAMTYPE_MPEG2_AUDIO_ATDS     = 0x0f,
+        STREAMTYPE_MPEG2_AUDIO_ADTS     = 0x0f,
         STREAMTYPE_MPEG4_VIDEO          = 0x10,
         STREAMTYPE_H264                 = 0x1b,
     };
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index ce07e32..f782ce5 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -29,8 +29,17 @@
 namespace android {
 
 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
-    : mFormat(meta),
+    : mIsAudio(false),
+      mFormat(meta),
       mEOSResult(OK) {
+    const char *mime;
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+    if (!strncasecmp("audio/", mime, 6)) {
+        mIsAudio = true;
+    } else {
+        CHECK(!strncasecmp("video/", mime, 6));
+    }
 }
 
 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
@@ -67,8 +76,7 @@
 
         int32_t discontinuity;
         if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
-
-            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+            if (wasFormatChange(discontinuity)) {
                 mFormat.clear();
             }
 
@@ -96,7 +104,7 @@
 
         int32_t discontinuity;
         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
-            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+            if (wasFormatChange(discontinuity)) {
                 mFormat.clear();
             }
 
@@ -117,6 +125,15 @@
     return mEOSResult;
 }
 
+bool AnotherPacketSource::wasFormatChange(
+        int32_t discontinuityType) const {
+    if (mIsAudio) {
+        return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
+    }
+
+    return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
+}
+
 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
     int32_t damaged;
     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 439c7853..c99f7f2 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -61,10 +61,13 @@
     Mutex mLock;
     Condition mCondition;
 
+    bool mIsAudio;
     sp<MetaData> mFormat;
     List<sp<ABuffer> > mBuffers;
     status_t mEOSResult;
 
+    bool wasFormatChange(int32_t discontinuityType) const;
+
     DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
 };
 
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index f55be6e..a089dbf 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -543,7 +543,7 @@
         case ATSParser::STREAMTYPE_H264:
             mode = ElementaryStreamQueue::H264;
             break;
-        case ATSParser::STREAMTYPE_MPEG2_AUDIO_ATDS:
+        case ATSParser::STREAMTYPE_MPEG2_AUDIO_ADTS:
             mode = ElementaryStreamQueue::AAC;
             break;
         case ATSParser::STREAMTYPE_MPEG1_AUDIO:
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 794c60b..5a95f9c 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1100,6 +1100,8 @@
         float npt1, npt2;
         if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
+
+            LOGI("This is a live stream");
             return;
         }
 
@@ -1386,12 +1388,14 @@
             msg->setInt32("what", kWhatConnected);
             msg->post();
 
-            for (size_t i = 0; i < mTracks.size(); ++i) {
-                TrackInfo *info = &mTracks.editItemAt(i);
+            if (mSeekable) {
+                for (size_t i = 0; i < mTracks.size(); ++i) {
+                    TrackInfo *info = &mTracks.editItemAt(i);
 
-                postNormalPlayTimeMapping(
-                        i,
-                        info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+                    postNormalPlayTimeMapping(
+                            i,
+                            info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+                }
             }
 
             mFirstAccessUnit = false;
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 20225ba..cfea7e8 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -25,10 +25,12 @@
 #include "MtpDataPacket.h"
 #include "MtpStringBuffer.h"
 
+#define MTP_BUFFER_SIZE 16384
+
 namespace android {
 
 MtpDataPacket::MtpDataPacket()
-    :   MtpPacket(16384),   // MAX_USBFS_BUFFER_SIZE
+    :   MtpPacket(MTP_BUFFER_SIZE),   // MAX_USBFS_BUFFER_SIZE
         mOffset(MTP_CONTAINER_HEADER_SIZE)
 {
 }
@@ -345,7 +347,7 @@
 
 #ifdef MTP_DEVICE 
 int MtpDataPacket::read(int fd) {
-    int ret = ::read(fd, mBuffer, mBufferSize);
+    int ret = ::read(fd, mBuffer, MTP_BUFFER_SIZE);
     if (ret < MTP_CONTAINER_HEADER_SIZE)
         return -1;
     mPacketSize = ret;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index dc6c011..1dcfb74 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -1053,11 +1053,14 @@
     int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
     if (result == MTP_RESPONSE_OK) {
         LOGV("deleting %s", (const char *)filePath);
-        deletePath((const char *)filePath);
-        return mDatabase->deleteFile(handle);
-    } else {
-        return result;
+        result = mDatabase->deleteFile(handle);
+        // Don't delete the actual files unless the database deletion is allowed
+        if (result == MTP_RESPONSE_OK) {
+            deletePath((const char *)filePath);
+        }
     }
+
+    return result;
 }
 
 MtpResponseCode MtpServer::doGetObjectPropDesc() {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 3fb2da0..92ac9eb 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -39,6 +39,7 @@
 import com.android.mediaframeworktest.functional.videoeditor.VideoEditorPreviewTest;
 import junit.framework.TestSuite;
 
+import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
 
@@ -54,6 +55,7 @@
 
 public class MediaFrameworkTestRunner extends InstrumentationTestRunner {
 
+    public static int mMinCameraFps = 0;
 
     @Override
     public TestSuite getAllTests() {
@@ -87,4 +89,16 @@
     public ClassLoader getLoader() {
         return MediaFrameworkTestRunner.class.getClassLoader();
     }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        String minCameraFps = (String) icicle.get("min_camera_fps");
+        System.out.print("min_camera_" + minCameraFps);
+
+        if (minCameraFps != null ) {
+            mMinCameraFps = Integer.parseInt(minCameraFps);
+        }
+    }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
index b5c8c8c..0684946 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
@@ -33,6 +33,7 @@
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import com.android.mediaframeworktest.MediaProfileReader;
+import com.android.mediaframeworktest.MediaFrameworkTestRunner;
 
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.Suppress;
@@ -115,9 +116,16 @@
         int audioChannels = highQuality? audioCap.mMaxChannels: audioCap.mMinChannels ;
         int audioSamplingRate = highQuality? audioCap.mMaxSampleRate: audioCap.mMinSampleRate;
 
+        //Overide the fps if the min_camera_fps is set
+        if (MediaFrameworkTestRunner.mMinCameraFps != 0 &&
+            MediaFrameworkTestRunner.mMinCameraFps > videoFps){
+            videoFps = MediaFrameworkTestRunner.mMinCameraFps;
+        }
+
         if (videoFps < MIN_VIDEO_FPS) {
             videoFps = MIN_VIDEO_FPS;
         }
+
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
         String filename = ("/sdcard/" + videoEncoder + "_" + audioEncoder + "_" + highQuality + ".3gp");
         try {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
index e848f5f..4181903 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
@@ -93,6 +93,7 @@
 
     private boolean previewStart;
     private boolean previewStop;
+    private boolean previewError;
 
     /* Minimum waiting time for Semaphore to wait for release */
     private final long minWaitingTime = 3000;
@@ -141,7 +142,9 @@
     protected void setPreviewStop() {
         previewStop = true;
     }
-
+    protected void setPreviewError() {
+        previewError = true;
+    }
     protected void validatePreviewProgress(int startMs, int endMs,
         boolean loop, long duration) throws Exception {
 
@@ -149,6 +152,7 @@
         final Semaphore blockTillPreviewCompletes = new Semaphore(1);
         previewStart = false;
         previewStop = false;
+        previewError = false;
         mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
             int i = 0;
             public void onProgress(Object item, int action, int progress) {
@@ -187,6 +191,10 @@
                     setPreviewStop();
                     blockTillPreviewCompletes.release();
                 }
+                public void onError(VideoEditor videoEditor, int error) {
+                    setPreviewError();
+                    blockTillPreviewCompletes.release();
+                }
         });
         } catch (Exception e) {
             blockTillPreviewCompletes.release();
@@ -196,6 +204,7 @@
         mVideoEditor.stopPreview();
         assertTrue("Preview Failed to start", previewStart);
         assertTrue("Preview Failed to stop", previewStop);
+        assertFalse("Preview Error occurred", previewError);
 
         blockTillPreviewCompletes.release();
     }
@@ -399,6 +408,7 @@
             "TransitionSpiral_QVGA.jpg";
         previewStart = false;
         previewStop = false;
+        previewError = false;
 
         final Semaphore blockTillPreviewCompletes = new Semaphore(1);
 
@@ -490,6 +500,10 @@
                     setPreviewStop();
                     blockTillPreviewCompletes.release();
                 }
+                public void onError(VideoEditor videoEditor, int error) {
+                    setPreviewError();
+                    blockTillPreviewCompletes.release();
+                }
         });
         } catch (Exception e) {
             blockTillPreviewCompletes.release();
@@ -499,6 +513,7 @@
         blockTillPreviewCompletes.release();
         assertTrue("Preview Failed to start", previewStart);
         assertTrue("Preview Failed to stop", previewStop);
+        assertFalse("Preview Error occurred", previewError);
 
         assertEquals("Removing Transition " + transition1And2CrossFade.getId(),
             transition1And2CrossFade,
@@ -677,6 +692,7 @@
         final Semaphore blockTillPreviewCompletes = new Semaphore(1);
         previewStart = false;
         previewStop = false;
+        previewError = false;
 
         final MediaVideoItem mediaVideoItem1 =
             mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
@@ -693,7 +709,7 @@
 
 
         blockTillPreviewCompletes.acquire();
-                    final String fileName = mVideoEditor.getPath() + "\test.3gp";
+                    final String fileName = mVideoEditor.getPath() + "/test.3gp";
                     final int height = MediaProperties.HEIGHT_480;
                     final int bitrate = MediaProperties.BITRATE_512K;
 
@@ -727,6 +743,10 @@
                     setPreviewStop();
                     blockTillPreviewCompletes.release();
                 }
+                public void onError(VideoEditor videoEditor, int error) {
+                    setPreviewError();
+                    blockTillPreviewCompletes.release();
+                }
             });
 
         } catch (Exception e) {
@@ -736,6 +756,8 @@
         mVideoEditor.stopPreview();
         assertTrue("Preview Failed to start", previewStart);
         assertTrue("Preview Failed to stop", previewStop);
+        assertFalse("Preview Error occurred", previewError);
+
         blockTillPreviewCompletes.release();
     }
 
@@ -784,6 +806,10 @@
                     setPreviewStop();
                     blockTillPreviewCompletes.release();
                 }
+                public void onError(VideoEditor videoEditor, int error) {
+                    setPreviewError();
+                    blockTillPreviewCompletes.release();
+                }
         });
 
         } catch (IllegalArgumentException e) {
@@ -1023,7 +1049,10 @@
                     }
                     public void onStop(VideoEditor videoEditor) {
                         setPreviewStop();
-                }
+                    }
+                    public void onError(VideoEditor videoEditor, int error) {
+                        setPreviewError();
+                    }
             });
         }catch (IllegalArgumentException e) {
             flagForException = true;
@@ -1089,7 +1118,10 @@
                     }
                     public void onStop(VideoEditor videoEditor) {
                         setPreviewStop();
-                }
+                    }
+                    public void onError(VideoEditor videoEditor, int error) {
+                        setPreviewError();
+                    }
             });
         }catch (IllegalArgumentException e) {
             flagForException = true;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 0b887b9..4f6e7d2 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -37,11 +37,13 @@
 import android.view.SurfaceHolder;
 
 import java.util.List;
+import java.io.BufferedReader;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.Writer;
 import java.io.File;
 import java.io.FileWriter;
@@ -68,6 +70,8 @@
     private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
     private static final String MEDIA_MEMORY_OUTPUT =
         "/sdcard/mediaMemOutput.txt";
+    private static final String MEDIA_PROCMEM_OUTPUT =
+        "/sdcard/mediaProcmemOutput.txt";
 
     private static int mStartMemory = 0;
     private static int mEndMemory = 0;
@@ -84,6 +88,9 @@
     private static int DECODER_LIMIT = 150;
     private static int CAMERA_LIMIT = 80;
 
+    private Writer mProcMemWriter;
+    private Writer mMemWriter;
+
     private static List<VideoEncoderCap> videoEncoders = MediaProfileReader.getVideoEncoders();
 
     Camera mCamera;
@@ -97,12 +104,21 @@
         getActivity();
         if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
             MediaTestUtil.getNativeHeapDump(this.getName() + "_before");
+
+        mProcMemWriter = new BufferedWriter(new FileWriter
+                (new File(MEDIA_PROCMEM_OUTPUT), true));
+        mProcMemWriter.write(this.getName() + "\n");
+        mMemWriter = new BufferedWriter(new FileWriter
+                (new File(MEDIA_MEMORY_OUTPUT), true));
+
     }
 
     protected void tearDown() throws Exception {
-        super.tearDown();
         if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
             MediaTestUtil.getNativeHeapDump(this.getName() + "_after");
+        mProcMemWriter.close();
+        mMemWriter.close();
+        super.tearDown();
     }
 
     private void initializeMessageLooper() {
@@ -247,24 +263,39 @@
     }
 
     //Write the ps output to the file
-    public void getMemoryWriteToLog(Writer output, int writeCount) {
+    public void getMemoryWriteToLog(int writeCount) {
         String memusage = null;
         try {
             if (writeCount == 0) {
                 mStartMemory = getMediaserverVsize();
-                output.write("Start memory : " + mStartMemory + "\n");
+                mMemWriter.write("Start memory : " + mStartMemory + "\n");
             }
             memusage = captureMediaserverInfo();
-            output.write(memusage);
+            mMemWriter.write(memusage);
             if (writeCount == NUM_STRESS_LOOP - 1) {
                 mEndMemory = getMediaserverVsize();
-                output.write("End Memory :" + mEndMemory + "\n");
+                mMemWriter.write("End Memory :" + mEndMemory + "\n");
             }
         } catch (Exception e) {
             e.toString();
         }
     }
 
+    public void writeProcmemInfo() throws Exception{
+        String cmd = "procmem " + getMediaserverPid();
+        Process p = Runtime.getRuntime().exec(cmd);
+
+        InputStream inStream = p.getInputStream();
+        InputStreamReader inReader = new InputStreamReader(inStream);
+        BufferedReader inBuffer = new BufferedReader(inReader);
+        String s;
+        while ((s = inBuffer.readLine()) != null) {
+              mProcMemWriter.write(s);
+              mProcMemWriter.write("\n");
+        }
+        mProcMemWriter.write("\n\n");
+    }
+
     public String captureMediaserverInfo() {
         String cm = "ps mediaserver";
         String memoryUsage = null;
@@ -306,7 +337,7 @@
         return vsizevalue;
     }
 
-    public boolean validateMemoryResult(int startPid, int startMemory, Writer output, int limit)
+    public boolean validateMemoryResult(int startPid, int startMemory, int limit)
             throws Exception {
         // Wait for 10 seconds to make sure the memory settle.
         Thread.sleep(10000);
@@ -315,11 +346,11 @@
         if (memDiff < 0) {
             memDiff = 0;
         }
-        output.write("The total diff = " + memDiff);
-        output.write("\n\n");
+        mMemWriter.write("The total diff = " + memDiff);
+        mMemWriter.write("\n\n");
         // mediaserver crash
         if (startPid != mEndPid) {
-            output.write("mediaserver died. Test failed\n");
+            mMemWriter.write("mediaserver died. Test failed\n");
             return false;
         }
         // memory leak greter than the tolerant
@@ -331,18 +362,16 @@
     @LargeTest
     public void testH263VideoPlaybackMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File h263MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(h263MemoryOut, true));
-        output.write("H263 Video Playback Only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("H263 Video Playback Only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
         assertTrue("H263 playback memory test", memoryResult);
     }
 
@@ -350,18 +379,16 @@
     @LargeTest
     public void testH264VideoPlaybackMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File h264MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(h264MemoryOut, true));
-        output.write("H264 Video Playback only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("H264 Video Playback only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
         assertTrue("H264 playback memory test", memoryResult);
     }
 
@@ -369,21 +396,19 @@
     @LargeTest
     public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File videoH263RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
-        output.write("H263 video record only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("H263 video record only\n");
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("H263 record only memory test", memoryResult);
     }
 
@@ -391,21 +416,19 @@
     @LargeTest
     public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File videoMp4RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
-        output.write("MPEG4 video record only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("MPEG4 video record only\n");
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.MPEG_4_SP);
         assertTrue("MPEG4 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("mpeg4 record only memory test", memoryResult);
     }
 
@@ -414,21 +437,19 @@
     @LargeTest
     public void testRecordVideoAudioMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File videoRecordAudioMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
+        mStartPid = getMediaserverPid();
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
-        output.write("Audio and h263 video record\n");
+        mMemWriter.write("Audio and h263 video record\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false));
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("H263 audio video record memory test", memoryResult);
     }
 
@@ -436,18 +457,16 @@
     @LargeTest
     public void testRecordAudioOnlyMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File audioOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut, true));
-        output.write("Audio record only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("Audio record only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressAudioRecord(MediaNames.RECORDER_OUTPUT);
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("audio record only memory test", memoryResult);
     }
 
@@ -455,18 +474,16 @@
     @LargeTest
     public void testCameraPreviewMemoryUsage() throws Exception {
         boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
 
-        File cameraPreviewMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(cameraPreviewMemoryOut, true));
-        output.write("Camera Preview Only\n");
+        mStartPid = getMediaserverPid();
+        mMemWriter.write("Camera Preview Only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressCameraPreview();
-            getMemoryWriteToLog(output, i);
+            getMemoryWriteToLog(i);
+            writeProcmemInfo();
         }
-        output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, CAMERA_LIMIT);
-        output.close();
+        mMemWriter.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, CAMERA_LIMIT);
         assertTrue("camera preview memory test", memoryResult);
     }
 }
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 5d49775..8414ff6 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -250,6 +250,10 @@
     AKEYCODE_LANGUAGE_SWITCH = 204,
     AKEYCODE_MANNER_MODE     = 205,
     AKEYCODE_3D_MODE         = 206,
+    AKEYCODE_CONTACTS        = 207,
+    AKEYCODE_CALENDAR        = 208,
+    AKEYCODE_MUSIC           = 209,
+    AKEYCODE_CALCULATOR      = 210,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index 25d5467..484439a 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -125,6 +125,10 @@
     public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT                           = 0x84FE;
     public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       = 0x84FF;
     public static final int GL_BGRA                                                 = 0x80E1;
+    public static final int GL_TEXTURE_EXTERNAL_OES                                 = 0x8D65;
+    public static final int GL_SAMPLER_EXTERNAL_OES                                 = 0x8D66;
+    public static final int GL_TEXTURE_BINDING_EXTERNAL_OES                         = 0x8D67;
+    public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     = 0x8D68;
 
     native private static void _nativeClassInit();
     static {
diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java
index d3a3662..61fa565 100644
--- a/opengl/java/android/opengl/ManagedEGLContext.java
+++ b/opengl/java/android/opengl/ManagedEGLContext.java
@@ -43,12 +43,13 @@
  * of the currently created EGL contexts in the process are being managed
  * through this class, then they will all be asked to terminate through the
  * call to {@link #onTerminate}.
+ * 
+ * @hide
  */
 public abstract class ManagedEGLContext {
     static final String TAG = "ManagedEGLContext";
 
-    static final ArrayList<ManagedEGLContext> sActive
-            = new ArrayList<ManagedEGLContext>();
+    static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
 
     final EGLContext mContext;
 
@@ -127,7 +128,7 @@
             sActive.clear();
         }
 
-        for (int i=0; i<active.size(); i++) {
+        for (int i = 0; i < active.size(); i++) {
             active.get(i).execTerminate();
         }
 
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 5855b63..9c1a10e 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -44,10 +44,17 @@
   LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
 
+ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),)
+  LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
+endif
+
+ifneq ($(MAX_EGL_CACHE_SIZE),)
+  LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
-
 # OpenGL drivers config file
 ifneq ($(BOARD_EGL_CFG),)
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 2237eb6..2b0ed5d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -49,6 +49,8 @@
 
 // ----------------------------------------------------------------------------
 
+#define EGL_VERSION_HW_ANDROID  0x3143
+
 struct extention_map_t {
     const char* name;
     __eglMustCastToProperFunctionPointerType address;
@@ -370,6 +372,11 @@
             }
         }
 
+        // the EGL spec requires that a new EGLSurface default to swap interval
+        // 1, so explicitly set that on the window here.
+        ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
+        anw->setSwapInterval(anw, 1);
+
         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                 iDpy, iConfig, window, attrib_list);
         if (surface != EGL_NO_SURFACE) {
@@ -967,6 +974,12 @@
             return dp->getExtensionString();
         case EGL_CLIENT_APIS:
             return dp->getClientApiString();
+        case EGL_VERSION_HW_ANDROID: {
+            if (gEGLImpl[IMPL_HARDWARE].dso) {
+                return dp->disp[IMPL_HARDWARE].queryString.version;
+            }
+            return dp->disp[IMPL_SOFTWARE].queryString.version;
+        }
     }
     return setError(EGL_BAD_PARAMETER, (const char *)0);
 }
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 13a4929..c4a7466 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -25,10 +25,18 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#ifndef MAX_EGL_CACHE_ENTRY_SIZE
+#define MAX_EGL_CACHE_ENTRY_SIZE (16 * 1024);
+#endif
+
+#ifndef MAX_EGL_CACHE_SIZE
+#define MAX_EGL_CACHE_SIZE (64 * 1024);
+#endif
+
 // Cache size limits.
 static const size_t maxKeySize = 1024;
-static const size_t maxValueSize = 4096;
-static const size_t maxTotalSize = 64 * 1024;
+static const size_t maxValueSize = MAX_EGL_CACHE_ENTRY_SIZE;
+static const size_t maxTotalSize = MAX_EGL_CACHE_SIZE;
 
 // Cache file header
 static const char* cacheFileMagic = "EGL$";
@@ -85,7 +93,7 @@
             bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
             bool atEnd = (bcExtLen+1) < extsLen &&
                     !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
-            bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
+            bool inMiddle = strstr(exts, " " BC_EXT_STR " ");
             if (equal || atStart || atEnd || inMiddle) {
                 PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
                 eglSetBlobCacheFuncsANDROID =
diff --git a/opengl/specs/README b/opengl/specs/README
index 2fa2587..16b278f 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -9,4 +9,5 @@
 0x3140               EGL_ANDROID_image_native_buffer
 0x3141               (unused)
 0x3142               EGL_ANDROID_recordable
-0x3143 - 0x314F      (unused)
+0x3143               EGL_VERSION_HW_ANDROID (internal use)
+0x3144 - 0x314F      (unused)
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
index c5e34cd..0c5fa04 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
@@ -124,6 +124,10 @@
     public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT                           = 0x84FE;
     public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       = 0x84FF;
     public static final int GL_BGRA                                                 = 0x80E1;
+    public static final int GL_TEXTURE_EXTERNAL_OES                                 = 0x8D65;
+    public static final int GL_SAMPLER_EXTERNAL_OES                                 = 0x8D66;
+    public static final int GL_TEXTURE_BINDING_EXTERNAL_OES                         = 0x8D67;
+    public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     = 0x8D68;
 
     native private static void _nativeClassInit();
     static {
@@ -135,4 +139,4 @@
     private static final int GL_FLOAT = GLES10.GL_FLOAT;
     private static final int GL_SHORT = GLES10.GL_SHORT;
     
-    private static Buffer _matrixIndexPointerOES;
\ No newline at end of file
+    private static Buffer _matrixIndexPointerOES;
diff --git a/packages/BackupRestoreConfirmation/res/values-af/strings.xml b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
index 8ee5550..fadd125 100644
--- a/packages/BackupRestoreConfirmation/res/values-af/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
@@ -18,10 +18,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"Volledige rugsteun"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"Volledige herstel"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"\'n Volledige rugsteun van al die data na \'n tafelrekenaar is aangevra. Wil jy dit toelaat? "\n\n"As jy nie self die rugsteun versoek het nie, moenie toelaat dat die aksie voortgaan nie."</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"\'n Volledige rugsteun van al die data na \'n rekenaar is aangevra. Wil jy dit toelaat? "\n\n"As jy nie self die rugsteun versoek het nie, moenie toelaat dat die aksie voortgaan nie."</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"Rugsteun my data"</string>
     <string name="deny_backup_button_label" msgid="6009119115581097708">"Moenie rugsteun nie"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"\'n Volle teruglaai van alle data van \'n gekoppelde tafelrekenaar is versoek. Wil jy dit toelaat? "\n\n" As jy nie die teruglaai self versoek het nie, moenie die aksie toelaat nie. Dit sal enige data tans op die toestel vervang!"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"\'n Volle teruglaai van alle data van \'n gekoppelde rekenaar is versoek. Wil jy dit toelaat? "\n\n" As jy nie die teruglaai self versoek het nie, moenie die aksie toelaat nie. Dit sal enige data tans op die toestel vervang!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"Laai my data terug"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"Moenie herstel nie"</string>
     <string name="current_password_text" msgid="8268189555578298067">"Voer asseblief jou huidige rugsteunwagwoord hieronder in:"</string>
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 113d7ad..504479d 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/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">"Bộ nhớ Cài đặt"</string>
+    <string name="app_label" msgid="4567566098528588863">"Lưu trữ cài đặt"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 7a98615..1ebed1f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -80,6 +80,9 @@
     <!-- Default for Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION -->
     <bool name="def_accessibility_script_injection">false</bool>
 
+    <!-- Default for Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD -->
+    <bool name="def_accessibility_speak_password">false</bool>
+
     <!-- Default for Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS -->
     <string name="def_accessibility_web_content_key_bindings" translatable="false">
             <!-- DPAD/Trackball UP - traverse previous on current axis and send an event. -->
diff --git a/packages/SettingsProvider/res/xml/bookmarks.xml b/packages/SettingsProvider/res/xml/bookmarks.xml
index 83229f4..454f456 100644
--- a/packages/SettingsProvider/res/xml/bookmarks.xml
+++ b/packages/SettingsProvider/res/xml/bookmarks.xml
@@ -19,6 +19,7 @@
      Bookmarks for vendor apps should be added to a bookmarks resource overlay; not here.
 
      Typical shortcuts (not necessarily defined here):
+       'a': Calculator
        'b': Browser
        'c': Contacts
        'e': Email
@@ -32,27 +33,27 @@
 -->
 <bookmarks>
     <bookmark
-        package="com.android.browser"
-        class="com.android.browser.BrowserActivity"
+        category="android.intent.category.APP_CALCULATOR"
+        shortcut="a" />
+    <bookmark
+        category="android.intent.category.APP_BROWSER"
         shortcut="b" />
     <bookmark
-        package="com.android.contacts"
-        class="com.android.contacts.activities.ContactsFrontDoor"
+        category="android.intent.category.APP_CONTACTS"
         shortcut="c" />
     <bookmark
-        package="com.google.android.email"
-        class="com.android.email.activity.Welcome"
+        category="android.intent.category.APP_EMAIL"
         shortcut="e" />
     <bookmark
-        package="com.google.android.calendar"
-        class="com.android.calendar.LaunchActivity"
+        category="android.intent.category.APP_CALENDAR"
         shortcut="l" />
     <bookmark
-        package="com.android.music"
-        class="com.android.music.MusicBrowserActivity"
+        category="android.intent.category.APP_MAPS"
+        shortcut="m" />
+    <bookmark
+        category="android.intent.category.APP_MUSIC"
         shortcut="p" />
     <bookmark
-        package="com.android.mms"
-        class="com.android.mms.ui.ConversationList"
+        category="android.intent.category.APP_MESSAGING"
         shortcut="s" />
 </bookmarks>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index aa08e64..1fbe08d 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 = 70;
+    private static final int DATABASE_VERSION = 73;
 
     private Context mContext;
 
@@ -946,6 +946,46 @@
             upgradeVersion = 70;
         }
 
+        if (upgradeVersion == 70) {
+            // Update all built-in bookmarks.  Some of the package names have changed.
+            loadBookmarks(db);
+            upgradeVersion = 71;
+        }
+
+        if (upgradeVersion == 71) {
+             // New setting to specify whether to speak passwords in accessibility mode.
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
+                        R.bool.def_accessibility_speak_password);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 72;
+        }
+
+        if (upgradeVersion == 72) {
+            // update vibration settings
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
+                        R.bool.def_vibrate_in_silent);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 73;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1086,16 +1126,11 @@
      * Loads the default set of bookmarked shortcuts from an xml file.
      *
      * @param db The database to write the values into
-     * @param startingIndex The zero-based position at which bookmarks in this file should begin
      */
-    private int loadBookmarks(SQLiteDatabase db, int startingIndex) {
-        Intent intent = new Intent(Intent.ACTION_MAIN, null);
-        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+    private void loadBookmarks(SQLiteDatabase db) {
         ContentValues values = new ContentValues();
 
         PackageManager packageManager = mContext.getPackageManager();
-        int i = startingIndex;
-
         try {
             XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks);
             XmlUtils.beginDocument(parser, "bookmarks");
@@ -1118,54 +1153,59 @@
                 String pkg = parser.getAttributeValue(null, "package");
                 String cls = parser.getAttributeValue(null, "class");
                 String shortcutStr = parser.getAttributeValue(null, "shortcut");
+                String category = parser.getAttributeValue(null, "category");
 
                 int shortcutValue = shortcutStr.charAt(0);
                 if (TextUtils.isEmpty(shortcutStr)) {
                     Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
+                    continue;
                 }
 
-                ActivityInfo info = null;                
-                ComponentName cn = new ComponentName(pkg, cls);
-                try {
-                    info = packageManager.getActivityInfo(cn, 0);
-                } catch (PackageManager.NameNotFoundException e) {
-                    String[] packages = packageManager.canonicalToCurrentPackageNames(
-                            new String[] { pkg });
-                    cn = new ComponentName(packages[0], cls);
+                final Intent intent;
+                final String title;
+                if (pkg != null && cls != null) {
+                    ActivityInfo info = null;
+                    ComponentName cn = new ComponentName(pkg, cls);
                     try {
                         info = packageManager.getActivityInfo(cn, 0);
-                    } catch (PackageManager.NameNotFoundException e1) {
-                        Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
+                    } catch (PackageManager.NameNotFoundException e) {
+                        String[] packages = packageManager.canonicalToCurrentPackageNames(
+                                new String[] { pkg });
+                        cn = new ComponentName(packages[0], cls);
+                        try {
+                            info = packageManager.getActivityInfo(cn, 0);
+                        } catch (PackageManager.NameNotFoundException e1) {
+                            Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
+                            continue;
+                        }
                     }
-                }
-                
-                if (info != null) {
+
+                    intent = new Intent(Intent.ACTION_MAIN, null);
+                    intent.addCategory(Intent.CATEGORY_LAUNCHER);
                     intent.setComponent(cn);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
-                    values.put(Settings.Bookmarks.TITLE,
-                            info.loadLabel(packageManager).toString());
-                    values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
-                    db.insert("bookmarks", null, values);
-                    i++;
+                    title = info.loadLabel(packageManager).toString();
+                } else if (category != null) {
+                    intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
+                    title = "";
+                } else {
+                    Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr
+                            + ": missing package/class or category attributes");
+                    continue;
                 }
+
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
+                values.put(Settings.Bookmarks.TITLE, title);
+                values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
+                db.delete("bookmarks", "shortcut = ?",
+                        new String[] { Integer.toString(shortcutValue) });
+                db.insert("bookmarks", null, values);
             }
         } catch (XmlPullParserException e) {
             Log.w(TAG, "Got execption parsing bookmarks.", e);
         } catch (IOException e) {
             Log.w(TAG, "Got execption parsing bookmarks.", e);
         }
-
-        return i;
-    }
-
-    /**
-     * Loads the default set of bookmark packages.
-     *
-     * @param db The database to write the values into
-     */
-    private void loadBookmarks(SQLiteDatabase db) {
-        loadBookmarks(db, 0);
     }
 
     /**
@@ -1483,6 +1523,9 @@
 
             loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
                     R.bool.def_touch_exploration_enabled);
+
+            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
+                    R.bool.def_accessibility_speak_password);
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index dff41c9..ec08e6c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -46,28 +46,9 @@
             </intent-filter>
         </receiver>
 
-        <!-- should you need to launch the screensaver, this is a good way to do it -->
-        <activity android:name=".DreamsDockLauncher"
-                android:theme="@android:style/Theme.Dialog"
-                android:label="@string/dreams_dock_launcher">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <!-- launch screensaver on (desk) dock event -->
-        <receiver android:name=".DreamsDockLauncher$DockEventReceiver" 
-            android:exported="true"
-            >
-            <intent-filter>
-                <action android:name="android.intent.action.DOCK_EVENT" />
-            </intent-filter>
-        </receiver>
-
-
         <activity android:name=".usb.UsbStorageActivity"
-                android:excludeFromRecents="true">
+                  android:label="@*android:string/usb_storage_activity_title"
+                  android:excludeFromRecents="true">
         </activity>
         <activity android:name="com.android.internal.app.ExternalMediaFormatActivity"
                 android:theme="@*android:style/Theme.Dialog.Alert"
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
index cbd72fb..c02bd42 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
index 7651331..05cdd9a 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
index b631779..2b2907b 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_ticker_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_ticker_panel.xml
index 6cd8899..d51f9c8 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_ticker_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_ticker_panel.xml
@@ -15,20 +15,29 @@
  * limitations under the License.
 -->
 
-<LinearLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="horizontal"
-    android:gravity="bottom"
     >
 
+    <View
+        android:layout_height="@*android:dimen/status_bar_height"
+        android:layout_width="match_parent"
+        android:background="@drawable/status_bar_ticker_background"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentBottom="true"
+        android:clickable="false"
+        />
+
     <ImageView
         android:id="@+id/large_icon"
         android:layout_width="@android:dimen/notification_large_icon_height"
         android:layout_height="@android:dimen/notification_large_icon_width"
         android:scaleType="center"
         android:visibility="gone"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentBottom="true"
         />
 
     <FrameLayout
@@ -36,6 +45,8 @@
         android:layout_weight="1"
         android:layout_height="@*android:dimen/status_bar_height"
         android:layout_width="match_parent"
-        android:background="@drawable/status_bar_ticker_background"
+        android:layout_toRightOf="@id/large_icon"
+        android:layout_alignParentBottom="true"
+        android:layout_alignWithParentIfMissing="true"
         />
-</LinearLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index d416af9..8b337ea 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -19,23 +19,18 @@
     <ImageView android:id="@+id/global_screenshot_background"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="#FF000000"
+        android:src="@android:color/black"
         android:visibility="gone" />
-    <FrameLayout
-        android:id="@+id/global_screenshot_container"
+    <ImageView android:id="@+id/global_screenshot"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:background="@drawable/screenshot_panel"
-        android:visibility="gone">
-        <ImageView android:id="@+id/global_screenshot"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:adjustViewBounds="true" />
-    </FrameLayout>
+        android:visibility="gone"
+        android:adjustViewBounds="true" />
     <ImageView android:id="@+id/global_screenshot_flash"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="#FFFFFFFF"
+        android:src="@android:color/white"
         android:visibility="gone" />
 </FrameLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 08dedfa..e140494 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Soek vir GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveer sluimerskerm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 612b666..7910f79 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">" ገፁማያ ማቆያ አንቃ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 4bc56af..e302559 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"جارٍ البحث عن GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"تم تعيين الموقع بواسطة GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"تنشيط شاشة التوقف"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d083467..25a82a6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Пошук GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Месца задана праз GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Актывацыя экраннай застаўкі"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 33aca92..c2bce86 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Търси се GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активиране на скрийнсейвъра"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 775e610..68ab2a7 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"S\'està cercant un GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activa el protector de pantalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4d9b2cd..48ebbd0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhledávání satelitů GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovat spořič obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 841f6e2..af6428b 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -33,7 +33,7 @@
   </plurals>
     <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>
+    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
     <string name="battery_low_title" msgid="2783104807551211639">"Tilslut oplader"</string>
     <string name="battery_low_subtitle" msgid="1752040062087829196">"Batteriet er ved at være fladt."</string>
     <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tilbage"</string>
@@ -45,7 +45,7 @@
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatisk skærmrotation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"LYDLØS"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
-    <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meddelelser"</string>
+    <string name="status_bar_settings_notifications" msgid="397146176280905137">"Underretninger"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inputmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string>
@@ -119,7 +119,7 @@
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flytilstand."</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systemindstillinger."</string>
-    <string name="accessibility_notifications_button" msgid="4498000369779421892">"Meddelelser."</string>
+    <string name="accessibility_notifications_button" msgid="4498000369779421892">"Underretninger."</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ryd meddelelse."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiveret."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS samler data."</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver pauseskærm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index dc1f1e3..447229d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Bildschirmschoner aktivieren"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index cc9dce1..2c25c43 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Αναζήτηση για GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ενεργοποίηση προφύλαξης οθόνης"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 3c70b15..d1835af 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Searching for GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activate screen saver"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 85818ae..66f43df 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar el protector de pantalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f0dcc23..f831aa4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar salvapantallas"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ed62c10..772c78d 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -106,7 +106,7 @@
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX-i on üks riba."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-i on kaks riba."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-i on kolm riba."</string>
-    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-i signaal on täis."</string>
+    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-i signaal on tugev."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-i otsimine"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveeri ekraanisäästja"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 91a8f64..fa527cd 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"جستجو برای GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"مکان تنظیم شده توسط GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"فعال کردن محافظ صفحه نمایش"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index cf9230c7..2db0278 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ota näytönsäästäjä käyttöön"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index df46d2609..017c9e9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -106,7 +106,7 @@
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Signal WiMAX : faible"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Signal WiMAX : moyen"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Signal WiMAX : bon"</string>
-    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX excellent"</string>
+    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX : excellent"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activer l\'économiseur d\'écran"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 42b901c..f29d08b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS को खोजा जा रहा है"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्‍थान"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"स्‍क्रीन सेवर सक्रिय करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4e6d99c..d12a16b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivirajte čuvar zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index e710d50..1d5fb73 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS keresése"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Képernyővédő aktiválása"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a8b024d..ff2bbea 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan tirai layar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0119d5c..14b3745 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ricerca del GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Attiva screensaver"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b6376c8..c9f3791 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"הפעלת שומר מסך"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 54c8482..3ea50f4 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -102,7 +102,7 @@
     <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi電波: レベル2"</string>
     <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi電波: レベル3"</string>
     <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi電波:フル"</string>
-    <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX電波状態:レベル0"</string>
+    <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX電波状態:圏外"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX電波状態:レベル1"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX電波状態:レベル2"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX電波状態:レベル3"</string>
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"スクリーンセーバーを有効にする"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 79569c5..8eb7656d 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"스크린 세이버 활성화"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 490bd4a..8ad91fb 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktyvinti ekrano užsklandą"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 62e99ee..da0019f 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivizēt ekrānsaudzētāju"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index bc32081..3297339 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -102,7 +102,7 @@
     <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dua bar Wi-Fi."</string>
     <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tiga bar Wi-Fi."</string>
     <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Isyarat WiFi penuh."</string>
-    <string name="accessibility_no_wimax" msgid="4329180129727630368">"No. WiMAX"</string>
+    <string name="accessibility_no_wimax" msgid="4329180129727630368">"Tiada WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX satu bar."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX dua bar."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX tiga bar."</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Mencari GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan gambar skrin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7320d6e..2a42cf9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivér skjermbeskytter"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8996b2a..3cef79e 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -106,7 +106,7 @@
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: één streepje."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: twee streepjes."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: drie streepjes."</string>
-    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signaal  is op volledige sterkte."</string>
+    <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signaal  is op volle sterkte."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Schermbeveiliging inschakelen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c65f99e..b658de0 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja ustawiona według GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Włącz wygaszacz ekranu."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e1340ec..9b8d7d8 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"A procurar GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de ecrã"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 545d54e..8c87b26 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de tela"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 2106b89..105a30e 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -244,6 +244,4 @@
     <skip />
     <!-- no translation found for accessibility_clear_all (5235938559247164925) -->
     <skip />
-    <!-- no translation found for dreams_dock_launcher (3541196417659166245) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e4c55d6..7c06b61 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ştergeţi toate notificările."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activaţi screensaverul"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d623990..44824a0 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -102,7 +102,7 @@
     <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: два деления."</string>
     <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: три деления."</string>
     <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Надежный сигнал Wi-Fi."</string>
-    <string name="accessibility_no_wimax" msgid="4329180129727630368">"Сигнал WiMAX отсутствует."</string>
+    <string name="accessibility_no_wimax" msgid="4329180129727630368">"Нет сигнала WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Сигнал WiMAX: одно деление."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Сигнал WiMAX: два деления."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Сигнал WiMAX: три деления."</string>
@@ -131,7 +131,7 @@
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Передача данных по каналам 2G и 3G отключена"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Передача данных по каналу 4G отключена"</string>
-    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобильный Интернет отключен"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Моб. Интернет отключен"</string>
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Передача данных отключена"</string>
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Достигнут лимит трафика."\n\n"При восстановлении подключения оператор может взимать плату за передачу данных."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Восстановить подключение"</string>
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположение установлено с помощью GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активация заставки экрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f0ec8ff..f5213b5 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovať šetrič obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 61b82c9..5c3857e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Iskanje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Vklop ohranjevalnika zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f341fba..ece79e9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Тражи се GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активирање чувара екрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index f8fb054..155d722 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Sökning efter GPS pågår"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivera skärmsläckare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 70e29eb..8d89dff 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -26,7 +26,7 @@
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Ondoa kwenye orodha"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Taarifa za programu-matumizi"</string>
     <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Hakuna programu za sasa"</string>
-    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha prog za hivi karibuni"</string>
+    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha programu za hivi karibuni"</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for status_bar_accessibility_recent_apps:other (1040784359794890744) -->
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Hakuna arifa"</string>
@@ -136,5 +136,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Inatafuta GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Amilisha hifadhi ya skrini"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 3f37060..b6f6671 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"กำลังค้นหา GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"เปิดโปรแกรมรักษาหน้าจอ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 807d797..ff62439 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Naghahanap ng GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"I-activate ang screen saver"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 83567ae..accf878 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ekran koruyucuyu etkinleştir"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index bec231a..2d901ec 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активувати заставку"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 9cf90d2..62b5eba 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -20,7 +20,7 @@
 <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="7164937344850004466">"Giao diện người dùng hệ thống"</string>
-    <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xoá"</string>
+    <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xóa"</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>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Xóa khỏi danh sách"</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Kích hoạt trình bảo vệ màn hình"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7e0e3c4..58cae0d5 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"激活屏幕保护程序"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 614f143..e8a85b8 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -140,5 +140,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"啟用螢幕保護程式"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 52a44a3..614d599 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -68,7 +68,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
-    <string name="screenshot_failed_text" msgid="8134011269572415402">"Ayikwazanga ukulondoloza isithombe-skrini. Ukugcina kwangaphandle kungenzeka kuyasetshenziswa."</string>
+    <string name="screenshot_failed_text" msgid="8134011269572415402">"Ayikwazanga ukulondoloza isithombe-skrini. Isitoreji sangaphandle kungenzeka kuyasetshenziswa."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
@@ -138,5 +138,4 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Isesha i-GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Yenza ukuthi iskrini seyiva sisebenze"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fc81f8e..2c1473b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -362,7 +362,4 @@
 
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
-
-    <!-- Description of the desk dock action that invokes the Android Dreams screen saver feature -->
-    <string name="dreams_dock_launcher">Activate screen saver</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
deleted file mode 100644
index 0035296..0000000
--- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.android.systemui;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Slog;
-
-public class DreamsDockLauncher extends Activity {
-    private static final String TAG = "DreamsDockLauncher";
-
-    // Launch the screen saver if started as an activity.
-    @Override
-    protected void onCreate (Bundle icicle) {
-        super.onCreate(icicle);
-        launchDream(this);
-        finish();
-    }
-
-    private static void launchDream(Context context) {
-        try {
-            String component = Settings.Secure.getString(
-                    context.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
-            if (component == null) {
-                component = context.getResources().getString(
-                    com.android.internal.R.string.config_defaultDreamComponent);
-            }
-            if (component != null) {
-                ComponentName cn = ComponentName.unflattenFromString(component);
-                Intent zzz = new Intent(Intent.ACTION_MAIN)
-                    .setComponent(cn)
-                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                        | Intent.FLAG_ACTIVITY_NO_USER_ACTION
-                        );
-                Slog.v(TAG, "Starting screen saver on dock event: " + component);
-                context.startActivity(zzz);
-            } else {
-                Slog.e(TAG, "Couldn't start screen saver: none selected");
-            }
-        } catch (android.content.ActivityNotFoundException exc) {
-            // no screensaver? give up
-            Slog.e(TAG, "Couldn't start screen saver: none installed");
-        }
-    }
-
-    // Trap low-level dock events and launch the screensaver.
-    public static class DockEventReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
-                Bundle extras = intent.getExtras();
-                int state = extras
-                        .getInt(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-                if (state == Intent.EXTRA_DOCK_STATE_DESK
-                        || state == Intent.EXTRA_DOCK_STATE_LE_DESK
-                        || state == Intent.EXTRA_DOCK_STATE_HE_DESK) {
-                    launchDream(context);
-                }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index ad37603..2232995 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -34,15 +34,14 @@
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
+import android.hardware.CameraSound;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Environment;
 import android.os.Process;
-import android.os.ServiceManager;
 import android.provider.MediaStore;
 import android.util.DisplayMetrics;
 import android.view.Display;
-import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -50,7 +49,6 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
@@ -77,7 +75,6 @@
  */
 class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
         SaveImageInBackgroundData> {
-    private static final String TAG = "SaveImageInBackgroundTask";
     private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
     private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
     private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
@@ -85,11 +82,8 @@
     private int mNotificationId;
     private NotificationManager mNotificationManager;
     private Notification.Builder mNotificationBuilder;
-    private Intent mLaunchIntent;
-    private String mImageDir;
     private String mImageFileName;
     private String mImageFilePath;
-    private String mImageDate;
     private long mImageTime;
 
     // WORKAROUND: We want the same notification across screenshots that we update so that we don't
@@ -105,11 +99,11 @@
 
         // Prepare all the output metadata
         mImageTime = System.currentTimeMillis();
-        mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
-        mImageDir = Environment.getExternalStoragePublicDirectory(
+        String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
+        String imageDir = Environment.getExternalStoragePublicDirectory(
                 Environment.DIRECTORY_PICTURES).getAbsolutePath();
-        mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate);
-        mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir,
+        mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+        mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
                 SCREENSHOTS_DIR_NAME, mImageFileName);
 
         // Create the large notification icon
@@ -190,7 +184,7 @@
         }
 
         return params[0];
-    };
+    }
 
     @Override
     protected void onPostExecute(SaveImageInBackgroundData params) {
@@ -202,14 +196,14 @@
             Resources r = params.context.getResources();
 
             // Create the intent to show the screenshot in gallery
-            mLaunchIntent = new Intent(Intent.ACTION_VIEW);
-            mLaunchIntent.setDataAndType(params.imageUri, "image/png");
-            mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+            launchIntent.setDataAndType(params.imageUri, "image/png");
+            launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
             mNotificationBuilder
                 .setContentTitle(r.getString(R.string.screenshot_saved_title))
                 .setContentText(r.getString(R.string.screenshot_saved_text))
-                .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0))
+                .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
                 .setWhen(System.currentTimeMillis())
                 .setAutoCancel(true);
 
@@ -218,7 +212,7 @@
             mNotificationManager.notify(mNotificationId, n);
         }
         params.finisher.run();
-    };
+    }
 }
 
 /**
@@ -228,7 +222,6 @@
  *     type of gallery?
  */
 class GlobalScreenshot {
-    private static final String TAG = "GlobalScreenshot";
     private static final int SCREENSHOT_NOTIFICATION_ID = 789;
     private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
     private static final int SCREENSHOT_DROP_IN_DURATION = 430;
@@ -244,8 +237,6 @@
     private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
 
     private Context mContext;
-    private LayoutInflater mLayoutInflater;
-    private IWindowManager mIWindowManager;
     private WindowManager mWindowManager;
     private WindowManager.LayoutParams mWindowLayoutParams;
     private NotificationManager mNotificationManager;
@@ -256,7 +247,6 @@
     private Bitmap mScreenBitmap;
     private View mScreenshotLayout;
     private ImageView mBackgroundView;
-    private FrameLayout mScreenshotContainerView;
     private ImageView mScreenshotView;
     private ImageView mScreenshotFlash;
 
@@ -266,6 +256,8 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
+    private CameraSound mCameraSound;
+
 
     /**
      * @param context everything needs a context :(
@@ -273,14 +265,13 @@
     public GlobalScreenshot(Context context) {
         Resources r = context.getResources();
         mContext = context;
-        mLayoutInflater = (LayoutInflater)
+        LayoutInflater layoutInflater = (LayoutInflater)
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
         // Inflate the screenshot layout
         mDisplayMatrix = new Matrix();
-        mScreenshotLayout = mLayoutInflater.inflate(R.layout.global_screenshot, null);
+        mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
         mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
-        mScreenshotContainerView = (FrameLayout) mScreenshotLayout.findViewById(R.id.global_screenshot_container);
         mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
         mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
         mScreenshotLayout.setFocusable(true);
@@ -293,8 +284,6 @@
         });
 
         // Setup the window that we are going to use
-        mIWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
         mWindowLayoutParams = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
                 WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
@@ -318,6 +307,9 @@
         // Scale has to account for both sides of the bg
         mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
         mBgPaddingScale = mBgPadding /  mDisplayMetrics.widthPixels;
+
+        // Setup the Camera shutter sound
+        mCameraSound = new CameraSound();
     }
 
     /**
@@ -428,8 +420,11 @@
         mScreenshotLayout.post(new Runnable() {
             @Override
             public void run() {
-                mScreenshotContainerView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-                mScreenshotContainerView.buildLayer();
+                // Play the shutter sound to notify that we've taken a screenshot
+                mCameraSound.playSound(CameraSound.SHUTTER_CLICK);
+
+                mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                mScreenshotView.buildLayer();
                 mScreenshotAnimation.start();
             }
         });
@@ -463,20 +458,16 @@
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                mBackgroundView.setFastAlpha(0f);
+                mBackgroundView.setAlpha(0f);
                 mBackgroundView.setVisibility(View.VISIBLE);
-                mBackgroundView.fastInvalidate();
-                mScreenshotContainerView.setFastAlpha(0f);
-                mScreenshotContainerView.setFastTranslationX(0f);
-                mScreenshotContainerView.setFastTranslationY(0f);
-                mScreenshotContainerView.setFastScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
-                mScreenshotContainerView.setFastScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
-                mScreenshotContainerView.setVisibility(View.VISIBLE);
-                mScreenshotContainerView.fastInvalidate();
-                mScreenshotFlash.setFastAlpha(0f);
+                mScreenshotView.setAlpha(0f);
+                mScreenshotView.setTranslationX(0f);
+                mScreenshotView.setTranslationY(0f);
+                mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
+                mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
+                mScreenshotView.setVisibility(View.VISIBLE);
+                mScreenshotFlash.setAlpha(0f);
                 mScreenshotFlash.setVisibility(View.VISIBLE);
-                mScreenshotFlash.fastInvalidate();
-                mScreenshotLayout.invalidate();
             }
             @Override
             public void onAnimationEnd(android.animation.Animator animation) {
@@ -486,19 +477,15 @@
         anim.addUpdateListener(new AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                float t = ((Float) animation.getAnimatedValue()).floatValue();
+                float t = (Float) animation.getAnimatedValue();
                 float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
-                    - (float) scaleInterpolator.getInterpolation(t)
+                    - scaleInterpolator.getInterpolation(t)
                         * (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
-                mBackgroundView.setFastAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
-                mBackgroundView.fastInvalidate();
-                mScreenshotContainerView.setFastAlpha(t);
-                mScreenshotContainerView.setFastScaleX(scaleT);
-                mScreenshotContainerView.setFastScaleY(scaleT);
-                mScreenshotContainerView.fastInvalidate();
-                mScreenshotFlash.setFastAlpha(flashAlphaInterpolator.getInterpolation(t));
-                mScreenshotFlash.fastInvalidate();
-                mScreenshotLayout.invalidate();
+                mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
+                mScreenshotView.setAlpha(t);
+                mScreenshotView.setScaleX(scaleT);
+                mScreenshotView.setScaleY(scaleT);
+                mScreenshotFlash.setAlpha(flashAlphaInterpolator.getInterpolation(t));
             }
         });
         return anim;
@@ -511,8 +498,8 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mBackgroundView.setVisibility(View.GONE);
-                mScreenshotContainerView.setVisibility(View.GONE);
-                mScreenshotContainerView.setLayerType(View.LAYER_TYPE_NONE, null);
+                mScreenshotView.setVisibility(View.GONE);
+                mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
 
@@ -522,17 +509,13 @@
             anim.addUpdateListener(new AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
-                    float t = ((Float) animation.getAnimatedValue()).floatValue();
+                    float t = (Float) animation.getAnimatedValue();
                     float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
-                            - (float) t * (SCREENSHOT_DROP_IN_MIN_SCALE
-                                    - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
-                    mBackgroundView.setFastAlpha((1f - t) * BACKGROUND_ALPHA);
-                    mBackgroundView.fastInvalidate();
-                    mScreenshotContainerView.setFastAlpha(1f - t);
-                    mScreenshotContainerView.setFastScaleX(scaleT);
-                    mScreenshotContainerView.setFastScaleY(scaleT);
-                    mScreenshotContainerView.fastInvalidate();
-                    mScreenshotLayout.invalidate();
+                            - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
+                    mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
+                    mScreenshotView.setAlpha(1f - t);
+                    mScreenshotView.setScaleX(scaleT);
+                    mScreenshotView.setScaleY(scaleT);
                 }
             });
         } else {
@@ -563,19 +546,16 @@
             anim.addUpdateListener(new AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
-                    float t = ((Float) animation.getAnimatedValue()).floatValue();
+                    float t = (Float) animation.getAnimatedValue();
                     float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
-                        - (float) scaleInterpolator.getInterpolation(t)
+                        - scaleInterpolator.getInterpolation(t)
                             * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
-                    mBackgroundView.setFastAlpha((1f - t) * BACKGROUND_ALPHA);
-                    mBackgroundView.fastInvalidate();
-                    mScreenshotContainerView.setFastAlpha(1f - scaleInterpolator.getInterpolation(t));
-                    mScreenshotContainerView.setFastScaleX(scaleT);
-                    mScreenshotContainerView.setFastScaleY(scaleT);
-                    mScreenshotContainerView.setFastTranslationX(t * finalPos.x);
-                    mScreenshotContainerView.setFastTranslationY(t * finalPos.y);
-                    mScreenshotContainerView.fastInvalidate();
-                    mScreenshotLayout.invalidate();
+                    mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
+                    mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
+                    mScreenshotView.setScaleX(scaleT);
+                    mScreenshotView.setScaleY(scaleT);
+                    mScreenshotView.setTranslationX(t * finalPos.x);
+                    mScreenshotView.setTranslationY(t * finalPos.y);
                 }
             });
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 694da20..97a1855 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Rect;
 import android.os.ServiceManager;
 import android.util.AttributeSet;
 import android.util.Slog;
@@ -32,6 +33,10 @@
 import android.view.WindowManager;
 import android.widget.LinearLayout;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.StringBuilder;
+
 import com.android.internal.statusbar.IStatusBarService;
 
 import com.android.systemui.R;
@@ -237,4 +242,79 @@
             Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
         }
     }
+
+    private String getResourceName(int resId) {
+        if (resId != 0) {
+            final android.content.res.Resources res = mContext.getResources();
+            try {
+                return res.getResourceName(resId);
+            } catch (android.content.res.Resources.NotFoundException ex) {
+                return "(unknown)";
+            }
+        } else {
+            return "(null)";
+        }
+    }
+
+    private static String visibilityToString(int vis) {
+        switch (vis) {
+            case View.INVISIBLE:
+                return "INVISIBLE";
+            case View.GONE:
+                return "GONE";
+            default:
+                return "VISIBLE";
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("NavigationBarView {");
+        final Rect r = new Rect();
+
+        pw.println(String.format("      this: " + PhoneStatusBar.viewInfo(this)
+                        + " " + visibilityToString(getVisibility())));
+
+        getWindowVisibleDisplayFrame(r);
+        final boolean offscreen = r.right > mDisplay.getRawWidth()
+            || r.bottom > mDisplay.getRawHeight();
+        pw.println("      window: " 
+                + r.toShortString()
+                + " " + visibilityToString(getWindowVisibility())
+                + (offscreen ? " OFFSCREEN!" : ""));
+
+        pw.println(String.format("      mCurrentView: id=%s (%dx%d) %s",
+                        getResourceName(mCurrentView.getId()),
+                        mCurrentView.getWidth(), mCurrentView.getHeight(),
+                        visibilityToString(mCurrentView.getVisibility())));
+
+        pw.println(String.format("      disabled=0x%08x vertical=%s hidden=%s low=%s menu=%s",
+                        mDisabledFlags,
+                        mVertical ? "true" : "false",
+                        mHidden ? "true" : "false",
+                        mLowProfile ? "true" : "false",
+                        mShowMenu ? "true" : "false"));
+
+        final View back = getBackButton();
+        final View home = getHomeButton();
+        final View recent = getRecentsButton();
+        final View menu = getMenuButton();
+
+        pw.println("      back: "
+                + PhoneStatusBar.viewInfo(back)
+                + " " + visibilityToString(back.getVisibility())
+                );
+        pw.println("      home: "
+                + PhoneStatusBar.viewInfo(home)
+                + " " + visibilityToString(home.getVisibility())
+                );
+        pw.println("      rcnt: "
+                + PhoneStatusBar.viewInfo(recent)
+                + " " + visibilityToString(recent.getVisibility())
+                );
+        pw.println("      menu: "
+                + PhoneStatusBar.viewInfo(menu)
+                + " " + visibilityToString(menu.getVisibility())
+                );
+        pw.println("    }");
+    }
 }
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 f0093d3..3c9d12c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -136,7 +136,7 @@
     BatteryController mBatteryController;
     LocationController mLocationController;
     NetworkController mNetworkController;
-    
+
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
     int mIconHPadding = -1;
@@ -168,7 +168,7 @@
 
     // drag bar
     CloseDragHandle mCloseView;
-    
+
     // all notifications
     NotificationData mNotificationData = new NotificationData();
     NotificationRowLayout mPile;
@@ -298,7 +298,7 @@
         try {
             boolean showNav = mWindowManager.hasNavigationBar();
             if (showNav) {
-                mNavigationBarView = 
+                mNavigationBarView =
                     (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
 
                 mNavigationBarView.setDisabledFlags(mDisabled);
@@ -352,11 +352,11 @@
         mBatteryController = new BatteryController(mContext);
         mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
         mNetworkController = new NetworkController(mContext);
-        final SignalClusterView signalCluster = 
+        final SignalClusterView signalCluster =
                 (SignalClusterView)sb.findViewById(R.id.signal_cluster);
         mNetworkController.addSignalCluster(signalCluster);
         signalCluster.setNetworkController(mNetworkController);
-//        final ImageView wimaxRSSI = 
+//        final ImageView wimaxRSSI =
 //                (ImageView)sb.findViewById(R.id.wimax_signal);
 //        if (wimaxRSSI != null) {
 //            mNetworkController.addWimaxIconView(wimaxRSSI);
@@ -973,7 +973,7 @@
             } catch (NameNotFoundException ex) {
                 Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
             }
-            if (version > 0 && version < Build.VERSION_CODES.HONEYCOMB) {
+            if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
                 content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
             } else {
                 content.setBackgroundResource(R.drawable.notification_row_bg);
@@ -1085,8 +1085,8 @@
             }
         }
 
-        if ((diff & (StatusBarManager.DISABLE_HOME 
-                        | StatusBarManager.DISABLE_RECENT 
+        if ((diff & (StatusBarManager.DISABLE_HOME
+                        | StatusBarManager.DISABLE_RECENT
                         | StatusBarManager.DISABLE_BACK)) != 0) {
             // the nav bar will take care of these
             if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state);
@@ -1204,7 +1204,7 @@
     public void animateCollapse(boolean excludeRecents) {
         animateCollapse(excludeRecents, 1.0f);
     }
-    
+
     public void animateCollapse(boolean excludeRecents, float velocityMultiplier) {
         if (SPEW) {
             Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
@@ -1516,8 +1516,8 @@
                 }
 
                 if (CHATTY) {
-                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f", 
-                        mVelocityTracker.getXVelocity(), 
+                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+                        mVelocityTracker.getXVelocity(),
                         mVelocityTracker.getYVelocity(),
                         xVel, yVel,
                         vel));
@@ -1735,9 +1735,9 @@
         return anim;
     }
 
-    public String viewInfo(View v) {
-        return "(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
-                + " " + v.getWidth() + "x" + v.getHeight() + ")";
+    public static String viewInfo(View v) {
+        return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
+                + ") " + v.getWidth() + "x" + v.getHeight() + "]";
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -1768,6 +1768,13 @@
                     + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
         }
 
+        pw.print("  mNavigationBarView=");
+        if (mNavigationBarView == null) {
+            pw.println("null");
+        } else {
+            mNavigationBarView.dump(fd, pw, args);
+        }
+
         if (DUMPTRUCK) {
             synchronized (mNotificationData) {
                 int N = mNotificationData.size();
@@ -1788,7 +1795,7 @@
                 StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
                 pw.println("    [" + i + "] icon=" + ic);
             }
-            
+
             if (false) {
                 pw.println("see the logcat for a dump of the views we have created.");
                 // must happen on ui thread
@@ -1963,10 +1970,10 @@
                         - (mTrackingParams.height-closePos) - contentsBottom;
 
                 if (SPEW) {
-                    Slog.d(PhoneStatusBar.TAG, 
+                    Slog.d(PhoneStatusBar.TAG,
                             "pos=" + pos +
                             " trackingHeight=" + mTrackingView.getHeight() +
-                            " (trackingParams.height - closePos)=" + 
+                            " (trackingParams.height - closePos)=" +
                                 (mTrackingParams.height - closePos) +
                             " contentsBottom=" + contentsBottom);
                 }
@@ -2041,7 +2048,7 @@
                 mExpandedDialog.getWindow().setAttributes(mExpandedParams);
             }
             if (DEBUG) {
-                Slog.d(TAG, "updateExpandedSize: height=" + mExpandedParams.height + " " + 
+                Slog.d(TAG, "updateExpandedSize: height=" + mExpandedParams.height + " " +
                     (mExpandedVisible ? "VISIBLE":"INVISIBLE"));
             }
         }
@@ -2181,6 +2188,11 @@
 
     private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
         public void onClick(View v) {
+            try {
+                // Dismiss the lock screen when Settings starts.
+                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+            } catch (RemoteException e) {
+            }
             v.getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
             animateCollapse();
@@ -2230,7 +2242,7 @@
 
         loadDimens();
     }
-    
+
     protected void loadDimens() {
         final Resources res = mContext.getResources();
 
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 903a300..603808e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -36,7 +36,7 @@
 
     private int mIconId = R.drawable.stat_sys_data_bluetooth;
     private int mContentDescriptionId = 0;
-    private boolean mEnabled;
+    private boolean mEnabled = false;
 
     public BluetoothController(Context context) {
         mContext = context;
@@ -47,8 +47,10 @@
         context.registerReceiver(this, filter);
 
         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        handleAdapterStateChange(adapter.getState());
-        handleConnectionStateChange(adapter.getConnectionState());
+        if (adapter != null) {
+            handleAdapterStateChange(adapter.getState());
+            handleConnectionStateChange(adapter.getConnectionState());
+        }
         refreshViews();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
index 7fbf734..2d951c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
@@ -49,6 +49,10 @@
 
     public void refresh() {
         int mode = mAM.getFrontActivityScreenCompatMode();
+        if (mode == ActivityManager.COMPAT_MODE_UNKNOWN) {
+            // If in an unknown state, don't change.
+            return;
+        }
         final boolean vis = (mode != ActivityManager.COMPAT_MODE_NEVER
                           && mode != ActivityManager.COMPAT_MODE_ALWAYS);
         if (DEBUG) Slog.d(TAG, "compat mode is " + mode + "; icon will " + (vis ? "show" : "hide"));
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 55a5b0a..135a04c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -898,7 +898,7 @@
             combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
             mContentDescriptionCombinedSignal = mContentDescriptionDataType;
         }
-        
+
         if (mWifiConnected) {
             if (mWifiSsid == null) {
                 label = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
@@ -932,19 +932,23 @@
             mContentDescriptionCombinedSignal = mContext.getString(
                     R.string.accessibility_bluetooth_tether);
         }
-        
+
         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);
-            mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal
-                = mContext.getString(R.string.accessibility_airplane_mode);
-            
+
             // look again; your radios are now airplanes
+            mContentDescriptionPhoneSignal = mContext.getString(
+                    R.string.accessibility_airplane_mode);
             mPhoneSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_flightmode;
             mDataTypeIconId = 0;
 
-            combinedSignalIconId = mDataSignalIconId;
+            // combined values from connected wifi take precedence over airplane mode
+            if (!mWifiConnected) {
+                label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+                mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
+                combinedSignalIconId = mDataSignalIconId;
+            }
         }
         else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected) {
             // pretty much totally disconnected
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 01406bc..05ad793 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -168,7 +168,6 @@
     NetworkController mNetworkController;
 
     ViewGroup mBarContents;
-    LayoutTransition mBarContentsLayoutTransition;
 
     // hide system chrome ("lights out") support
     View mShadow;
@@ -461,19 +460,6 @@
         }
 
         mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
-        // layout transitions for the status bar's contents
-        mBarContentsLayoutTransition = new LayoutTransition();
-        // add/removal will fade as normal
-        mBarContentsLayoutTransition.setAnimator(LayoutTransition.APPEARING,
-                ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
-        mBarContentsLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING,
-                ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
-        // no animations for siblings on change: just jump into place please
-        mBarContentsLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, null);
-        mBarContentsLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, null);
-        // quick like bunny
-        mBarContentsLayoutTransition.setDuration(250 * (DEBUG?10:1));
-        mBarContents.setLayoutTransition(mBarContentsLayoutTransition);
 
         // the whole right-hand side of the bar
         mNotificationArea = sb.findViewById(R.id.notificationArea);
@@ -522,7 +508,23 @@
         mMenuButton = mNavigationArea.findViewById(R.id.menu);
         mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
         mRecentButton.setOnClickListener(mOnClickListener);
-        mNavigationArea.setLayoutTransition(mBarContentsLayoutTransition);
+
+        LayoutTransition lt = new LayoutTransition();
+        lt.setDuration(250);
+        // don't wait for these transitions; we just want icons to fade in/out, not move around
+        lt.setDuration(LayoutTransition.CHANGE_APPEARING, 0);
+        lt.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 0);
+        lt.addTransitionListener(new LayoutTransition.TransitionListener() {
+            public void endTransition(LayoutTransition transition, ViewGroup container,
+                    View view, int transitionType) {
+                // ensure the menu button doesn't stick around on the status bar after it's been
+                // removed
+                mBarContents.invalidate();
+            }
+            public void startTransition(LayoutTransition transition, ViewGroup container,
+                    View view, int transitionType) {}
+        });
+        mNavigationArea.setLayoutTransition(lt);
         // no multi-touch on the nav buttons
         mNavigationArea.setMotionEventSplittingEnabled(false);
 
@@ -534,6 +536,7 @@
 
         mCompatModeButton = (CompatModeButton) sb.findViewById(R.id.compatModeButton);
         mCompatModeButton.setOnClickListener(mOnClickListener);
+        mCompatModeButton.setVisibility(View.GONE);
 
         // for redirecting errant bar taps to the IME
         mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
@@ -1835,7 +1838,7 @@
             } catch (NameNotFoundException ex) {
                 Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
             }
-            if (version > 0 && version < Build.VERSION_CODES.HONEYCOMB) {
+            if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
                 content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
             } else {
                 content.setBackgroundResource(R.drawable.notification_row_bg);
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 6045e31..e93a32b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -73,6 +73,8 @@
     private StatusBarNotification[] mQueue = new StatusBarNotification[QUEUE_LENGTH];
     private int mQueuePos;
 
+    private final int mLargeIconHeight;
+
     private TabletStatusBar mBar;
 
     private LayoutTransition mLayoutTransition;
@@ -81,6 +83,9 @@
     public TabletTicker(TabletStatusBar bar) {
         mBar = bar;
         mContext = bar.getContext();
+        final Resources res = mContext.getResources();
+        mLargeIconHeight = res.getDimensionPixelSize(
+                android.R.dimen.notification_large_icon_height);
     }
 
     public void add(IBinder key, StatusBarNotification notification) {
@@ -209,8 +214,6 @@
         final Resources res = mContext.getResources();
         final FrameLayout view = new FrameLayout(mContext);
         final int width = res.getDimensionPixelSize(R.dimen.notification_ticker_width);
-        final int height = res.getDimensionPixelSize(
-                android.R.dimen.notification_large_icon_height);
         int windowFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -219,7 +222,7 @@
         } else {
             windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
         }
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, mLargeIconHeight,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, windowFlags,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
@@ -297,6 +300,16 @@
         if (n.largeIcon != null) {
             largeIcon.setImageBitmap(n.largeIcon);
             largeIcon.setVisibility(View.VISIBLE);
+            final ViewGroup.LayoutParams lp = largeIcon.getLayoutParams();
+            final int statusBarHeight = mBar.getStatusBarHeight();
+            if (n.largeIcon.getHeight() <= statusBarHeight) {
+                // for smallish largeIcons, it looks a little odd to have them floating halfway up
+                // the ticker, so we vertically center them in the status bar area instead
+                lp.height = statusBarHeight;
+            } else {
+                lp.height = mLargeIconHeight;
+            }
+            largeIcon.setLayoutParams(lp);
         }
 
         if (CLICKABLE_TICKER) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
index 43dfb96..e61ef8a 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
@@ -114,16 +114,11 @@
         thr.start();
         mAsyncStorageHandler = new Handler(thr.getLooper());
 
-        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-        setProgressBarIndeterminateVisibility(true);
-
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
         if (Environment.isExternalStorageRemovable()) {
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
         }
 
-        setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
-
         setContentView(com.android.internal.R.layout.usb_storage_activity);
 
         mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index f040e87..38c85bb 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -56,13 +56,15 @@
 
     private static final String TAG = "GlobalActions";
 
+    private static final boolean SHOW_SILENT_TOGGLE = true;
+
     private final Context mContext;
     private final AudioManager mAudioManager;
 
     private ArrayList<Action> mItems;
     private AlertDialog mDialog;
 
-    private ToggleAction mSilentModeToggle;
+    private SilentModeAction mSilentModeAction;
     private ToggleAction mAirplaneModeOn;
 
     private MyAdapter mAdapter;
@@ -113,39 +115,7 @@
      * @return A new dialog.
      */
     private AlertDialog createDialog() {
-        mSilentModeToggle = new ToggleAction(
-                R.drawable.ic_audio_vol_mute,
-                R.drawable.ic_audio_vol,
-                R.string.global_action_toggle_silent_mode,
-                R.string.global_action_silent_mode_on_status,
-                R.string.global_action_silent_mode_off_status) {
-
-            void willCreate() {
-                mEnabledIconResId = (Settings.System.getInt(mContext.getContentResolver(),
-                        Settings.System.VIBRATE_IN_SILENT, 1) == 1)
-                    ? R.drawable.ic_audio_ring_notif_vibrate
-                    : R.drawable.ic_audio_vol_mute;
-            }
-
-            void onToggle(boolean on) {
-                if (on) {
-                    mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(),
-                        Settings.System.VIBRATE_IN_SILENT, 1) == 1)
-                        ? AudioManager.RINGER_MODE_VIBRATE
-                        : AudioManager.RINGER_MODE_SILENT);
-                } else {
-                    mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-                }
-            }
-
-            public boolean showDuringKeyguard() {
-                return true;
-            }
-
-            public boolean showBeforeProvisioning() {
-                return false;
-            }
-        };
+        mSilentModeAction = new SilentModeAction(mAudioManager, mHandler);
 
         mAirplaneModeOn = new ToggleAction(
                 R.drawable.ic_lock_airplane_mode,
@@ -187,39 +157,45 @@
             }
         };
 
-        mItems = Lists.newArrayList(
-                // silent mode
-                mSilentModeToggle,
-                // next: airplane mode
-                mAirplaneModeOn,
-                // last: power off
-                new SinglePressAction(
-                        com.android.internal.R.drawable.ic_lock_power_off,
-                        R.string.global_action_power_off) {
+        mItems = new ArrayList<Action>();
 
-                    public void onPress() {
-                        // shutdown by making sure radio and power are handled accordingly.
-                        ShutdownThread.shutdown(mContext, true);
-                    }
+        // first: power off
+        mItems.add(
+            new SinglePressAction(
+                    com.android.internal.R.drawable.ic_lock_power_off,
+                    R.string.global_action_power_off) {
 
-                    public boolean showDuringKeyguard() {
-                        return true;
-                    }
+                public void onPress() {
+                    // shutdown by making sure radio and power are handled accordingly.
+                    ShutdownThread.shutdown(mContext, true);
+                }
 
-                    public boolean showBeforeProvisioning() {
-                        return true;
-                    }
-                });
+                public boolean showDuringKeyguard() {
+                    return true;
+                }
+
+                public boolean showBeforeProvisioning() {
+                    return true;
+                }
+            });
+
+        // next: airplane mode
+        mItems.add(mAirplaneModeOn);
+
+        // last: silent mode
+        if (SHOW_SILENT_TOGGLE) {
+            mItems.add(mSilentModeAction);
+        }
 
         mAdapter = new MyAdapter();
 
         final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
 
         ab.setAdapter(mAdapter, this)
-                .setInverseBackgroundForced(true)
-                .setTitle(R.string.global_actions);
+                .setInverseBackgroundForced(true);
 
         final AlertDialog dialog = ab.create();
+        dialog.getListView().setItemsCanFocus(true);
         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
 
         dialog.setOnDismissListener(this);
@@ -230,8 +206,6 @@
     private void prepareDialog() {
         final boolean silentModeOn =
                 mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
-        mSilentModeToggle.updateState(
-                silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off);
         mAirplaneModeOn.updateState(mAirplaneState);
         mAdapter.notifyDataSetChanged();
         if (mKeyguardShowing) {
@@ -239,20 +213,28 @@
         } else {
             mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
         }
+        if (SHOW_SILENT_TOGGLE) {
+            IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
+            mContext.registerReceiver(mRingerModeReceiver, filter);
+        }
     }
 
 
     /** {@inheritDoc} */
     public void onDismiss(DialogInterface dialog) {
+        if (SHOW_SILENT_TOGGLE) {
+            mContext.unregisterReceiver(mRingerModeReceiver);
+        }
     }
 
     /** {@inheritDoc} */
     public void onClick(DialogInterface dialog, int which) {
-        dialog.dismiss();
+        if (!(mAdapter.getItem(which) instanceof SilentModeAction)) {
+            dialog.dismiss();
+        }
         mAdapter.getItem(which).onPress();
     }
 
-
     /**
      * The adapter used for the list within the global actions dialog, taking
      * into account whether the keyguard is showing via
@@ -373,9 +355,7 @@
 
         public View create(
                 Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
-            View v = (convertView != null) ?
-                    convertView :
-                    inflater.inflate(R.layout.global_actions_item, parent, false);
+            View v = inflater.inflate(R.layout.global_actions_item, parent, false);
 
             ImageView icon = (ImageView) v.findViewById(R.id.icon);
             TextView messageView = (TextView) v.findViewById(R.id.message);
@@ -452,27 +432,31 @@
                 LayoutInflater inflater) {
             willCreate();
 
-            View v = (convertView != null) ?
-                    convertView :
-                    inflater.inflate(R
+            View v = inflater.inflate(R
                             .layout.global_actions_item, parent, false);
 
             ImageView icon = (ImageView) v.findViewById(R.id.icon);
             TextView messageView = (TextView) v.findViewById(R.id.message);
             TextView statusView = (TextView) v.findViewById(R.id.status);
+            final boolean enabled = isEnabled();
 
-            messageView.setText(mMessageResId);
+            if (messageView != null) {
+                messageView.setText(mMessageResId);
+                messageView.setEnabled(enabled);
+            }
 
             boolean on = ((mState == State.On) || (mState == State.TurningOn));
-            icon.setImageDrawable(context.getResources().getDrawable(
-                    (on ? mEnabledIconResId : mDisabledIconResid)));
-            statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
-            statusView.setVisibility(View.VISIBLE);
+            if (icon != null) {
+                icon.setImageDrawable(context.getResources().getDrawable(
+                        (on ? mEnabledIconResId : mDisabledIconResid)));
+                icon.setEnabled(enabled);
+            }
 
-            final boolean enabled = isEnabled();
-            messageView.setEnabled(enabled);
-            statusView.setEnabled(enabled);
-            icon.setEnabled(enabled);
+            if (statusView != null) {
+                statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
+                statusView.setVisibility(View.VISIBLE);
+                statusView.setEnabled(enabled);
+            }
             v.setEnabled(enabled);
 
             return v;
@@ -510,6 +494,70 @@
         }
     }
 
+    private static class SilentModeAction implements Action, View.OnClickListener {
+
+        private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 };
+
+        private final AudioManager mAudioManager;
+        private final Handler mHandler;
+
+        SilentModeAction(AudioManager audioManager, Handler handler) {
+            mAudioManager = audioManager;
+            mHandler = handler;
+        }
+
+        private int ringerModeToIndex(int ringerMode) {
+            // They just happen to coincide
+            return ringerMode;
+        }
+
+        private int indexToRingerMode(int index) {
+            // They just happen to coincide
+            return index;
+        }
+
+        public View create(Context context, View convertView, ViewGroup parent,
+                LayoutInflater inflater) {
+            View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
+
+            int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode());
+            for (int i = 0; i < 3; i++) {
+                View itemView = v.findViewById(ITEM_IDS[i]);
+                itemView.setSelected(selectedIndex == i);
+                // Set up click handler
+                itemView.setTag(i);
+                itemView.setOnClickListener(this);
+            }
+            return v;
+        }
+
+        public void onPress() {
+        }
+
+        public boolean showDuringKeyguard() {
+            return true;
+        }
+
+        public boolean showBeforeProvisioning() {
+            return false;
+        }
+
+        public boolean isEnabled() {
+            return true;
+        }
+
+        void willCreate() {
+        }
+
+        public void onClick(View v) {
+            if (!(v.getTag() instanceof Integer)) return;
+
+            int index = (Integer) v.getTag();
+            mAudioManager.setRingerMode(indexToRingerMode(index));
+            mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);
+        }
+    }
+
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
@@ -541,13 +589,27 @@
         }
     };
 
+    private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+                mHandler.sendEmptyMessage(MESSAGE_REFRESH);
+            }
+        }
+    };
+
     private static final int MESSAGE_DISMISS = 0;
+    private static final int MESSAGE_REFRESH = 1;
+    private static final int DIALOG_DISMISS_DELAY = 300; // ms
+
     private Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             if (msg.what == MESSAGE_DISMISS) {
                 if (mDialog != null) {
                     mDialog.dismiss();
                 }
+            } else if (msg.what == MESSAGE_REFRESH) {
+                mAdapter.notifyDataSetChanged();
             }
         }
     };
diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java
index 4564f90..e997355 100644
--- a/policy/src/com/android/internal/policy/impl/IconUtilities.java
+++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java
@@ -38,6 +38,8 @@
 import android.text.TextPaint;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 import android.content.res.Resources;
 import android.content.Context;
 
@@ -74,9 +76,13 @@
         mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);
 
         mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
-        mGlowColorPressedPaint.setColor(0xffffc300);
+
+        TypedValue value = new TypedValue();
+        mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute(
+                android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300);
         mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
-        mGlowColorFocusedPaint.setColor(0xffff8e00);
+        mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute(
+                android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00);
         mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
 
         ColorMatrix cm = new ColorMatrix();
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 84540a15..b4b82aa 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -110,10 +110,14 @@
      * the intent and provide a {@link SimCard.State} result.
      */
     private static class SimArgs {
-
         public final IccCard.State simState;
 
-        private SimArgs(Intent intent) {
+        SimArgs(IccCard.State state) {
+            simState = state;
+        }
+
+        static SimArgs fromIntent(Intent intent) {
+            IccCard.State state;
             if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
                 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
             }
@@ -124,27 +128,28 @@
 
                 if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
                         absentReason)) {
-                    this.simState = IccCard.State.PERM_DISABLED;
+                    state = IccCard.State.PERM_DISABLED;
                 } else {
-                    this.simState = IccCard.State.ABSENT;
+                    state = IccCard.State.ABSENT;
                 }
             } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
-                this.simState = IccCard.State.READY;
+                state = IccCard.State.READY;
             } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
                 final String lockedReason = intent
                         .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
                 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                    this.simState = IccCard.State.PIN_REQUIRED;
+                    state = IccCard.State.PIN_REQUIRED;
                 } else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                    this.simState = IccCard.State.PUK_REQUIRED;
+                    state = IccCard.State.PUK_REQUIRED;
                 } else {
-                    this.simState = IccCard.State.UNKNOWN;
+                    state = IccCard.State.UNKNOWN;
                 }
             } else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
-                this.simState = IccCard.State.NETWORK_LOCKED;
+                state = IccCard.State.NETWORK_LOCKED;
             } else {
-                this.simState = IccCard.State.UNKNOWN;
+                state = IccCard.State.UNKNOWN;
             }
+            return new SimArgs(state);
         }
 
         public String toString() {
@@ -279,8 +284,7 @@
                     mHandler.sendMessage(msg);
                 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
                     mHandler.sendMessage(mHandler.obtainMessage(
-                            MSG_SIM_STATE_CHANGE,
-                            new SimArgs(intent)));
+                            MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
                 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
                             intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
@@ -571,12 +575,16 @@
     }
 
     /**
-     * Report that the user succesfully entered the sim pin or puk so we
+     * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
      * have the information earlier than waiting for the intent
      * broadcast from the telephony code.
+     *
+     * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
+     * through mHandler, this *must* be called from the UI thread.
      */
     public void reportSimUnlocked() {
         mSimState = IccCard.State.READY;
+        handleSimStateChange(new SimArgs(mSimState));
     }
 
     public boolean isKeyguardBypassEnabled() {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 26bd697..f204070 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -46,6 +46,10 @@
     private KeyguardViewCallback mCallback;
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager = null;
+    // Whether the volume keys should be handled by keyguard. If true, then
+    // they will be handled here for specific media types such as music, otherwise
+    // the audio service will bring up the volume dialog.
+    private static final boolean KEYGUARD_MANAGES_VOLUME = true;
 
     // This is a faster way to draw the background on devices without hardware acceleration
     Drawable mBackgroundDrawable = new Drawable() {
@@ -203,24 +207,28 @@
                 case KeyEvent.KEYCODE_VOLUME_UP:
                 case KeyEvent.KEYCODE_VOLUME_DOWN:
                 case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                    synchronized (this) {
-                        if (mAudioManager == null) {
-                            mAudioManager = (AudioManager) getContext().getSystemService(
-                                    Context.AUDIO_SERVICE);
+                    if (KEYGUARD_MANAGES_VOLUME) {
+                        synchronized (this) {
+                            if (mAudioManager == null) {
+                                mAudioManager = (AudioManager) getContext().getSystemService(
+                                        Context.AUDIO_SERVICE);
+                            }
                         }
+                        // Volume buttons should only function for music.
+                        if (mAudioManager.isMusicActive()) {
+                            // TODO: Actually handle MUTE.
+                            mAudioManager.adjustStreamVolume(
+                                        AudioManager.STREAM_MUSIC,
+                                        keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                                                ? AudioManager.ADJUST_RAISE
+                                                : AudioManager.ADJUST_LOWER,
+                                        0);
+                        }
+                        // Don't execute default volume behavior
+                        return true;
+                    } else {
+                        return false;
                     }
-                    // Volume buttons should only function for music.
-                    if (mAudioManager.isMusicActive()) {
-                        // TODO: Actually handle MUTE.
-                        mAudioManager.adjustStreamVolume(
-                                    AudioManager.STREAM_MUSIC,
-                                    keyCode == KeyEvent.KEYCODE_VOLUME_UP
-                                            ? AudioManager.ADJUST_RAISE
-                                            : AudioManager.ADJUST_LOWER,
-                                    0);
-                    }
-                    // Don't execute default volume behavior
-                    return true;
                 }
             }
         } else if (event.getAction() == KeyEvent.ACTION_UP) {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index dd3b75d..6eff4b6 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -558,9 +558,12 @@
         mScreenOn = false;
         mForgotPattern = false;
         mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
-        if (mMode == Mode.LockScreen) {
+
+        // Emulate activity life-cycle for both lock and unlock screen.
+        if (mLockScreen != null) {
             ((KeyguardScreen) mLockScreen).onPause();
-        } else {
+        }
+        if (mUnlockScreen != null) {
             ((KeyguardScreen) mUnlockScreen).onPause();
         }
 
@@ -651,9 +654,11 @@
 
     @Override
     public void show() {
-        if (mMode == Mode.LockScreen) {
+        // Emulate activity life-cycle for both lock and unlock screen.
+        if (mLockScreen != null) {
             ((KeyguardScreen) mLockScreen).onResume();
-        } else {
+        }
+        if (mUnlockScreen != null) {
             ((KeyguardScreen) mUnlockScreen).onResume();
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index af86ae9..535f039 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1816,22 +1816,42 @@
 
         @Override
         public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
-            // Perform the shortcut (mPreparedPanel can be null since
-            // global shortcuts (such as search) don't rely on a
-            // prepared panel or menu).
-            boolean handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
-                    Menu.FLAG_PERFORM_NO_CLOSE);
-            if (handled) {
-                if (mPreparedPanel != null) {
-                    mPreparedPanel.isHandled = true;
+            // If the panel is already prepared, then perform the shortcut using it.
+            boolean handled;
+            if (mPreparedPanel != null) {
+                handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
+                        Menu.FLAG_PERFORM_NO_CLOSE);
+                if (handled) {
+                    if (mPreparedPanel != null) {
+                        mPreparedPanel.isHandled = true;
+                    }
+                    return true;
                 }
-                return true;
             }
 
             // Shortcut not handled by the panel.  Dispatch to the view hierarchy.
             final Callback cb = getCallback();
-            return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchKeyShortcutEvent(ev)
-                    : super.dispatchKeyShortcutEvent(ev);
+            handled = cb != null && !isDestroyed() && mFeatureId < 0
+                    ? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev);
+            if (handled) {
+                return true;
+            }
+
+            // If the panel is not prepared, then we may be trying to handle a shortcut key
+            // combination such as Control+C.  Temporarily prepare the panel then mark it
+            // unprepared again when finished to ensure that the panel will again be prepared
+            // the next time it is shown for real.
+            if (mPreparedPanel == null) {
+                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+                preparePanel(st, ev);
+                handled = performPanelShortcut(st, ev.getKeyCode(), ev,
+                        Menu.FLAG_PERFORM_NO_CLOSE);
+                st.isPrepared = false;
+                if (handled) {
+                    return true;
+                }
+            }
+            return false;
         }
 
         @Override
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e00a54c..7510e04 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -39,7 +39,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.os.Binder;
+import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -68,8 +68,10 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
+import android.view.IApplicationToken;
 import android.view.IWindowManager;
 import android.view.InputChannel;
 import android.view.InputDevice;
@@ -226,7 +228,30 @@
     // Useful scan codes.
     private static final int SW_LID = 0x00;
     private static final int BTN_MOUSE = 0x110;
-    
+
+    /* Table of Application Launch keys.  Maps from key codes to intent categories.
+     *
+     * These are special keys that are used to launch particular kinds of applications,
+     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
+     * usage page.  We don't support quite that many yet...
+     */
+    static SparseArray<String> sApplicationLaunchKeyCategories;
+    static {
+        sApplicationLaunchKeyCategories = new SparseArray<String>();
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
+        sApplicationLaunchKeyCategories.append(
+                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
+    }
+
     /**
      * Lock protecting internal state.  Must not call out into window
      * manager with lock held.  (This lock will be acquired in places
@@ -273,9 +298,15 @@
     GlobalActions mGlobalActions;
     volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
     boolean mPendingPowerKeyUpCanceled;
-    RecentApplicationsDialog mRecentAppsDialog;
     Handler mHandler;
 
+    static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
+    static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
+    static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
+
+    RecentApplicationsDialog mRecentAppsDialog;
+    int mRecentAppsDialogHeldModifiers;
+
     private static final int LID_ABSENT = -1;
     private static final int LID_CLOSED = 0;
     private static final int LID_OPEN = 1;
@@ -315,6 +346,7 @@
 
     // The last window we were told about in focusChanged.
     WindowState mFocusedWindow;
+    IApplicationToken mFocusedApp;
 
     private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
         @Override
@@ -394,10 +426,6 @@
     int mLockScreenTimeout;
     boolean mLockScreenTimerActive;
 
-    // visual screen saver support
-    int mScreenSaverTimeout = 0;
-    boolean mScreenSaverEnabled = true;
-
     // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
     int mEndcallBehavior;
 
@@ -460,8 +488,6 @@
                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
             resolver.registerContentObserver(Settings.System.getUriFor(
                     "fancy_rotation_anim"), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.DREAM_TIMEOUT), false, this);
             updateSettings();
         }
 
@@ -673,7 +699,7 @@
         }
 
         if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
-            showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+            showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
         } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
             try {
                 mStatusBarService.toggleRecentApps();
@@ -684,10 +710,10 @@
     }
 
     /**
-     * Create (if necessary) and launch the recent apps dialog, or hide it if it is
-     * already shown.
+     * Create (if necessary) and show or dismiss the recent apps dialog according
+     * according to the requested behavior.
      */
-    void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
+    void showOrHideRecentAppsDialog(final int behavior) {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -695,12 +721,33 @@
                     mRecentAppsDialog = new RecentApplicationsDialog(mContext);
                 }
                 if (mRecentAppsDialog.isShowing()) {
-                    if (dismissIfShown) {
-                        mRecentAppsDialog.dismiss();
+                    switch (behavior) {
+                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+                            mRecentAppsDialog.dismiss();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+                            mRecentAppsDialog.dismissAndSwitch();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+                        default:
+                            break;
                     }
                 } else {
-                    mRecentAppsDialog.setHeldModifiers(heldModifiers);
-                    mRecentAppsDialog.show();
+                    switch (behavior) {
+                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+                            mRecentAppsDialog.show();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+                            try {
+                                mWindowManager.setInTouchMode(false);
+                            } catch (RemoteException e) {
+                            }
+                            mRecentAppsDialog.show();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+                        default:
+                            break;
+                    }
                 }
             }
         });
@@ -768,6 +815,7 @@
             mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
         }
+
         mVibrator = new Vibrator();
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_longPressVibePattern);
@@ -916,10 +964,6 @@
                 mHasSoftInput = hasSoftInput;
                 updateRotation = true;
             }
-
-            mScreenSaverTimeout = Settings.Secure.getInt(resolver,
-                    Settings.Secure.DREAM_TIMEOUT, 0);
-            updateScreenSaverTimeoutLocked();
         }
         if (updateRotation) {
             updateRotation(true);
@@ -1581,7 +1625,7 @@
             return 0;
         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
             if (down && repeatCount == 0) {
-                showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+                showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
             }
             return -1;
         }
@@ -1617,6 +1661,62 @@
             }
         }
 
+        // Invoke shortcuts using Meta.
+        if (down && repeatCount == 0
+                && (metaState & KeyEvent.META_META_ON) != 0) {
+            final KeyCharacterMap kcm = event.getKeyCharacterMap();
+            Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
+                    metaState & ~(KeyEvent.META_META_ON
+                            | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
+            if (shortcutIntent != null) {
+                shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                try {
+                    mContext.startActivity(shortcutIntent);
+                } catch (ActivityNotFoundException ex) {
+                    Slog.w(TAG, "Dropping shortcut key combination because "
+                            + "the activity to which it is registered was not found: "
+                            + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
+                }
+                return -1;
+            }
+        }
+
+        // Handle application launch keys.
+        if (down && repeatCount == 0) {
+            String category = sApplicationLaunchKeyCategories.get(keyCode);
+            if (category != null) {
+                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                try {
+                    mContext.startActivity(intent);
+                } catch (ActivityNotFoundException ex) {
+                    Slog.w(TAG, "Dropping application launch key because "
+                            + "the activity to which it is registered was not found: "
+                            + "keyCode=" + keyCode + ", category=" + category, ex);
+                }
+                return -1;
+            }
+        }
+
+        // Display task switcher for ALT-TAB or Meta-TAB.
+        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
+            if (mRecentAppsDialogHeldModifiers == 0) {
+                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
+                        || KeyEvent.metaStateHasModifiers(
+                                shiftlessModifiers, KeyEvent.META_META_ON)) {
+                    mRecentAppsDialogHeldModifiers = shiftlessModifiers;
+                    showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
+                    return -1;
+                }
+            }
+        } else if (!down && mRecentAppsDialogHeldModifiers != 0
+                && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
+            mRecentAppsDialogHeldModifiers = 0;
+            showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
+        }
+
+        // Let the application handle the key.
         return 0;
     }
 
@@ -1638,39 +1738,6 @@
             final KeyCharacterMap kcm = event.getKeyCharacterMap();
             final int keyCode = event.getKeyCode();
             final int metaState = event.getMetaState();
-            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
-                    && event.getRepeatCount() == 0;
-
-            if (initialDown) {
-                // Invoke shortcuts using Meta as a fallback.
-                if ((metaState & KeyEvent.META_META_ON) != 0) {
-                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
-                            metaState & ~(KeyEvent.META_META_ON
-                                    | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
-                    if (shortcutIntent != null) {
-                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        try {
-                            mContext.startActivity(shortcutIntent);
-                        } catch (ActivityNotFoundException ex) {
-                            Slog.w(TAG, "Dropping shortcut key combination because "
-                                    + "the activity to which it is registered was not found: "
-                                    + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
-                        }
-                        return null;
-                    }
-                }
-
-                // Display task switcher for ALT-TAB or Meta-TAB.
-                if (keyCode == KeyEvent.KEYCODE_TAB) {
-                    final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
-                    if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
-                            || KeyEvent.metaStateHasModifiers(
-                                    shiftlessModifiers, KeyEvent.META_META_ON)) {
-                        showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/);
-                        return null;
-                    }
-                }
-            }
 
             // Check for fallback actions specified by the key character map.
             if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
@@ -2965,7 +3032,6 @@
         synchronized (mLock) {
             updateOrientationListenerLp();
             updateLockScreenTimeout();
-            updateScreenSaverTimeoutLocked();
         }
     }
 
@@ -3012,7 +3078,6 @@
             mScreenOnEarly = true;
             updateOrientationListenerLp();
             updateLockScreenTimeout();
-            updateScreenSaverTimeoutLocked();
         }
     }
 
@@ -3103,10 +3168,7 @@
             }
 
             final int preferredRotation;
-            if (mHdmiPlugged) {
-                // Ignore sensor when plugged into HDMI.
-                preferredRotation = mHdmiRotation;
-            } else if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) {
+            if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) {
                 // Ignore sensor when lid switch is open and rotation is forced.
                 preferredRotation = mLidOpenRotation;
             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
@@ -3125,6 +3187,10 @@
                 // enable 180 degree rotation while docked.
                 preferredRotation = mDeskDockEnablesAccelerometer
                         ? sensorRotation : mDeskDockRotation;
+            } else if (mHdmiPlugged) {
+                // Ignore sensor when plugged into HDMI.
+                // Note that the dock orientation overrides the HDMI orientation.
+                preferredRotation = mHdmiRotation;
             } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */
                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
@@ -3367,6 +3433,9 @@
                             WindowManager.LayoutParams.FLAG_DIM_BEHIND
                             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
                     mBootMsgDialog.getWindow().setDimAmount(1);
+                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
+                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+                    mBootMsgDialog.getWindow().setAttributes(lp);
                     mBootMsgDialog.setCancelable(false);
                     mBootMsgDialog.show();
                 }
@@ -3407,65 +3476,6 @@
                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
             }
         }
-
-        synchronized (mLock) {
-            // Only posts messages; holds no additional locks.
-            updateScreenSaverTimeoutLocked();
-        }
-    }
-
-    Runnable mScreenSaverActivator = new Runnable() {
-        public void run() {
-            if (!(mScreenSaverEnabled && mScreenOnEarly)) {
-                Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
-                return;
-            }
-
-            if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
-            try {
-                String component = Settings.Secure.getString(
-                        mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
-                if (component == null) {
-                    component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
-                }
-                if (component != null) {
-                    ComponentName cn = ComponentName.unflattenFromString(component);
-                    Intent intent = new Intent(Intent.ACTION_MAIN)
-                        .setComponent(cn)
-                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                            | Intent.FLAG_ACTIVITY_NO_USER_ACTION
-                            );
-                    mContext.startActivity(intent);
-                } else {
-                    Log.e(TAG, "Couldn't start screen saver: none selected");
-                }
-            } catch (android.content.ActivityNotFoundException exc) {
-                // no screensaver? give up
-                Log.e(TAG, "Couldn't start screen saver: none installed");
-            }
-        }
-    };
-
-    // Must call while holding mLock
-    private void updateScreenSaverTimeoutLocked() {
-        if (mScreenSaverActivator == null) return;
-
-        mHandler.removeCallbacks(mScreenSaverActivator);
-        if (mScreenSaverEnabled && mScreenOnEarly && mScreenSaverTimeout > 0) {
-            if (localLOGV)
-                Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
-            mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
-        } else {
-            if (localLOGV) {
-                if (mScreenSaverTimeout == 0)
-                    Log.v(TAG, "screen saver disabled by user");
-                else if (!mScreenOnEarly)
-                    Log.v(TAG, "screen saver disabled while screen off");
-                else
-                    Log.v(TAG, "screen saver disabled by wakelock");
-            }
-        }
     }
 
     Runnable mScreenLockTimeout = new Runnable() {
@@ -3671,11 +3681,6 @@
     }
     
     public void screenOnStartedLw() {
-        // The window manager has just grabbed a wake lock. This is our cue to disable the screen
-        // saver.
-        synchronized (mLock) {
-            mScreenSaverEnabled = false;
-        }
     }
 
     public void screenOnStoppedLw() {
@@ -3684,13 +3689,6 @@
                 long curTime = SystemClock.uptimeMillis();
                 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
             }
-
-            synchronized (mLock) {
-                // even if the keyguard is up, now that all the wakelocks have been released, we
-                // should re-enable the screen saver
-                mScreenSaverEnabled = true;
-                updateScreenSaverTimeoutLocked();
-            }
         }
     }
 
@@ -3711,11 +3709,13 @@
         int diff = visibility ^ mLastSystemUiFlags;
         final boolean needsMenu = (mFocusedWindow.getAttrs().flags
                 & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
-        if (diff == 0 && mLastFocusNeedsMenu == needsMenu) {
+        if (diff == 0 && mLastFocusNeedsMenu == needsMenu
+                && mFocusedApp == mFocusedWindow.getAppToken()) {
             return 0;
         }
         mLastSystemUiFlags = visibility;
         mLastFocusNeedsMenu = needsMenu;
+        mFocusedApp = mFocusedWindow.getAppToken();
         mHandler.post(new Runnable() {
                 public void run() {
                     if (mStatusBarService == null) {
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index aa00fbdd..b9903dd 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -71,8 +71,6 @@
         }
     };
 
-    private int mHeldModifiers;
-
     public RecentApplicationsDialog(Context context) {
         super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
 
@@ -124,17 +122,6 @@
         }
     }
 
-    /**
-     * Sets the modifier keys that are being held to keep the dialog open, or 0 if none.
-     * Used to make the recent apps dialog automatically dismiss itself when the modifiers
-     * all go up.
-     * @param heldModifiers The held key modifiers, such as {@link KeyEvent#META_ALT_ON}.
-     * Should exclude shift.
-     */
-    public void setHeldModifiers(int heldModifiers) {
-        mHeldModifiers = heldModifiers;
-    }
-
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_TAB) {
@@ -174,30 +161,27 @@
         return super.onKeyDown(keyCode, event);
     }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
-            final int numIcons = mIcons.length;
-            RecentTag tag = null;
-            for (int i = 0; i < numIcons; i++) {
-                if (mIcons[i].getVisibility() != View.VISIBLE) {
+    /**
+     * Dismiss the dialog and switch to the selected application.
+     */
+    public void dismissAndSwitch() {
+        final int numIcons = mIcons.length;
+        RecentTag tag = null;
+        for (int i = 0; i < numIcons; i++) {
+            if (mIcons[i].getVisibility() != View.VISIBLE) {
+                break;
+            }
+            if (i == 0 || mIcons[i].hasFocus()) {
+                tag = (RecentTag) mIcons[i].getTag();
+                if (mIcons[i].hasFocus()) {
                     break;
                 }
-                if (i == 0 || mIcons[i].hasFocus()) {
-                    tag = (RecentTag) mIcons[i].getTag();
-                    if (mIcons[i].hasFocus()) {
-                        break;
-                    }
-                }
             }
-            if (tag != null) {
-                switchTo(tag);
-            }
-            dismiss();
-            return true;
         }
-
-        return super.onKeyUp(keyCode, event);
+        if (tag != null) {
+            switchTo(tag);
+        }
+        dismiss();
     }
 
     /**
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 47a7157..ba06996 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -242,20 +242,24 @@
 
         new CheckSimPuk(mPukText.getText().toString(),
                 mPinText.getText().toString()) {
-            void onSimLockChangedResponse(boolean success) {
-                if (mSimUnlockProgressDialog != null) {
-                    mSimUnlockProgressDialog.hide();
-                }
-                if (success) {
-                    // before closing the keyguard, report back that
-                    // the sim is unlocked so it knows right away
-                    mUpdateMonitor.reportSimUnlocked();
-                    mCallback.goToUnlockScreen();
-                } else {
-                    mHeaderText.setText(R.string.badPuk);
-                    mPukText.setText("");
-                    mPinText.setText("");
-                }
+            void onSimLockChangedResponse(final boolean success) {
+                mPinText.post(new Runnable() {
+                    public void run() {
+                        if (mSimUnlockProgressDialog != null) {
+                            mSimUnlockProgressDialog.hide();
+                        }
+                        if (success) {
+                            // before closing the keyguard, report back that
+                            // the sim is unlocked so it knows right away
+                            mUpdateMonitor.reportSimUnlocked();
+                            mCallback.goToUnlockScreen();
+                        } else {
+                            mHeaderText.setText(R.string.badPuk);
+                            mPukText.setText("");
+                            mPinText.setText("");
+                        }
+                    }
+                });
             }
         }.start();
     }
@@ -379,6 +383,9 @@
 
         public void onClick(View v) {
             if (v == mCancelButton) {
+                // clear the PIN/PUK entry fields if the user cancels
+                mPinText.setText("");
+                mPukText.setText("");
                 mCallback.goToLockScreen();
                 return;
             }
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 99e1ce1..9604cdc 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -214,21 +214,25 @@
         getSimUnlockProgressDialog().show();
 
         new CheckSimPin(mPinText.getText().toString()) {
-            void onSimLockChangedResponse(boolean success) {
-                if (mSimUnlockProgressDialog != null) {
-                    mSimUnlockProgressDialog.hide();
-                }
-                if (success) {
-                    // before closing the keyguard, report back that
-                    // the sim is unlocked so it knows right away
-                    mUpdateMonitor.reportSimUnlocked();
-                    mCallback.goToUnlockScreen();
-                } else {
-                    mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
-                    mPinText.setText("");
-                    mEnteredDigits = 0;
-                }
-                mCallback.pokeWakelock();
+            void onSimLockChangedResponse(final boolean success) {
+                mPinText.post(new Runnable() {
+                    public void run() {
+                        if (mSimUnlockProgressDialog != null) {
+                            mSimUnlockProgressDialog.hide();
+                        }
+                        if (success) {
+                            // before closing the keyguard, report back that
+                            // the sim is unlocked so it knows right away
+                            mUpdateMonitor.reportSimUnlocked();
+                            mCallback.goToUnlockScreen();
+                        } else {
+                            mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
+                            mPinText.setText("");
+                            mEnteredDigits = 0;
+                        }
+                        mCallback.pokeWakelock();
+                    }
+                });
             }
         }.start();
     }
@@ -355,6 +359,7 @@
 
         public void onClick(View v) {
             if (v == mCancelButton) {
+                mPinText.setText(""); // clear the PIN entry field if the user cancels
                 mCallback.goToLockScreen();
                 return;
             }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 780c0d2..e9ac3f9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -89,6 +89,12 @@
 
 static const nsecs_t kSetParametersTimeout = seconds(2);
 
+// minimum sleep time for the mixer thread loop when tracks are active but in underrun
+static const uint32_t kMinThreadSleepTimeUs = 5000;
+// maximum divider applied to the active sleep time in the mixer thread loop
+static const uint32_t kMaxThreadSleepTimeShift = 2;
+
+
 // ----------------------------------------------------------------------------
 
 static bool recordingAllowed() {
@@ -1810,6 +1816,18 @@
     return &mOutput->stream->common;
 }
 
+uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
+{
+    // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
+    // decoding and transfer time. So sleeping for half of the latency would likely cause
+    // underruns
+    if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
+        return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
+    } else {
+        return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
@@ -1846,6 +1864,7 @@
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
+    uint32_t sleepTimeShift = 0;
     Vector< sp<EffectChain> > effectChains;
 #ifdef DEBUG_CPU_USAGE
     ThreadCpuUsage cpu;
@@ -1937,6 +1956,7 @@
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
                     sleepTime = idleSleepTime;
+                    sleepTimeShift = 0;
                     continue;
                 }
             }
@@ -1953,6 +1973,10 @@
             // mix buffers...
             mAudioMixer->process();
             sleepTime = 0;
+            // increase sleep time progressively when application underrun condition clears
+            if (sleepTimeShift > 0) {
+                sleepTimeShift--;
+            }
             standbyTime = systemTime() + kStandbyTimeInNsecs;
             //TODO: delay standby when effects have a tail
         } else {
@@ -1960,7 +1984,17 @@
             // buffer size, then write 0s to the output
             if (sleepTime == 0) {
                 if (mixerStatus == MIXER_TRACKS_ENABLED) {
-                    sleepTime = activeSleepTime;
+                    sleepTime = activeSleepTime >> sleepTimeShift;
+                    if (sleepTime < kMinThreadSleepTimeUs) {
+                        sleepTime = kMinThreadSleepTimeUs;
+                    }
+                    // reduce sleep time in case of consecutive application underruns to avoid
+                    // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
+                    // duration we would end up writing less data than needed by the audio HAL if
+                    // the condition persists.
+                    if (sleepTimeShift < kMaxThreadSleepTimeShift) {
+                        sleepTimeShift++;
+                    }
                 } else {
                     sleepTime = idleSleepTime;
                 }
@@ -2400,11 +2434,6 @@
     return NO_ERROR;
 }
 
-uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
-{
-    return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
-}
-
 uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
 {
     return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
@@ -2871,7 +2900,7 @@
 {
     uint32_t time;
     if (audio_is_linear_pcm(mFormat)) {
-        time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
+        time = PlaybackThread::activeSleepTimeUs();
     } else {
         time = 10000;
     }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 897bc78..6cafa7e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -776,7 +776,7 @@
 
         virtual int             getTrackName_l() = 0;
         virtual void            deleteTrackName_l(int name) = 0;
-        virtual uint32_t        activeSleepTimeUs() = 0;
+        virtual uint32_t        activeSleepTimeUs();
         virtual uint32_t        idleSleepTimeUs() = 0;
         virtual uint32_t        suspendSleepTimeUs() = 0;
 
@@ -833,7 +833,6 @@
                                                 Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    activeSleepTimeUs();
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
 
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 04b4855..40268b0 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -4320,12 +4320,23 @@
             mKeyMementos.removeAt(index);
             return true;
         }
+        /* FIXME: We can't just drop the key up event because that prevents creating
+         * popup windows that are automatically shown when a key is held and then
+         * dismissed when the key is released.  The problem is that the popup will
+         * not have received the original key down, so the key up will be considered
+         * to be inconsistent with its observed state.  We could perhaps handle this
+         * by synthesizing a key down but that will cause other problems.
+         *
+         * So for now, allow inconsistent key up events to be dispatched.
+         *
 #if DEBUG_OUTBOUND_EVENT_DETAILS
         LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
                 "keyCode=%d, scanCode=%d",
                 entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
 #endif
         return false;
+        */
+        return true;
     }
 
     case AKEY_EVENT_ACTION_DOWN: {
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 2af5103..4f81178 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -24,9 +24,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.Intent.FilterComparison;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.Intent.FilterComparison;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -39,6 +39,8 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -74,6 +76,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 class AppWidgetService extends IAppWidgetService.Stub
 {
@@ -805,6 +808,45 @@
                     id.host.callbacks = null;
                 }
             }
+
+            // If the host is unavailable, then we call the associated
+            // RemoteViewsFactory.onDataSetChanged() directly
+            if (id.host.callbacks == null) {
+                Set<FilterComparison> keys = mRemoteViewsServicesAppWidgets.keySet();
+                for (FilterComparison key : keys) {
+                    if (mRemoteViewsServicesAppWidgets.get(key).contains(id.appWidgetId)) {
+                        Intent intent = key.getIntent();
+
+                        final ServiceConnection conn = new ServiceConnection() {
+                            @Override
+                            public void onServiceConnected(ComponentName name, IBinder service) {
+                                IRemoteViewsFactory cb =
+                                    IRemoteViewsFactory.Stub.asInterface(service);
+                                try {
+                                    cb.onDataSetChangedAsync();
+                                } catch (RemoteException e) {
+                                    e.printStackTrace();
+                                } catch (RuntimeException e) {
+                                    e.printStackTrace();
+                                }
+                                mContext.unbindService(this);
+                            }
+                            @Override
+                            public void onServiceDisconnected(android.content.ComponentName name) {
+                                // Do nothing
+                            }
+                        };
+
+                        // Bind to the service and call onDataSetChanged()
+                        final long token = Binder.clearCallingIdentity();
+                        try {
+                            mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
+                        } finally {
+                            Binder.restoreCallingIdentity(token);
+                        }
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index d34087f..16eeb7ba 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -163,7 +163,6 @@
             } catch (IllegalArgumentException e) {
                 // ignore; report -1
             }
-            mCacheFileStats.restat(CACHE_PATH);
             EventLog.writeEvent(EventLogTags.FREE_STORAGE_LEFT,
                                 mFreeMem, mFreeSystem, mFreeCache);
         }
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5408436..4dad209 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -50,12 +50,12 @@
 # NotificationManagerService.java
 # ---------------------------
 # when a NotificationManager.notify is called
-2750 notification_enqueue (pkg|3),(id|1|5),(notification|3)
+2750 notification_enqueue (pkg|3),(id|1|5),(tag|3),(notification|3)
 # when someone tries to cancel a notification, the notification manager sometimes
 # calls this with flags too
-2751 notification_cancel (pkg|3),(id|1|5),(required_flags|1)
+2751 notification_cancel (pkg|3),(id|1|5),(tag|3),(required_flags|1),(forbidden_flags|1)
 # when someone tries to cancel all of the notifications for a particular package
-2752 notification_cancel_all (pkg|3),(required_flags|1)
+2752 notification_cancel_all (pkg|3),(required_flags|1),(forbidden_flags|1)
 
 
 # ---------------------------
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index ddac35c..f5c4ed4 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -382,6 +382,7 @@
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                 mScreenOn = true;
+                refreshImeWindowVisibilityLocked();
             } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 mScreenOn = false;
                 setImeWindowVisibilityStatusHiddenLocked();
@@ -640,6 +641,21 @@
         updateImeWindowStatusLocked();
     }
 
+    private void refreshImeWindowVisibilityLocked() {
+        final Configuration conf = mRes.getConfiguration();
+        final boolean haveHardKeyboard = conf.keyboard
+                != Configuration.KEYBOARD_NOKEYS;
+        final boolean hardKeyShown = haveHardKeyboard
+                && conf.hardKeyboardHidden
+                        != Configuration.HARDKEYBOARDHIDDEN_YES;
+        final boolean isScreenLocked = mKeyguardManager != null
+                && mKeyguardManager.isKeyguardLocked()
+                && mKeyguardManager.isKeyguardSecure();
+        mImeWindowVis = (!isScreenLocked && (mInputShown || hardKeyShown)) ?
+                (InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0;
+        updateImeWindowStatusLocked();
+    }
+
     private void updateImeWindowStatusLocked() {
         setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
     }
@@ -1285,16 +1301,7 @@
                     }
                     if (mCurMethod != null) {
                         try {
-                            final Configuration conf = mRes.getConfiguration();
-                            final boolean haveHardKeyboard = conf.keyboard
-                                    != Configuration.KEYBOARD_NOKEYS;
-                            final boolean hardKeyShown = haveHardKeyboard
-                                    && conf.hardKeyboardHidden
-                                            != Configuration.HARDKEYBOARDHIDDEN_YES;
-                            mImeWindowVis = (mInputShown || hardKeyShown) ? (
-                                    InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE)
-                                    : 0;
-                            updateImeWindowStatusLocked();
+                            refreshImeWindowVisibilityLocked();
                             // If subtype is null, try to find the most applicable one from
                             // getCurrentInputMethodSubtype.
                             if (subtype == null) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index da960ae..75e5366 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -856,13 +856,17 @@
 
         NetworkInterface internalNetworkInterface =
                 NetworkInterface.getByName(internalInterface);
-        Collection<InterfaceAddress>interfaceAddresses =
-                internalNetworkInterface.getInterfaceAddresses();
-        cmd += " " + interfaceAddresses.size();
-        for (InterfaceAddress ia : interfaceAddresses) {
-            InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
-                    ia.getNetworkPrefixLength());
-            cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
+        if (internalNetworkInterface == null) {
+            cmd += " 0";
+        } else {
+            Collection<InterfaceAddress>interfaceAddresses =
+                    internalNetworkInterface.getInterfaceAddresses();
+            cmd += " " + interfaceAddresses.size();
+            for (InterfaceAddress ia : interfaceAddresses) {
+                InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
+                        ia.getNetworkPrefixLength());
+                cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
+            }
         }
 
         mConnector.doCommand(cmd);
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7d1d976..5039294 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -707,7 +707,8 @@
         //     behalf of the download manager without affecting other apps.
         if (!pkg.equals("com.android.providers.downloads")
                 || Log.isLoggable("DownloadManager", Log.VERBOSE)) {
-            EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, notification.toString());
+            EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag,
+                    notification.toString());
         }
 
         if (pkg == null || notification == null) {
@@ -944,7 +945,8 @@
      */
     private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
             int mustNotHaveFlags, boolean sendDelete) {
-        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, mustHaveFlags);
+        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
+                mustHaveFlags, mustNotHaveFlags);
 
         synchronized (mNotificationList) {
             int index = indexOfNotificationLocked(pkg, tag, id);
@@ -972,7 +974,8 @@
      */
     boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
             int mustNotHaveFlags, boolean doit) {
-        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags);
+        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
+                mustNotHaveFlags);
 
         synchronized (mNotificationList) {
             final int N = mNotificationList.size();
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 6b23b33..2a0d2a0 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1689,6 +1689,11 @@
                 // before showing it to the user.  We want the light off
                 // until it is ready to be shown to the user, not it using
                 // whatever the last value it had.
+                if (DEBUG_SCREEN_ON) {
+                    Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
+                            + Integer.toHexString(mPowerState)
+                            + " mSkippedScreenOn=" + mSkippedScreenOn);
+                }
                 mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
             }
         }
@@ -2038,12 +2043,14 @@
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
-            mScreenBrightness.setTargetLocked(brightness, steps,
-                    INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
-            if (DEBUG_SCREEN_ON) {
-                RuntimeException e = new RuntimeException("here");
-                e.fillInStackTrace();
-                Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+            if (!mSkippedScreenOn) {
+                mScreenBrightness.setTargetLocked(brightness, steps,
+                        INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+                if (DEBUG_SCREEN_ON) {
+                    RuntimeException e = new RuntimeException("here");
+                    e.fillInStackTrace();
+                    Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+                }
             }
         }
 
@@ -2086,6 +2093,11 @@
                             ? LightsService.BRIGHTNESS_MODE_SENSOR
                             : LightsService.BRIGHTNESS_MODE_USER);
         if ((mask & SCREEN_BRIGHT_BIT) != 0) {
+            if (DEBUG_SCREEN_ON) {
+                RuntimeException e = new RuntimeException("here");
+                e.fillInStackTrace();
+                Slog.i(TAG, "Set LCD brightness: " + value, e);
+            }
             mLcdLight.setBrightness(value, brightnessMode);
         }
         if ((mask & BUTTON_BRIGHT_BIT) != 0) {
@@ -2137,7 +2149,7 @@
             delta = (targetValue -
                     (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
                     / stepsToTarget;
-            if (mSpew) {
+            if (mSpew || DEBUG_SCREEN_ON) {
                 String noticeMe = nominalCurrentValue == curValue ? "" : "  ******************";
                 Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue
                         + " target=" + target + " targetValue=" + targetValue + " delta=" + delta
@@ -2527,8 +2539,10 @@
                 }
 
                 if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
-                    mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
-                            INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
+                    if (!mSkippedScreenOn) {
+                        mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
+                                INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
+                    }
                 }
                 if (mButtonBrightnessOverride < 0) {
                     mButtonLight.setBrightness(buttonValue);
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index d04b440..8384ebc 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -392,9 +392,16 @@
             Slog.d(TAG, "FinishSpellCheckerService");
         }
         synchronized(mSpellCheckerMap) {
+            final ArrayList<SpellCheckerBindGroup> removeList =
+                    new ArrayList<SpellCheckerBindGroup>();
             for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
                 if (group == null) continue;
-                group.removeListener(listener);
+                // Use removeList to avoid modifying mSpellCheckerBindGroups in this loop.
+                removeList.add(group);
+            }
+            final int removeSize = removeList.size();
+            for (int i = 0; i < removeSize; ++i) {
+                removeList.get(i).removeListener(listener);
             }
         }
     }
@@ -669,6 +676,7 @@
             }
         }
 
+        // cleanLocked may remove elements from mSpellCheckerBindGroups
         private void cleanLocked() {
             if (DBG) {
                 Slog.d(TAG, "cleanLocked");
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index e6392d7..c7fbc00 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -65,7 +65,7 @@
 
     // Enable launching of applications when entering the dock.
     private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
-    private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false;
+    private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
 
     private static final int MSG_UPDATE_TWILIGHT = 0;
     private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 7fa404e..4925a4e 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -476,6 +476,13 @@
     ParcelFileDescriptor updateWallpaperBitmapLocked(String name) {
         if (name == null) name = "";
         try {
+            if (!WALLPAPER_DIR.exists()) {
+                WALLPAPER_DIR.mkdir();
+                FileUtils.setPermissions(
+                        WALLPAPER_DIR.getPath(),
+                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                        -1, -1);
+            }
             ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
                     MODE_CREATE|MODE_READ_WRITE);
             mName = name;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 3c65255..aef3426 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -152,8 +152,12 @@
     /* Wifi disabled due to airplane mode on */
     private static final int WIFI_DISABLED_AIRPLANE_ON      = 3;
 
-    private AtomicInteger mWifiState = new AtomicInteger(WIFI_DISABLED);
+    /* Persisted state that tracks the wifi & airplane interaction from settings */
+    private AtomicInteger mPersistWifiState = new AtomicInteger(WIFI_DISABLED);
+    /* Tracks current airplane mode state */
     private AtomicBoolean mAirplaneModeOn = new AtomicBoolean(false);
+    /* Tracks whether wifi is enabled from WifiStateMachine's perspective */
+    private boolean mWifiEnabled;
 
     private boolean mIsReceiverRegistered = false;
 
@@ -373,8 +377,8 @@
                         mAirplaneModeOn.set(isAirplaneModeOn());
                         /* On airplane mode disable, restore wifi state if necessary */
                         if (!mAirplaneModeOn.get() && (testAndClearWifiSavedState() ||
-                            mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) {
-                                persistWifiEnabled(true);
+                            mPersistWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) {
+                                persistWifiState(true);
                         }
                         updateWifiState();
                     }
@@ -391,7 +395,12 @@
                     @Override
                     public void onReceive(Context context, Intent intent) {
                         if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                            // reset & clear notification on any wifi state change
+                            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                                    WifiManager.WIFI_STATE_DISABLED);
+
+                            mWifiEnabled = (wifiState == WifiManager.WIFI_STATE_ENABLED);
+
+                           // reset & clear notification on any wifi state change
                             resetNotification();
                         } else if (intent.getAction().equals(
                                 WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
@@ -435,7 +444,7 @@
      */
     public void checkAndStartWifi() {
         mAirplaneModeOn.set(isAirplaneModeOn());
-        mWifiState.set(getPersistedWifiState());
+        mPersistWifiState.set(getPersistedWifiState());
         /* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */
         boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState();
         Slog.i(TAG, "WifiService starting up with Wi-Fi " +
@@ -472,29 +481,30 @@
 
     private boolean shouldWifiBeEnabled() {
         if (mAirplaneModeOn.get()) {
-            return mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE;
+            return mPersistWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE;
         } else {
-            return mWifiState.get() != WIFI_DISABLED;
+            return mPersistWifiState.get() != WIFI_DISABLED;
         }
     }
 
-    private void persistWifiEnabled(boolean enabled) {
+    private void persistWifiState(boolean enabled) {
         final ContentResolver cr = mContext.getContentResolver();
         boolean airplane = mAirplaneModeOn.get() && isAirplaneToggleable();
         if (enabled) {
             if (airplane) {
-                mWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
+                mPersistWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
             } else {
-                mWifiState.set(WIFI_ENABLED);
+                mPersistWifiState.set(WIFI_ENABLED);
             }
         } else {
             if (airplane) {
-                mWifiState.set(WIFI_DISABLED_AIRPLANE_ON);
+                mPersistWifiState.set(WIFI_DISABLED_AIRPLANE_ON);
             } else {
-                mWifiState.set(WIFI_DISABLED);
+                mPersistWifiState.set(WIFI_DISABLED);
             }
         }
-        Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mWifiState.get());
+
+        Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mPersistWifiState.get());
     }
 
 
@@ -545,7 +555,6 @@
      */
     public synchronized boolean setWifiEnabled(boolean enable) {
         enforceChangePermission();
-
         if (DBG) {
             Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
         }
@@ -559,16 +568,20 @@
          * Caller might not have WRITE_SECURE_SETTINGS,
          * only CHANGE_WIFI_STATE is enforced
          */
-        long ident = Binder.clearCallingIdentity();
-        persistWifiEnabled(enable);
-        Binder.restoreCallingIdentity(ident);
+
+        /* Avoids overriding of airplane state when wifi is already in the expected state */
+        if (enable != mWifiEnabled) {
+            long ident = Binder.clearCallingIdentity();
+            persistWifiState(enable);
+            Binder.restoreCallingIdentity(ident);
+        }
 
         if (enable) {
             if (!mIsReceiverRegistered) {
                 registerForBroadcasts();
                 mIsReceiverRegistered = true;
             }
-        } else if (mIsReceiverRegistered){
+        } else if (mIsReceiverRegistered) {
             mContext.unregisterReceiver(mReceiver);
             mIsReceiverRegistered = false;
         }
@@ -840,7 +853,7 @@
          * of WifiLock & device idle status unless wifi enabled status is toggled
          */
 
-        mWifiStateMachine.setDriverStart(true);
+        mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
         mWifiStateMachine.reconnectCommand();
     }
 
@@ -854,7 +867,7 @@
          * TODO: if a stop is issued, wifi is brought up only by startWifi
          * unless wifi enabled status is toggled
          */
-        mWifiStateMachine.setDriverStart(false);
+        mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
     }
 
 
@@ -1074,12 +1087,11 @@
                 mWifiStateMachine.setWifiEnabled(true);
                 mWifiStateMachine.setScanOnlyMode(
                         strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
-                mWifiStateMachine.setDriverStart(true);
+                mWifiStateMachine.setDriverStart(true, mEmergencyCallbackMode);
                 mWifiStateMachine.setHighPerfModeEnabled(strongestLockMode
                         == WifiManager.WIFI_MODE_FULL_HIGH_PERF);
             } else {
-                mWifiStateMachine.requestCmWakeLock();
-                mWifiStateMachine.setDriverStart(false);
+                mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
             }
         } else {
             mWifiStateMachine.setWifiEnabled(false);
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index fd528cc..b70ed96 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -115,8 +115,8 @@
 
     private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
 
-    private final SparseArray<IAccessibilityInteractionConnection> mWindowIdToInteractionConnectionMap =
-        new SparseArray<IAccessibilityInteractionConnection>();
+    private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
+        new SparseArray<AccessibilityConnectionWrapper>();
 
     private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
 
@@ -439,16 +439,11 @@
             final IWindow addedWindowToken = windowToken;
             final IAccessibilityInteractionConnection addedConnection = connection;
             final int windowId = sNextWindowId++;
-            addedConnection.asBinder().linkToDeath(new DeathRecipient() {
-                public void binderDied() {
-                    synchronized (mLock) {
-                        addedConnection.asBinder().unlinkToDeath(this, 0);
-                        removeAccessibilityInteractionConnection(addedWindowToken);
-                    }
-                }
-            }, 0);
+            AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(windowId,
+                    connection);
+            wrapper.linkToDeath();
             mWindowIdToWindowTokenMap.put(windowId, addedWindowToken.asBinder());
-            mWindowIdToInteractionConnectionMap.put(windowId, connection);
+            mWindowIdToInteractionConnectionWrapperMap.put(windowId, wrapper);
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
             }
@@ -462,18 +457,17 @@
             for (int i = 0; i < count; i++) {
                 if (mWindowIdToWindowTokenMap.valueAt(i) == windowToken.asBinder()) {
                     final int windowId = mWindowIdToWindowTokenMap.keyAt(i);
-                    mWindowIdToWindowTokenMap.remove(windowId);
-                    mWindowIdToInteractionConnectionMap.remove(windowId);
-                    if (DEBUG) {
-                        Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
-                    }
+                    AccessibilityConnectionWrapper wrapper =
+                        mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+                    wrapper.unlinkToDeath();
+                    removeAccessibilityInteractionConnectionLocked(windowId);
                     return;
                 }
             }
         }
     }
 
-    public IAccessibilityServiceConnection registerEventListener(IEventListener listener) {
+    public void registerEventListener(IEventListener listener) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
                 FUNCTION_REGISTER_EVENT_LISTENER);
         ComponentName componentName = new ComponentName("foo.bar",
@@ -501,7 +495,19 @@
         accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
         Service service = new Service(componentName, accessibilityServiceInfo, true);
         service.onServiceConnected(componentName, listener.asBinder());
-        return service;
+    }
+
+    /**
+     * Removes an AccessibilityInteractionConnection.
+     *
+     * @param windowId The id of the window to which the connection is targeted.
+     */
+    private void removeAccessibilityInteractionConnectionLocked(int windowId) {
+        mWindowIdToWindowTokenMap.remove(windowId);
+        mWindowIdToInteractionConnectionWrapperMap.remove(windowId);
+        if (DEBUG) {
+            Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
+        }
     }
 
     /**
@@ -594,6 +600,13 @@
      */
     private void notifyEventListenerLocked(Service service, int eventType) {
         IEventListener listener = service.mServiceInterface;
+
+        // If the service died/was disabled while the message for dispatching
+        // the accessibility event was propagating the listener may be null.
+        if (listener == null) {
+            return;
+        }
+
         AccessibilityEvent event = service.mPendingEvents.get(eventType);
 
         // Check for null here because there is a concurrent scenario in which this
@@ -618,7 +631,7 @@
         service.mPendingEvents.remove(eventType);
         try {
             if (mSecurityPolicy.canRetrieveWindowContent(service)) {
-                event.setConnection(service);
+                event.setConnectionId(service.mId);
             } else {
                 event.setSource(null);
             }
@@ -666,6 +679,7 @@
         mComponentNameToServiceMap.remove(service.mComponentName);
         mHandler.removeMessages(service.mId);
         service.unlinkToOwnDeath();
+        service.dispose();
         updateInputFilterLocked();
         return removed;
     }
@@ -895,6 +909,33 @@
         sendStateToClientsLocked();
     }
 
+    private class AccessibilityConnectionWrapper implements DeathRecipient {
+        private final int mWindowId;
+        private final IAccessibilityInteractionConnection mConnection;
+
+        public AccessibilityConnectionWrapper(int windowId,
+                IAccessibilityInteractionConnection connection) {
+            mWindowId = windowId;
+            mConnection = connection;
+        }
+
+        public void linkToDeath() throws RemoteException {
+            mConnection.asBinder().linkToDeath(this, 0);
+        }
+
+        public void unlinkToDeath() {
+            mConnection.asBinder().unlinkToDeath(this, 0);
+        }
+
+        @Override
+        public void binderDied() {
+            unlinkToDeath();
+            synchronized (mLock) {
+                removeAccessibilityInteractionConnectionLocked(mWindowId);
+            }
+        }
+    }
+
     /**
      * This class represents an accessibility service. It stores all per service
      * data required for the service management, provides API for starting/stopping the
@@ -997,7 +1038,6 @@
                 if (!mIsAutomation) {
                     mContext.unbindService(this);
                 }
-                mService = null;
                 return true;
             }
             return false;
@@ -1021,7 +1061,7 @@
             mService = service;
             mServiceInterface = IEventListener.Stub.asInterface(service);
             try {
-                mServiceInterface.setConnection(this);
+                mServiceInterface.setConnection(this, mId);
                 synchronized (mLock) {
                     tryAddServiceLocked(this);
                 }
@@ -1123,14 +1163,16 @@
                 if (!permissionGranted) {
                     return 0;
                 } else {
-                    connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
-                    if (connection == null) {
+                    AccessibilityConnectionWrapper wrapper =
+                        mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+                    if (wrapper == null) {
                         if (DEBUG) {
                             Slog.e(LOG_TAG, "No interaction connection to window: "
                                     + accessibilityWindowId);
                         }
                         return 0;
                     }
+                    connection = wrapper.mConnection;
                 }
             }
             final int interrogatingPid = Binder.getCallingPid();
@@ -1159,14 +1201,16 @@
                 if (!permissionGranted) {
                     return false;
                 } else {
-                    connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
-                    if (connection == null) {
+                    AccessibilityConnectionWrapper wrapper =
+                        mWindowIdToInteractionConnectionWrapperMap.get(accessibilityWindowId);
+                    if (wrapper == null) {
                         if (DEBUG) {
                             Slog.e(LOG_TAG, "No interaction connection to window: "
                                     + accessibilityWindowId);
                         }
                         return false;
                     }
+                    connection = wrapper.mConnection;
                 }
             }
             final int interrogatingPid = Binder.getCallingPid();
@@ -1197,9 +1241,21 @@
             mService.unlinkToDeath(this, 0);
         }
 
+        public void dispose() {
+            try {
+                // Clear the proxy in the other process so this
+                // IAccessibilityServiceConnection can be garbage collected.
+                mServiceInterface.setConnection(null, mId);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            mService = null;
+            mServiceInterface = null;
+        }
+
         public void binderDied() {
             synchronized (mLock) {
-                mService.unlinkToDeath(this, 0);
+                unlinkToOwnDeath();
                 tryRemoveServiceLocked(this);
                 // We no longer have an automation service, so restore
                 // the state based on values in the settings database.
@@ -1214,7 +1270,9 @@
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
             }
-            return mWindowIdToInteractionConnectionMap.get(windowId);
+            AccessibilityConnectionWrapper wrapper =
+                mWindowIdToInteractionConnectionWrapperMap.get(windowId);
+            return (wrapper != null) ? wrapper.mConnection : null;
         }
 
         private float getCompatibilityScale(int windowId) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8023477..df58e83 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -129,7 +129,6 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -415,7 +414,12 @@
      * is in a different process from the one they are currently in.
      */
     ProcessRecord mPreviousProcess;
-    
+
+    /**
+     * The time at which the previous process was last visible.
+     */
+    long mPreviousProcessVisibleTime;
+
     /**
      * Packages that the user has asked to have run in screen size
      * compatibility mode instead of filling the screen.
@@ -1222,6 +1226,23 @@
                     @Override public void run() {
                         StringBuilder dropBuilder = new StringBuilder(1024);
                         StringBuilder logBuilder = new StringBuilder(1024);
+                        StringWriter oomSw = new StringWriter();
+                        PrintWriter oomPw = new PrintWriter(oomSw);
+                        StringWriter catSw = new StringWriter();
+                        PrintWriter catPw = new PrintWriter(catSw);
+                        String[] emptyArgs = new String[] { };
+                        StringBuilder tag = new StringBuilder(128);
+                        StringBuilder stack = new StringBuilder(128);
+                        tag.append("Low on memory -- ");
+                        dumpApplicationMemoryUsage(null, oomPw, "  ", emptyArgs, true, catPw,
+                                tag, stack);
+                        dropBuilder.append(stack);
+                        dropBuilder.append('\n');
+                        dropBuilder.append('\n');
+                        String oomString = oomSw.toString();
+                        dropBuilder.append(oomString);
+                        dropBuilder.append('\n');
+                        logBuilder.append(oomString);
                         try {
                             java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
                                     "procrank", });
@@ -1244,27 +1265,15 @@
                             converter.close();
                         } catch (IOException e) {
                         }
-                        StringWriter sw = new StringWriter();
-                        PrintWriter pw = new PrintWriter(sw);
-                        StringWriter catSw = new StringWriter();
-                        PrintWriter catPw = new PrintWriter(catSw);
-                        String[] emptyArgs = new String[] { };
-                        StringBuilder tag = new StringBuilder(128);
                         synchronized (ActivityManagerService.this) {
+                            catPw.println();
                             dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
                             catPw.println();
                             dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
                             catPw.println();
                             dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
-                            catPw.println();
                         }
-                        tag.append("Low on memory -- ");
-                        dumpApplicationMemoryUsage(null, pw, "  ", emptyArgs, true, catPw, tag);
-                        String memUsage = sw.toString();
-                        dropBuilder.append('\n');
-                        dropBuilder.append(memUsage);
                         dropBuilder.append(catSw.toString());
-                        logBuilder.append(memUsage);
                         addErrorToDropBox("lowmem", null, "system_server", null,
                                 null, tag.toString(), dropBuilder.toString(), null, null);
                         Slog.i(TAG, logBuilder.toString());
@@ -1420,7 +1429,7 @@
             }
 
             mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args,
-                    false, null, null);
+                    false, null, null, null);
         }
     }
 
@@ -2716,6 +2725,10 @@
                     }
                     if (!r.finishing) {
                         Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
+                        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
+                                System.identityHashCode(r),
+                                r.task.taskId, r.shortComponentName,
+                                "proc died without state saved");
                     }
                     r.makeFinishing();
                     mMainStack.mHistory.remove(i);
@@ -8353,6 +8366,12 @@
         pw.println();
         pw.println("  mHomeProcess: " + mHomeProcess);
         pw.println("  mPreviousProcess: " + mPreviousProcess);
+        if (dumpAll) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("  mPreviousProcessVisibleTime: ");
+            TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
+            pw.println(sb);
+        }
         if (mHeavyWeightProcess != null) {
             pw.println("  mHeavyWeightProcess: " + mHeavyWeightProcess);
         }
@@ -9416,7 +9435,7 @@
             } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
                 oomAdj = buildOomTag("svc  ", null, r.setAdj, ProcessList.SERVICE_ADJ);
             } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
-                oomAdj = buildOomTag("bckup", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
+                oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
             } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                 oomAdj = buildOomTag("hvy  ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
             } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -9645,7 +9664,8 @@
         1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
     };
 
-    static final void appendMemBucket(StringBuilder out, long memKB, String label) {
+    static final void appendMemBucket(StringBuilder out, long memKB, String label,
+            boolean stackLike) {
         int start = label.lastIndexOf('.');
         if (start >= 0) start++;
         else start = 0;
@@ -9654,13 +9674,13 @@
             if (DUMP_MEM_BUCKETS[i] >= memKB) {
                 long bucket = DUMP_MEM_BUCKETS[i]/1024;
                 out.append(bucket);
-                out.append("MB ");
+                out.append(stackLike ? "MB." : "MB ");
                 out.append(label, start, end);
                 return;
             }
         }
         out.append(memKB/1024);
-        out.append("MB ");
+        out.append(stackLike ? "MB." : "MB ");
         out.append(label, start, end);
     }
 
@@ -9679,7 +9699,7 @@
 
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, String prefix, String[] args, boolean brief,
-            PrintWriter categoryPw, StringBuilder outTag) {
+            PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
         boolean dumpAll = false;
         boolean oomOnly = false;
         
@@ -9816,8 +9836,14 @@
                 }
             }
 
-            if (outTag != null) {
-                appendMemBucket(outTag, totalPss, "total");
+            if (outTag != null || outStack != null) {
+                if (outTag != null) {
+                    appendMemBucket(outTag, totalPss, "total", false);
+                }
+                if (outStack != null) {
+                    appendMemBucket(outStack, totalPss, "total", true);
+                }
+                boolean firstLine = true;
                 for (int i=0; i<oomMems.size(); i++) {
                     MemItem miCat = oomMems.get(i);
                     if (miCat.subitems == null || miCat.subitems.size() < 1) {
@@ -9826,13 +9852,47 @@
                     if (miCat.id < ProcessList.SERVICE_ADJ
                             || miCat.id == ProcessList.HOME_APP_ADJ
                             || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
-                        outTag.append(" / ");
+                        if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
+                            outTag.append(" / ");
+                        }
+                        if (outStack != null) {
+                            if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
+                                if (firstLine) {
+                                    outStack.append(":");
+                                    firstLine = false;
+                                }
+                                outStack.append("\n\t at ");
+                            } else {
+                                outStack.append("$");
+                            }
+                        }
                         for (int j=0; j<miCat.subitems.size(); j++) {
                             MemItem mi = miCat.subitems.get(j);
                             if (j > 0) {
-                                outTag.append(" ");
+                                if (outTag != null) {
+                                    outTag.append(" ");
+                                }
+                                if (outStack != null) {
+                                    outStack.append("$");
+                                }
                             }
-                            appendMemBucket(outTag, mi.pss, mi.shortLabel);
+                            if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
+                                appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
+                            }
+                            if (outStack != null) {
+                                appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
+                            }
+                        }
+                        if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
+                            outStack.append("(");
+                            for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
+                                if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
+                                    outStack.append(DUMP_MEM_OOM_LABEL[k]);
+                                    outStack.append(":");
+                                    outStack.append(DUMP_MEM_OOM_ADJ[k]);
+                                }
+                            }
+                            outStack.append(")");
                         }
                     }
                 }
@@ -13551,6 +13611,7 @@
                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                         app.adjType = "stopping";
                     }
+                    app.hidden = false;
                     app.foregroundActivities = true;
                 }
             }
@@ -14199,7 +14260,7 @@
 
         if (app.curAdj != app.setAdj) {
             if (Process.setOomAdj(app.pid, app.curAdj)) {
-                if (true || DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
                     TAG, "Set " + app.pid + " " + app.processName +
                     " adj " + app.curAdj + ": " + app.adjType);
                 app.setAdj = app.curAdj;
@@ -14358,10 +14419,16 @@
                             app.thread.scheduleTrimMemory(curLevel);
                         } catch (RemoteException e) {
                         }
-                        if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
-                            // For these apps we will also finish their activities
-                            // to help them free memory.
-                            mMainStack.destroyActivitiesLocked(app, false, "trim");
+                        if (false) {
+                            // For now we won't do this; our memory trimming seems
+                            // to be good enough at this point that destroying
+                            // activities causes more harm than good.
+                            if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+                                    && app != mHomeProcess && app != mPreviousProcess) {
+                                // For these apps we will also finish their activities
+                                // to help them free memory.
+                                mMainStack.destroyActivitiesLocked(app, false, "trim");
+                            }
                         }
                     }
                     app.trimMemoryLevel = curLevel;
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 951a946..c819114 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -80,6 +80,7 @@
     ThumbnailHolder thumbHolder; // where our thumbnails should go.
     long launchTime;        // when we starting launching this activity
     long startTime;         // last time this activity was started
+    long lastVisibleTime;   // last time this activity became visible
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     Configuration configuration; // configuration activity was last running in
     CompatibilityInfo compat;// last used compatibility mode
@@ -188,6 +189,10 @@
                     TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
                     TimeUtils.formatDuration(startTime, pw); pw.println("");
         }
+        if (lastVisibleTime != 0) {
+            pw.print(prefix); pw.print("lastVisibleTime=");
+                    TimeUtils.formatDuration(lastVisibleTime, pw); pw.println("");
+        }
         if (waitingVisible || nowVisible) {
             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
                     pw.print(" nowVisible="); pw.println(nowVisible);
@@ -632,6 +637,7 @@
                     ActivityManagerService.TAG, "windowsVisible(): " + this);
             if (!nowVisible) {
                 nowVisible = true;
+                lastVisibleTime = SystemClock.uptimeMillis();
                 if (!idle) {
                     // Instead of doing the full stop routine here, let's just
                     // hide any activities we now can, and let them stop when
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c7ce3c3..6c11953 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -949,6 +949,22 @@
             if (r.configDestroy) {
                 destroyActivityLocked(r, true, false, "stop-config");
                 resumeTopActivityLocked(null);
+            } else {
+                // Now that this process has stopped, we may want to consider
+                // it to be the previous app to try to keep around in case
+                // the user wants to return to it.
+                ProcessRecord fgApp = null;
+                if (mResumedActivity != null) {
+                    fgApp = mResumedActivity.app;
+                } else if (mPausingActivity != null) {
+                    fgApp = mPausingActivity.app;
+                }
+                if (r.app != null && fgApp != null && r.app != fgApp
+                        && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
+                        && r.app != mService.mHomeProcess) {
+                    mService.mPreviousProcess = r.app;
+                    mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+                }
             }
         }
     }
@@ -1363,14 +1379,6 @@
                         + ", nowVisible=" + next.nowVisible);
                 }
             }
-
-            if (!prev.finishing && prev.app != null && prev.app != next.app
-                    && prev.app != mService.mHomeProcess) {
-                // We are switching to a new activity that is in a different
-                // process than the previous one.  Note the previous process,
-                // so we can try to keep it around.
-                mService.mPreviousProcess = prev.app;
-            }
         }
 
         // Launching this app's activity, make sure the app is no longer
@@ -1924,8 +1932,9 @@
                     // should be left as-is.
                     replyChainEnd = -1;
                 }
-                
-            } else if (target.resultTo != null) {
+
+            } else if (target.resultTo != null && (below == null
+                    || below.task == target.task)) {
                 // If this activity is sending a reply to a previous
                 // activity, we can't do anything with it now until
                 // we reach the start of the reply chain.
@@ -1955,6 +1964,8 @@
                         replyChainEnd = targetI;
                     }
                     ActivityRecord p = null;
+                    if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
+                            + targetI + " to " + replyChainEnd);
                     for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
                         p = mHistory.get(srcPos);
                         if (p.finishing) {
@@ -1973,6 +1984,8 @@
                     if (replyChainEnd < 0) {
                         replyChainEnd = targetI;
                     }
+                    if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
+                            + targetI + " to " + replyChainEnd);
                     for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
                         ActivityRecord p = mHistory.get(srcPos);
                         if (p.finishing) {
@@ -1994,6 +2007,7 @@
                         p.setTask(task, null, false);
                         mHistory.add(lastReparentPos, p);
                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
+                                + " from " + srcPos + " to " + lastReparentPos
                                 + " in to resetting task " + task);
                         mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
                         mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
@@ -2023,6 +2037,11 @@
                         }
                     }
                 }
+
+            } else if (below != null && below.task != target.task) {
+                // We hit the botton of a task; the reply chain can't
+                // pass through it.
+                replyChainEnd = -1;
             }
             
             target = below;
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index a860763..de3129b 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -54,8 +54,17 @@
     
     void setIntent(Intent _intent, ActivityInfo info) {
         stringName = null;
-        
+
         if (info.targetActivity == null) {
+            if (_intent != null) {
+                // If this Intent has a selector, we want to clear it for the
+                // recent task since it is not relevant if the user later wants
+                // to re-launch the app.
+                if (_intent.getSelector() != null) {
+                    _intent = new Intent(_intent);
+                    _intent.setSelector(null);
+                }
+            }
             intent = _intent;
             realActivity = _intent != null ? _intent.getComponent() : null;
             origActivity = null;
@@ -65,6 +74,7 @@
             if (_intent != null) {
                 Intent targetIntent = new Intent(_intent);
                 targetIntent.setComponent(targetComponent);
+                targetIntent.setSelector(null);
                 intent = targetIntent;
                 realActivity = targetComponent;
                 origActivity = _intent.getComponent();
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 55e0678..72cf512 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -482,6 +482,7 @@
                 if (state.exists()) {
                     throw new IllegalStateException("Cannot delete the state");
                 }
+                new File("/data/misc/vpn/abort").delete();
 
                 // Check if we need to restart any of the daemons.
                 boolean restart = false;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 7005541..6b61c47 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -2162,6 +2162,9 @@
             int flags, List<ResolveInfo> query, int priority) {
         // writer
         synchronized (mPackages) {
+            if (intent.getSelector() != null) {
+                intent = intent.getSelector(); 
+            }
             if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
             List<PreferredActivity> prefs =
                     mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
@@ -2242,7 +2245,13 @@
 
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags) {
-        final ComponentName comp = intent.getComponent();
+        ComponentName comp = intent.getComponent();
+        if (comp == null) {
+            if (intent.getSelector() != null) {
+                intent = intent.getSelector(); 
+                comp = intent.getComponent();
+            }
+        }
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
             final ActivityInfo ai = getActivityInfo(comp, flags);
@@ -2440,6 +2449,12 @@
 
     public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
         ComponentName comp = intent.getComponent();
+        if (comp == null) {
+            if (intent.getSelector() != null) {
+                intent = intent.getSelector(); 
+                comp = intent.getComponent();
+            }
+        }
         if (comp != null) {
             List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
             ActivityInfo ai = getReceiverInfo(comp, flags);
@@ -2478,7 +2493,13 @@
     }
 
     public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
-        final ComponentName comp = intent.getComponent();
+        ComponentName comp = intent.getComponent();
+        if (comp == null) {
+            if (intent.getSelector() != null) {
+                intent = intent.getSelector(); 
+                comp = intent.getComponent();
+            }
+        }
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
             final ServiceInfo si = getServiceInfo(comp, flags);
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index ee62a56..77575f2 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -151,18 +151,22 @@
 
     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewFlags,
-            boolean insetsPending, Rect outFrame, Rect outContentInsets,
+            int flags, Rect outFrame, Rect outContentInsets,
             Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
         if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         int res = mService.relayoutWindow(this, window, seq, attrs,
-                requestedWidth, requestedHeight, viewFlags, insetsPending,
+                requestedWidth, requestedHeight, viewFlags, flags,
                 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
         if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
         return res;
     }
 
+    public void performDeferredDestroy(IWindow window) {
+        mService.performDeferredDestroyWindow(this, window);
+    }
+
     public boolean outOfMemory(IWindow window) {
         return mService.outOfMemoryWindow(this, window);
     }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index ebb13d5..f5c2de9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -429,6 +429,18 @@
     boolean mSystemBooted = false;
     boolean mForceDisplayEnabled = false;
     boolean mShowingBootMessages = false;
+
+    // This protects the following display size properties, so that
+    // getDisplaySize() doesn't need to acquire the global lock.  This is
+    // needed because the window manager sometimes needs to use ActivityThread
+    // while it has its global state locked (for example to load animation
+    // resources), but the ActivityThread also needs get the current display
+    // size sometimes when it has its package lock held.
+    //
+    // These will only be modified with both mWindowMap and mDisplaySizeLock
+    // held (in that order) so the window manager doesn't need to acquire this
+    // lock when needing these values in its normal operation.
+    final Object mDisplaySizeLock = new Object();
     int mInitialDisplayWidth = 0;
     int mInitialDisplayHeight = 0;
     int mBaseDisplayWidth = 0;
@@ -437,6 +449,7 @@
     int mCurDisplayHeight = 0;
     int mAppDisplayWidth = 0;
     int mAppDisplayHeight = 0;
+
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mAltOrientation = false;
@@ -2499,12 +2512,13 @@
 
     public int relayoutWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int requestedWidth,
-            int requestedHeight, int viewVisibility, boolean insetsPending,
+            int requestedHeight, int viewVisibility, int flags,
             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
             Configuration outConfig, Surface outSurface) {
         boolean displayed = false;
         boolean inTouchMode;
         boolean configChanged;
+        boolean surfaceChanged = false;
 
         // if they don't have this permission, mask out the status bar bits
         int systemUiVisibility = 0;
@@ -2534,6 +2548,9 @@
                 mPolicy.adjustWindowParamsLw(attrs);
             }
 
+            win.mSurfaceDestroyDeferred =
+                    (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+
             int attrChanges = 0;
             int flagChanges = 0;
             if (attrs != null) {
@@ -2630,8 +2647,12 @@
                     // To change the format, we need to re-build the surface.
                     win.destroySurfaceLocked();
                     displayed = true;
+                    surfaceChanged = true;
                 }
                 try {
+                    if (win.mSurface == null) {
+                        surfaceChanged = true;
+                    }
                     Surface surface = win.createSurfaceLocked();
                     if (surface != null) {
                         outSurface.copyFrom(surface);
@@ -2683,6 +2704,7 @@
                     // If we are not currently running the exit animation, we
                     // need to see about starting one.
                     if (!win.mExiting || win.mSurfacePendingDestroy) {
+                        surfaceChanged = true;
                         // Try starting an animation; if there isn't one, we
                         // can destroy the surface right away.
                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
@@ -2715,10 +2737,10 @@
                 if (win.mSurface == null || (win.getAttrs().flags
                         & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
                         || win.mSurfacePendingDestroy) {
-                    // We are being called from a local process, which
+                    // We could be called from a local process, which
                     // means outSurface holds its current surface.  Ensure the
-                    // surface object is cleared, but we don't want it actually
-                    // destroyed at this point.
+                    // surface object is cleared, but we don't necessarily want
+                    // it actually destroyed at this point.
                     win.mSurfacePendingDestroy = false;
                     outSurface.release();
                     if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
@@ -2760,7 +2782,7 @@
             }
 
             mLayoutNeeded = true;
-            win.mGivenInsetsPending = insetsPending;
+            win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
             if (assignLayers) {
                 assignLayersLocked();
             }
@@ -2797,8 +2819,25 @@
 
         Binder.restoreCallingIdentity(origId);
 
-        return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
-                | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
+        return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
+                | (displayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
+                | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0);
+    }
+
+    public void performDeferredDestroyWindow(Session session, IWindow client) {
+        long origId = Binder.clearCallingIdentity();
+
+        try {
+            synchronized(mWindowMap) {
+                WindowState win = windowForClientLocked(session, client, false);
+                if (win == null) {
+                    return;
+                }
+                win.destroyDeferredSurfaceLocked();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
     }
 
     public boolean outOfMemoryWindow(Session session, IWindow client) {
@@ -3738,7 +3777,7 @@
                 return;
             }
 
-            // If this is a translucent or wallpaper window, then don't
+            // If this is a translucent window, then don't
             // show a starting window -- the current effect (a full-screen
             // opaque starting window that fades away to the real contents
             // when it is ready) does not work for this.
@@ -3755,7 +3794,16 @@
                 }
                 if (ent.array.getBoolean(
                         com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
-                    return;
+                    if (mWallpaperTarget == null) {
+                        // If this theme is requesting a wallpaper, and the wallpaper
+                        // is not curently visible, then this effectively serves as
+                        // an opaque window and our starting window transition animation
+                        // can still work.  We just need to make sure the starting window
+                        // is also showing the wallpaper.
+                        windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+                    } else {
+                        return;
+                    }
                 }
             }
 
@@ -5971,25 +6019,27 @@
         final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
         final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
 
-        if (mAltOrientation) {
-            mCurDisplayWidth = realdw;
-            mCurDisplayHeight = realdh;
-            if (realdw > realdh) {
-                // Turn landscape into portrait.
-                int maxw = (int)(realdh/1.3f);
-                if (maxw < realdw) {
-                    mCurDisplayWidth = maxw;
+        synchronized(mDisplaySizeLock) {
+            if (mAltOrientation) {
+                mCurDisplayWidth = realdw;
+                mCurDisplayHeight = realdh;
+                if (realdw > realdh) {
+                    // Turn landscape into portrait.
+                    int maxw = (int)(realdh/1.3f);
+                    if (maxw < realdw) {
+                        mCurDisplayWidth = maxw;
+                    }
+                } else {
+                    // Turn portrait into landscape.
+                    int maxh = (int)(realdw/1.3f);
+                    if (maxh < realdh) {
+                        mCurDisplayHeight = maxh;
+                    }
                 }
             } else {
-                // Turn portrait into landscape.
-                int maxh = (int)(realdw/1.3f);
-                if (maxh < realdh) {
-                    mCurDisplayHeight = maxh;
-                }
+                mCurDisplayWidth = realdw;
+                mCurDisplayHeight = realdh;
             }
-        } else {
-            mCurDisplayWidth = realdw;
-            mCurDisplayHeight = realdh;
         }
 
         final int dw = mCurDisplayWidth;
@@ -6008,8 +6058,12 @@
 
         // Update application display metrics.
         final DisplayMetrics dm = mDisplayMetrics;
-        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
-        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
+        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
+        synchronized(mDisplaySizeLock) {
+            mAppDisplayWidth = appWidth;
+            mAppDisplayHeight = appHeight;
+        }
         if (false) {
             Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
                     + " x " + mAppDisplayHeight);
@@ -6379,18 +6433,20 @@
             }
             WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
             mDisplay = wm.getDefaultDisplay();
-            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
-                // initial width and height to get the true natural values.
-                int tmp = mInitialDisplayWidth;
-                mInitialDisplayWidth = mInitialDisplayHeight;
-                mInitialDisplayHeight = tmp;
+            synchronized(mDisplaySizeLock) {
+                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
+                    // initial width and height to get the true natural values.
+                    int tmp = mInitialDisplayWidth;
+                    mInitialDisplayWidth = mInitialDisplayHeight;
+                    mInitialDisplayHeight = tmp;
+                }
+                mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
+                mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
             }
-            mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
-            mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
             mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
                     mDisplay.getRawWidth(), mDisplay.getRawHeight(),
                     mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
@@ -6928,28 +6984,28 @@
     }
 
     public void getDisplaySize(Point size) {
-        synchronized(mWindowMap) {
+        synchronized(mDisplaySizeLock) {
             size.x = mAppDisplayWidth;
             size.y = mAppDisplayHeight;
         }
     }
 
     public void getRealDisplaySize(Point size) {
-        synchronized(mWindowMap) {
+        synchronized(mDisplaySizeLock) {
             size.x = mCurDisplayWidth;
             size.y = mCurDisplayHeight;
         }
     }
 
     public void getInitialDisplaySize(Point size) {
-        synchronized(mWindowMap) {
+        synchronized(mDisplaySizeLock) {
             size.x = mInitialDisplayWidth;
             size.y = mInitialDisplayHeight;
         }
     }
 
     public int getMaximumSizeDimension() {
-        synchronized(mWindowMap) {
+        synchronized(mDisplaySizeLock) {
             // Do this based on the raw screen size, until we are smarter.
             return mBaseDisplayWidth > mBaseDisplayHeight
                     ? mBaseDisplayWidth : mBaseDisplayHeight;
@@ -7042,8 +7098,10 @@
     private void setForcedDisplaySizeLocked(int width, int height) {
         Slog.i(TAG, "Using new display size: " + width + "x" + height);
 
-        mBaseDisplayWidth = width;
-        mBaseDisplayHeight = height;
+        synchronized(mDisplaySizeLock) {
+            mBaseDisplayWidth = width;
+            mBaseDisplayHeight = height;
+        }
         mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight);
 
         mLayoutNeeded = true;
@@ -7659,7 +7717,8 @@
                         // a detached wallpaper animation.
                         if (nowAnimating) {
                             if (w.mAnimation != null) {
-                                if (w.mAnimation.getDetachWallpaper()) {
+                                if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                                        && w.mAnimation.getDetachWallpaper()) {
                                     windowDetachedWallpaper = w;
                                 }
                                 if (w.mAnimation.getBackgroundColor() != 0) {
@@ -7679,7 +7738,8 @@
                         // displayed behind it.
                         if (w.mAppToken != null && w.mAppToken.animation != null
                                 && w.mAppToken.animating) {
-                            if (w.mAppToken.animation.getDetachWallpaper()) {
+                            if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                                    && w.mAppToken.animation.getDetachWallpaper()) {
                                 windowDetachedWallpaper = w;
                             }
                             if (w.mAppToken.animation.getBackgroundColor() != 0) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 23ec2d9..aa7bf2d 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -85,6 +85,7 @@
     boolean mPolicyVisibilityAfterAnim = true;
     boolean mAppFreezing;
     Surface mSurface;
+    Surface mPendingDestroySurface;
     boolean mReportDestroySurface;
     boolean mSurfacePendingDestroy;
     boolean mAttachedHidden;    // is our parent window hidden?
@@ -121,7 +122,13 @@
      * we must tell them application to resize (and thus redraw itself).
      */
     boolean mSurfaceResized;
-    
+
+    /**
+     * Set if the client has asked that the destroy of its surface be delayed
+     * until it explicitly says it is okay.
+     */
+    boolean mSurfaceDestroyDeferred;
+
     /**
      * Insets that determine the actually visible area.  These are in the application's
      * coordinate space (without compatibility scale applied).
@@ -764,15 +771,32 @@
                     Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface "
                             + mSurface + ", session " + mSession, e);
                 }
-                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
-                    RuntimeException e = null;
-                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
-                        e = new RuntimeException();
-                        e.fillInStackTrace();
+                if (mSurfaceDestroyDeferred) {
+                    if (mSurface != null && mPendingDestroySurface != mSurface) {
+                        if (mPendingDestroySurface != null) {
+                            if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+                                RuntimeException e = null;
+                                if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                                    e = new RuntimeException();
+                                    e.fillInStackTrace();
+                                }
+                                WindowManagerService.logSurface(this, "DESTROY PENDING", e);
+                            }
+                            mPendingDestroySurface.destroy();
+                        }
+                        mPendingDestroySurface = mSurface;
                     }
-                    WindowManagerService.logSurface(this, "DESTROY", e);
+                } else {
+                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+                        RuntimeException e = null;
+                        if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                            e = new RuntimeException();
+                            e.fillInStackTrace();
+                        }
+                        WindowManagerService.logSurface(this, "DESTROY", e);
+                    }
+                    mSurface.destroy();
                 }
-                mSurface.destroy();
             } catch (RuntimeException e) {
                 Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this
                     + " surface " + mSurface + " session " + mSession
@@ -784,6 +808,28 @@
         }
     }
 
+    void destroyDeferredSurfaceLocked() {
+        try {
+            if (mPendingDestroySurface != null) {
+                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+                    RuntimeException e = null;
+                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                        e = new RuntimeException();
+                        e.fillInStackTrace();
+                    }
+                    mService.logSurface(this, "DESTROY PENDING", e);
+                }
+                mPendingDestroySurface.destroy();
+            }
+        } catch (RuntimeException e) {
+            Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window "
+                    + this + " surface " + mPendingDestroySurface
+                    + " session " + mSession + ": " + e.toString());
+        }
+        mSurfaceDestroyDeferred = false;
+        mPendingDestroySurface = null;
+    }
+
     boolean finishDrawingLocked() {
         if (mDrawPending) {
             if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
@@ -977,6 +1023,9 @@
             mAnimation.cancel();
             mAnimation = null;
         }
+        if (mService.mWindowDetachedWallpaper == this) {
+            mService.mWindowDetachedWallpaper = null;
+        }
         mAnimLayer = mLayer;
         if (mIsImWindow) {
             mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
@@ -1415,6 +1464,7 @@
             if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
             mAttachedWindow.mChildWindows.remove(this);
         }
+        destroyDeferredSurfaceLocked();
         destroySurfaceLocked();
         mSession.windowRemovedLocked();
         try {
@@ -1612,6 +1662,10 @@
                     pw.print(") "); pw.print(mSurfaceW);
                     pw.print(" x "); pw.println(mSurfaceH);
         }
+        if (mPendingDestroySurface != null) {
+            pw.print(prefix); pw.print("mPendingDestroySurface=");
+                    pw.println(mPendingDestroySurface);
+        }
         if (dumpAll) {
             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
             pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
@@ -1640,6 +1694,10 @@
         if (!mRelayoutCalled) {
             pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
         }
+        if (mSurfaceResized || mSurfaceDestroyDeferred) {
+            pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
+                    pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
+        }
         if (mXOffset != 0 || mYOffset != 0) {
             pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
                     pw.print(" y="); pw.println(mYOffset);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 61a8358..f63c0c1 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -28,6 +28,7 @@
 endif
 ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
+	LOCAL_CFLAGS += -DREFRESH_RATE=56
 endif
 
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1b00e93..24bd2a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,8 @@
 #define AID_GRAPHICS 1003
 #endif
 
+#define EGL_VERSION_HW_ANDROID  0x3143
+
 #define DISPLAY_COUNT       1
 
 namespace android {
@@ -708,6 +710,14 @@
 
 void SurfaceFlinger::commitTransaction()
 {
+    if (!mLayersPendingRemoval.isEmpty()) {
+        // Notify removed layers now that they can't be drawn from
+        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
+            mLayersPendingRemoval[i]->onRemoved();
+        }
+        mLayersPendingRemoval.clear();
+    }
+
     mDrawingState = mCurrentState;
     mTransationPending = false;
     mTransactionCV.broadcast();
@@ -1160,7 +1170,7 @@
         mLayerPurgatory.add(layerBase);
     }
 
-    layerBase->onRemoved();
+    mLayersPendingRemoval.push(layerBase);
 
     // it's possible that we don't find a layer, because it might
     // have been destroyed already -- this is not technically an error
@@ -1527,7 +1537,7 @@
          * Dump the layers in the purgatory
          */
 
-        const size_t purgatorySize =  mLayerPurgatory.size();
+        const size_t purgatorySize = mLayerPurgatory.size();
         snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
         result.append(buffer);
         for (size_t i=0 ; i<purgatorySize ; i++) {
@@ -1548,6 +1558,12 @@
                 extensions.getRenderer(),
                 extensions.getVersion());
         result.append(buffer);
+
+        snprintf(buffer, SIZE, "EGL : %s\n",
+                eglQueryString(graphicPlane(0).getEGLDisplay(),
+                        EGL_VERSION_HW_ANDROID));
+        result.append(buffer);
+
         snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
         result.append(buffer);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 17028db..17b80a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -345,6 +345,7 @@
                 Condition               mTransactionCV;
                 SortedVector< sp<LayerBase> > mLayerPurgatory;
                 bool                    mTransationPending;
+                Vector< sp<LayerBase> > mLayersPendingRemoval;
 
                 // protected by mStateLock (but we could use another lock)
                 GraphicPlane                mGraphicPlanes[1];
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 4390ca1..5020e00 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -28,7 +28,7 @@
 
 
 SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer)
-    : SurfaceTexture(tex), mLayer(layer) {
+    : SurfaceTexture(tex, true, GL_TEXTURE_EXTERNAL_OES, false), mLayer(layer) {
 }
 
 SurfaceTextureLayer::~SurfaceTextureLayer() {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 56a0a2c..07afe30 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2118,6 +2118,31 @@
     }
 
     /**
+     * @return the "username" part of the specified SIP address,
+     *         i.e. the part before the "@" character (or "%40").
+     *
+     * @param number SIP address of the form "username@domainname"
+     *               (or the URI-escaped equivalent "username%40domainname")
+     * @see isUriNumber
+     *
+     * @hide
+     */
+    public static String getUsernameFromUriNumber(String number) {
+        // The delimiter between username and domain name can be
+        // either "@" or "%40" (the URI-escaped equivalent.)
+        int delimiterIndex = number.indexOf('@');
+        if (delimiterIndex < 0) {
+            delimiterIndex = number.indexOf("%40");
+        }
+        if (delimiterIndex < 0) {
+            Log.w(LOG_TAG,
+                  "getUsernameFromUriNumber: no delimiter found in SIP addr '" + number + "'");
+            delimiterIndex = number.length();
+        }
+        return number.substring(0, delimiterIndex);
+    }
+
+    /**
      * This function handles the plus code conversion within NANP CDMA network
      * If the number format is
      * 1)+1NANP,remove +,
diff --git a/telephony/java/com/android/internal/telephony/ApnSetting.java b/telephony/java/com/android/internal/telephony/ApnSetting.java
index 002ffad9..980bb49 100755
--- a/telephony/java/com/android/internal/telephony/ApnSetting.java
+++ b/telephony/java/com/android/internal/telephony/ApnSetting.java
@@ -189,4 +189,11 @@
         }
         return false;
     }
+
+    // TODO - if we have this function we should also have hashCode.
+    // Also should handle changes in type order and perhaps case-insensitivity
+    public boolean equals(Object o) {
+        if (o instanceof ApnSetting == false) return false;
+        return (this.toString().equals(o.toString()));
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index f111dd6..07b6183 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -683,6 +683,13 @@
         mRilConnectedRegistrants.remove(h);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setCurrentPreferredNetworkType() {
+    }
+
     //***** Protected Methods
     /**
      * Store new RadioState and send notification based on the changes
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 6324550..5d1f758 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -288,7 +288,7 @@
             String number, CallerInfo previousResult) {
         if (!previousResult.contactExists
                 && PhoneNumberUtils.isUriNumber(number)) {
-            String username = number.substring(0, number.indexOf('@'));
+            String username = PhoneNumberUtils.getUsernameFromUriNumber(number);
             if (PhoneNumberUtils.isGlobalPhoneNumber(username)) {
                 previousResult = getCallerInfo(context,
                         Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index 33ead75..d6e6ae0 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -1311,6 +1311,12 @@
     void queryAvailableBandMode (Message response);
 
     /**
+     * Set the current preferred network type. This will be the last
+     * networkType that was passed to setPreferredNetworkType.
+     */
+    void setCurrentPreferredNetworkType();
+
+    /**
      *  Requests to set the preferred network type for searching and registering
      * (CS/PS domain, RAT, and operation mode)
      * @param networkType one of  NT_*_TYPE
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index 6d8956f..efbf608 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -126,6 +126,8 @@
                 // set link addresses
                 if (addresses != null && addresses.length > 0) {
                     for (String addr : addresses) {
+                        addr = addr.trim();
+                        if (addr.isEmpty()) continue;
                         LinkAddress la;
                         int addrPrefixLen;
 
@@ -159,6 +161,8 @@
                 // set dns servers
                 if (dnses != null && dnses.length > 0) {
                     for (String addr : dnses) {
+                        addr = addr.trim();
+                        if (addr.isEmpty()) continue;
                         InetAddress ia;
                         try {
                             ia = NetworkUtils.numericToInetAddress(addr);
@@ -174,6 +178,8 @@
                     dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
                     dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
                     for (String dnsAddr : dnsServers) {
+                        dnsAddr = dnsAddr.trim();
+                        if (dnsAddr.isEmpty()) continue;
                         InetAddress ia;
                         try {
                             ia = NetworkUtils.numericToInetAddress(dnsAddr);
@@ -198,6 +204,8 @@
                     }
                 }
                 for (String addr : gateways) {
+                    addr = addr.trim();
+                    if (addr.isEmpty()) continue;
                     InetAddress ia;
                     try {
                         ia = NetworkUtils.numericToInetAddress(addr);
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 636646e..4619899 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -699,8 +699,10 @@
                     break;
 
                 case EVENT_DISCONNECT:
-                    if (DBG) log("DcDefaultState: msg.what=EVENT_DISCONNECT");
-                    notifyDisconnectCompleted((DisconnectParams) msg.obj);
+                    if (DBG) {
+                        log("DcDefaultState deferring msg.what=EVENT_DISCONNECT" + mRefCount);
+                    }
+                    deferMessage(msg);
                     break;
 
                 case EVENT_RIL_CONNECTED:
@@ -807,6 +809,12 @@
                     retVal = HANDLED;
                     break;
 
+                case EVENT_DISCONNECT:
+                    if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
+                    notifyDisconnectCompleted((DisconnectParams)msg.obj);
+                    retVal = HANDLED;
+                    break;
+
                 default:
                     if (VDBG) {
                         log("DcInactiveState nothandled msg.what=0x" +
@@ -831,13 +839,6 @@
             ConnectionParams cp;
 
             switch (msg.what) {
-                case EVENT_DISCONNECT:
-                    if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"
-                            + mRefCount);
-                    deferMessage(msg);
-                    retVal = HANDLED;
-                    break;
-
                 case EVENT_CONNECT:
                     if (DBG) log("DcActivatingState deferring msg.what=EVENT_CONNECT refCount = "
                             + mRefCount);
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 9f93fb8..f2e7f45 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -1823,6 +1823,16 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    public void setCurrentPreferredNetworkType() {
+        if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType: " + mSetPreferredNetworkType);
+        setPreferredNetworkType(mSetPreferredNetworkType, null);
+    }
+    private int mSetPreferredNetworkType;
+
+    /**
+     * {@inheritDoc}
+     */
     public void setPreferredNetworkType(int networkType , Message response) {
         RILRequest rr = RILRequest.obtain(
                 RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
@@ -1830,6 +1840,7 @@
         rr.mp.writeInt(1);
         rr.mp.writeInt(networkType);
 
+        mSetPreferredNetworkType = networkType;
         mPreferredNetworkType = networkType;
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 3d6cd68..d939e98 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -257,6 +257,9 @@
             break;
 
         case EVENT_RUIM_READY:
+            // TODO: Consider calling setCurrentPreferredNetworkType as we do in GsmSST.
+            // cm.setCurrentPreferredNetworkType();
+
             // The RUIM is now ready i.e if it was locked it has been
             // unlocked. At this stage, the radio is already powered on.
             isSubscriptionFromRuim = true;
@@ -277,6 +280,9 @@
             break;
 
         case EVENT_NV_READY:
+            // TODO: Consider calling setCurrentPreferredNetworkType as we do in GsmSST.
+            // cm.setCurrentPreferredNetworkType();
+
             isSubscriptionFromRuim = false;
             // For Non-RUIM phones, the subscription information is stored in
             // Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 7cd01a1..963db2c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -914,10 +914,16 @@
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
-                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
+                        NetworkUtils.trimV4AddrZeros(
+                                cursor.getString(
+                                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT)),
-                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC)),
-                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
+                        NetworkUtils.trimV4AddrZeros(
+                                cursor.getString(
+                                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+                        NetworkUtils.trimV4AddrZeros(
+                                cursor.getString(
+                                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT)),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
                         cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
@@ -1720,11 +1726,25 @@
     private DataConnection checkForConnectionForApnContext(ApnContext apnContext) {
         // Loop through all apnContexts looking for one with a conn that satisfies this apnType
         String apnType = apnContext.getApnType();
+        ApnSetting dunSetting = null;
+
+        if (Phone.APN_TYPE_DUN.equals(apnType)) {
+            dunSetting = fetchDunApn();
+        }
+
         for (ApnContext c : mApnContexts.values()) {
             DataConnection conn = c.getDataConnection();
             if (conn != null) {
                 ApnSetting apnSetting = c.getApnSetting();
-                if (apnSetting != null && apnSetting.canHandleType(apnType)) {
+                if (dunSetting != null) {
+                    if (dunSetting.equals(apnSetting)) {
+                        if (DBG) {
+                            log("checkForConnectionForApnContext: apnContext=" + apnContext +
+                                    " found conn=" + conn);
+                        }
+                        return conn;
+                    }
+                } else if (apnSetting != null && apnSetting.canHandleType(apnType)) {
                     if (DBG) {
                         log("checkForConnectionForApnContext: apnContext=" + apnContext +
                                 " found conn=" + conn);
@@ -1848,8 +1868,14 @@
             DataConnection dc = apnContext.getDataConnection();
 
             if (DBG) {
-                log(String.format("onDataSetupComplete: success apn=%s",
-                    apnContext.getWaitingApns().get(0).apn));
+                // TODO We may use apnContext.getApnSetting() directly
+                // instead of getWaitingApns().get(0)
+                String apnStr = "<unknown>";
+                if (apnContext.getWaitingApns() != null
+                        && !apnContext.getWaitingApns().isEmpty()){
+                    apnStr = apnContext.getWaitingApns().get(0).apn;
+                }
+                log("onDataSetupComplete: success apn=" + apnStr);
             }
             ApnSetting apn = apnContext.getApnSetting();
             if (apn.proxy != null && apn.proxy.length() != 0) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 3799894..16d3129 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -132,7 +132,7 @@
     // See TS 22.030 6.5.2 "Structure of the MMI"
 
     static Pattern sPatternSuppService = Pattern.compile(
-        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
+        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)([^#]*)");
 /*       1  2                    3          4  5       6   7         8    9     10  11             12
 
          1 = Full string up to and including #
@@ -141,7 +141,7 @@
          5 = SIA
          7 = SIB
          9 = SIC
-         10 = dialing number
+         10 = dialing number which must not include #, e.g. *SCn*SI#DN format
 */
 
     static final int MATCH_GROUP_POUND_STRING = 1;
@@ -1338,4 +1338,20 @@
      * SpecialCharSequenceMgr class.
      */
 
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("GsmMmiCode {");
+
+        sb.append("State=" + getState());
+        if (action != null) sb.append(" action=" + action);
+        if (sc != null) sb.append(" sc=" + sc);
+        if (sia != null) sb.append(" sia=" + sia);
+        if (sib != null) sb.append(" sib=" + sib);
+        if (sic != null) sb.append(" sic=" + sic);
+        if (poundString != null) sb.append(" poundString=" + poundString);
+        if (dialingNumber != null) sb.append(" dialingNumber=" + dialingNumber);
+        if (pwd != null) sb.append(" pwd=" + pwd);
+        sb.append("}");
+        return sb.toString();
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index eea2780..84127cf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -270,6 +270,9 @@
                 break;
 
             case EVENT_SIM_READY:
+                // Set the network type, in case the radio does not restore it.
+                cm.setCurrentPreferredNetworkType();
+
                 // The SIM is now ready i.e if it was locked
                 // it has been unlocked. At this stage, the radio is already
                 // powered on.
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
index 03893d6..2eb52f0 100644
--- a/tests/FrameworkPerf/Android.mk
+++ b/tests/FrameworkPerf/Android.mk
@@ -7,6 +7,8 @@
 
 LOCAL_PACKAGE_NAME := FrameworkPerf
 
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
 LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
 
 include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index e88f4fb..2591aaf 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -4,6 +4,7 @@
     <uses-sdk android:minSdkVersion="5" />
 
     <application android:hardwareAccelerated="false">
+        <uses-library android:name="android.test.runner" />
         <activity android:name="FrameworkPerfActivity" android:label="Framework Perf">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -20,4 +21,9 @@
         <receiver android:name="Receiver" android:exported="true">
         </receiver>
     </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.frameworkperf"
+        android:label="Framework Perf Runner"
+    />
 </manifest>
diff --git a/tests/FrameworkPerf/res/layout/main.xml b/tests/FrameworkPerf/res/layout/main.xml
index 7812648..e00ad92 100644
--- a/tests/FrameworkPerf/res/layout/main.xml
+++ b/tests/FrameworkPerf/res/layout/main.xml
@@ -66,7 +66,24 @@
         >
         <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="Limit by: "
+            />
+        <Spinner android:id="@+id/limitspinner"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:drawSelectorOnTop="true"
+        />
+    </LinearLayout>
+
+    <LinearLayout android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_marginTop="10dp"
+        >
+        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:text="Test time (ms): "
+            android:id="@+id/limitlabel"
             />
         <EditText android:id="@+id/testtime"
             android:layout_width="match_parent"
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 175f227..30a968f 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -50,6 +50,8 @@
 
     Spinner mFgSpinner;
     Spinner mBgSpinner;
+    Spinner mLimitSpinner;
+    TextView mLimitLabel;
     TextView mTestTime;
     Button mStartButton;
     Button mStopButton;
@@ -58,10 +60,12 @@
     PowerManager.WakeLock mPartialWakeLock;
 
     long mMaxRunTime = 5000;
+    boolean mLimitIsIterations;
     boolean mStarted;
 
     final String[] mAvailOpLabels;
     final String[] mAvailOpDescriptions;
+    final String[] mLimitLabels = { "Time", "Iterations" };
 
     int mFgTestIndex = -1;
     int mBgTestIndex = -1;
@@ -73,6 +77,8 @@
 
     final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
 
+    Object mResultNotifier = new Object();
+
     class TestConnection implements ServiceConnection, IBinder.DeathRecipient {
         Messenger mService;
         boolean mLinked;
@@ -167,8 +173,15 @@
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         mBgSpinner.setAdapter(adapter);
         mBgSpinner.setOnItemSelectedListener(this);
+        mLimitSpinner = (Spinner) findViewById(R.id.limitspinner);
+        adapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, mLimitLabels);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mLimitSpinner.setAdapter(adapter);
+        mLimitSpinner.setOnItemSelectedListener(this);
 
         mTestTime = (TextView)findViewById(R.id.testtime);
+        mLimitLabel = (TextView)findViewById(R.id.limitlabel);
 
         mStartButton = (Button)findViewById(R.id.start);
         mStartButton.setOnClickListener(new View.OnClickListener() {
@@ -194,16 +207,23 @@
 
     @Override
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-        if (parent == mFgSpinner || parent == mBgSpinner) {
+        if (parent == mFgSpinner || parent == mBgSpinner || parent == mLimitSpinner) {
             TestService.Op op = TestService.mAvailOps[position];
             if (parent == mFgSpinner) {
                 mFgTestIndex = position;
                 mFgTest = op;
                 ((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]);
-            } else {
+            } else if (parent == mBgSpinner) {
                 mBgTestIndex = position;
                 mBgTest = op;
                 ((TextView)findViewById(R.id.bgtext)).setText(mAvailOpDescriptions[position]);
+            } else if (parent == mLimitSpinner) {
+                mLimitIsIterations = (position != 0);
+                if (mLimitIsIterations) {
+                    mLimitLabel.setText("Iterations: ");
+                } else {
+                    mLimitLabel.setText("Test time (ms): ");
+                }
             }
         }
     }
@@ -232,7 +252,11 @@
             return;
         }
         TestArgs args = new TestArgs();
-        args.maxTime = mMaxRunTime;
+        if (mLimitIsIterations) {
+            args.maxOps = mMaxRunTime;
+        } else {
+            args.maxTime = mMaxRunTime;
+        }
         if (mFgTestIndex == 0 && mBgTestIndex == 0) {
             args.combOp = mCurOpIndex;
         } else if (mFgTestIndex != 0 && mBgTestIndex != 0) {
@@ -266,7 +290,9 @@
         log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
                 result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
                 result.bgOps, result.getBgMsPerOp(), result.bgTime));
-        mResults.add(result);
+        synchronized (mResults) {
+            mResults.add(result);
+        }
         if (!mStarted) {
             log("Stop");
             stopRunning();
@@ -372,11 +398,14 @@
             mTestTime.setEnabled(false);
             mFgSpinner.setEnabled(false);
             mBgSpinner.setEnabled(false);
+            mLimitSpinner.setEnabled(false);
             updateWakeLock();
             startService(new Intent(this, SchedulerService.class));
             mCurOpIndex = 0;
             mMaxRunTime = Integer.parseInt(mTestTime.getText().toString());
-            mResults.clear();
+            synchronized (mResults) {
+                mResults.clear();
+            }
             startCurOp();
         }
     }
@@ -391,19 +420,25 @@
             mTestTime.setEnabled(true);
             mFgSpinner.setEnabled(true);
             mBgSpinner.setEnabled(true);
+            mLimitSpinner.setEnabled(true);
             updateWakeLock();
             stopService(new Intent(this, SchedulerService.class));
-            for (int i=0; i<mResults.size(); i++) {
-                RunResult result = mResults.get(i);
-                float fgMsPerOp = result.getFgMsPerOp();
-                float bgMsPerOp = result.getBgMsPerOp();
-                String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
-                String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
-                Log.i("PerfRes", "\t" + result.name + "\t" + result.fgOps
-                        + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
-                        + "\t" + result.fgLongName + "\t" + result.bgOps
-                        + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
-                        + "\t" + result.bgLongName);
+            synchronized (mResults) {
+                for (int i=0; i<mResults.size(); i++) {
+                    RunResult result = mResults.get(i);
+                    float fgMsPerOp = result.getFgMsPerOp();
+                    float bgMsPerOp = result.getBgMsPerOp();
+                    String fgMsPerOpStr = fgMsPerOp != 0 ? Float.toString(fgMsPerOp) : "";
+                    String bgMsPerOpStr = bgMsPerOp != 0 ? Float.toString(bgMsPerOp) : "";
+                    Log.i("PerfRes", "\t" + result.name + "\t" + result.fgOps
+                            + "\t" + result.getFgMsPerOp() + "\t" + result.fgTime
+                            + "\t" + result.fgLongName + "\t" + result.bgOps
+                            + "\t" + result.getBgMsPerOp() + "\t" + result.bgTime
+                            + "\t" + result.bgLongName);
+                }
+            }
+            synchronized (mResultNotifier) {
+                mResultNotifier.notifyAll();
             }
         }
     }
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java
new file mode 100644
index 0000000..2a53b06
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfTest.java
@@ -0,0 +1,41 @@
+package com.android.frameworkperf;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class FrameworkPerfTest extends ActivityInstrumentationTestCase2<FrameworkPerfActivity> {
+
+    private static final int TEST_TIMEOUT = 15 * 60 * 1000; //15 minutes
+
+    public FrameworkPerfTest() {
+        super("com.android.frameworkperf", FrameworkPerfActivity.class);
+    }
+
+    public void testFrameworkPerf() {
+        final FrameworkPerfActivity activity = getActivity();
+        synchronized (activity.mResultNotifier) {
+            getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    activity.startRunning();
+                }
+            });
+            try {
+                activity.mResultNotifier.wait(TEST_TIMEOUT);
+            } catch (InterruptedException e) {
+                fail("test interrupted.");
+            }
+        }
+        Bundle testResult = new Bundle();
+        synchronized (activity.mResults) {
+            assertTrue("test results were empty.", activity.mResults.size() > 0);
+            for (RunResult result : activity.mResults) {
+                testResult.putString(result.name, String.format("%f,%d,%d,%f,%d,%d",
+                        result.getFgMsPerOp(), result.fgOps, result.fgTime,
+                        result.getBgMsPerOp(), result.bgOps, result.bgTime));
+            }
+        }
+        getInstrumentation().sendStatus(Activity.RESULT_OK, testResult);
+    }
+}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
index f2f7c56..2fe38aa 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
@@ -21,6 +21,7 @@
 
 public class TestArgs implements Parcelable {
     long maxTime;
+    long maxOps = -1;
     int combOp = -1;
     int fgOp = -1;
     int bgOp = -1;
@@ -30,6 +31,7 @@
 
     public TestArgs(Parcel source) {
         maxTime = source.readLong();
+        maxOps = source.readLong();
         combOp = source.readInt();
         fgOp = source.readInt();
         bgOp = source.readInt();
@@ -43,6 +45,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(maxTime);
+        dest.writeLong(maxOps);
         dest.writeInt(combOp);
         dest.writeInt(fgOp);
         dest.writeInt(bgOp);
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
index 8cf1ac2..a8c43e9 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
@@ -224,6 +224,7 @@
     public class TestRunner {
         Handler mHandler;
         long mMaxRunTime;
+        long mMaxOps;
         Op mForegroundOp;
         Op mBackgroundOp;
         Runnable mDoneCallback;
@@ -277,6 +278,7 @@
         public void run(Handler handler, TestArgs args, Runnable doneCallback) {
             mHandler = handler;
             mMaxRunTime = args.maxTime;
+            mMaxOps = args.maxOps;
             if (args.combOp >= 0) {
                 mForegroundOp = mOpPairs[args.combOp];
                 mBackgroundOp = mOpPairs[args.combOp+1];
@@ -352,9 +354,18 @@
                 if (!mBackgroundRunning && !mForegroundRunning) {
                     return false;
                 }
-                long now = SystemClock.uptimeMillis();
-                if (now > (mStartTime+mMaxRunTime)) {
-                    return false;
+                if (mMaxOps > 0) {
+                    // iteration-limited case
+                    if (mForegroundOps >= mMaxOps) {
+                        return false;
+                    }
+                    mForegroundOps++;
+                } else {
+                    // time-limited case
+                    long now = SystemClock.uptimeMillis();
+                    if (now > (mStartTime+mMaxRunTime)) {
+                        return false;
+                    }
                 }
                 return true;
             }
diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml
index e1199c7..6c384f7 100644
--- a/tests/StatusBar/res/layout/notification_builder_test.xml
+++ b/tests/StatusBar/res/layout/notification_builder_test.xml
@@ -605,6 +605,11 @@
                         style="@style/FieldContents"
                         android:text="pineapple2"
                         />
+                <RadioButton
+                        android:id="@+id/large_icon_small"
+                        style="@style/FieldContents"
+                        android:text="small"
+                        />
             </RadioGroup>
             
 
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index 5a2ebac..fefd890 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -287,6 +287,9 @@
             case R.id.large_icon_pineapple2:
                 b.setLargeIcon(loadBitmap(R.drawable.pineapple2));
                 break;
+            case R.id.large_icon_small:
+                b.setLargeIcon(loadBitmap(R.drawable.icon2));
+                break;
         }
 
         // sound TODO
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index b1cef15c..10802b4 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -110,9 +110,9 @@
      * been redrawn.
      */
     @Override
-    protected void pageSwapCallback() {
+    protected void pageSwapCallback(boolean startAnim) {
         mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
-        super.pageSwapCallback();
+        super.pageSwapCallback(startAnim);
         Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis
                 + "millis");
         mIsTesting = true;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 1d97e15..a640a91 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -79,12 +79,16 @@
     }
 
     public int relayout(IWindow arg0, int seq, LayoutParams arg1, int arg2, int arg3, int arg4,
-            boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
+            int arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
             throws RemoteException {
         // pass for now.
         return 0;
     }
 
+    public void performDeferredDestroy(IWindow window) {
+        // pass for now.
+    }
+
     public boolean outOfMemory(IWindow window) throws RemoteException {
         return false;
     }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index dc628e0..113f007 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -73,7 +73,7 @@
  */
 class SipHelper {
     private static final String TAG = SipHelper.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final boolean DEBUG_PING = false;
 
     private SipStack mSipStack;
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 119ed54..38a683e 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -68,8 +68,7 @@
  */
 public final class SipService extends ISipService.Stub {
     static final String TAG = "SipService";
-    static final boolean DEBUGV = false;
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
     private static final int EXPIRY_TIME = 3600;
     private static final int SHORT_EXPIRY_TIME = 10;
     private static final int MIN_EXPIRY_TIME = 60;
@@ -581,7 +580,7 @@
         @Override
         public void onRinging(ISipSession s, SipProfile caller,
                 String sessionDescription) {
-            if (DEBUGV) Log.d(TAG, "<<<<< onRinging()");
+            if (DEBUG) Log.d(TAG, "<<<<< onRinging()");
             SipSessionGroup.SipSessionImpl session =
                     (SipSessionGroup.SipSessionImpl) s;
             synchronized (SipService.this) {
@@ -778,7 +777,6 @@
         private void restartLater() {
             synchronized (SipService.this) {
                 int interval = NAT_MEASUREMENT_RETRY_INTERVAL;
-                Log.d(TAG, "Retry measurement " + interval + "s later.");
                 mTimer.cancel(this);
                 mTimer.set(interval * 1000, this);
             }
@@ -788,7 +786,7 @@
     private class AutoRegistrationProcess extends SipSessionAdapter
             implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
         private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
-        private String TAG = "SipAudoReg";
+        private String TAG = "SipAutoReg";
 
         private SipSessionGroup.SipSessionImpl mSession;
         private SipSessionGroup.SipSessionImpl mKeepAliveSession;
@@ -820,13 +818,12 @@
                 // in registration to avoid adding duplicate entries to server
                 mMyWakeLock.acquire(mSession);
                 mSession.unregister();
-                if (DEBUG) TAG = mSession.getLocalProfile().getUriString();
-                if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess");
+                TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
             }
         }
 
         private void startKeepAliveProcess(int interval) {
-            Log.d(TAG, "start keepalive w interval=" + interval);
+            if (DEBUG) Log.d(TAG, "start keepalive w interval=" + interval);
             if (mKeepAliveSession == null) {
                 mKeepAliveSession = mSession.duplicate();
             } else {
@@ -864,9 +861,11 @@
                             mKeepAliveSuccessCount = 0;
                         }
                     } else {
-                        Log.i(TAG, "keep keepalive going with interval "
-                                + interval + ", past success count="
-                                + mKeepAliveSuccessCount);
+                        if (DEBUG) {
+                            Log.i(TAG, "keep keepalive going with interval "
+                                    + interval + ", past success count="
+                                    + mKeepAliveSuccessCount);
+                        }
                         mKeepAliveSuccessCount /= 2;
                     }
                 } else {
@@ -894,7 +893,9 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
-            Log.e(TAG, "keepalive error: " + description);
+            if (DEBUG) {
+                Log.e(TAG, "keepalive error: " + description);
+            }
             onResponse(true); // re-register immediately
         }
 
@@ -917,7 +918,7 @@
         public void onKeepAliveIntervalChanged() {
             if (mKeepAliveSession != null) {
                 int newInterval = getKeepAliveInterval();
-                if (DEBUGV) {
+                if (DEBUG) {
                     Log.v(TAG, "restart keepalive w interval=" + newInterval);
                 }
                 mKeepAliveSuccessCount = 0;
@@ -987,7 +988,7 @@
         }
 
         private void restart(int duration) {
-            if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later.");
+            Log.d(TAG, "Refresh registration " + duration + "s later.");
             mTimer.cancel(this);
             mTimer.set(duration * 1000, this);
         }
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 06cdaf2..877a0a4 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -89,8 +89,8 @@
  */
 class SipSessionGroup implements SipListener {
     private static final String TAG = "SipSession";
-    private static final boolean DEBUG = true;
-    private static final boolean DEBUG_PING = DEBUG && false;
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_PING = false;
     private static final String ANONYMOUS = "anonymous";
     // Limit the size of thread pool to 1 for the order issue when the phone is
     // waken up from sleep and there are many packets to be processed in the SIP
@@ -205,7 +205,9 @@
     }
 
     synchronized void resetExternalAddress() {
-        Log.d(TAG, " reset external addr on " + mSipStack);
+        if (DEBUG) {
+            Log.d(TAG, " reset external addr on " + mSipStack);
+        }
         mExternalIp = null;
         mExternalPort = 0;
     }
@@ -362,7 +364,7 @@
                         + SipSession.State.toString(session.mState));
             }
         } catch (Throwable e) {
-            Log.w(TAG, "event process error: " + event, e);
+            Log.w(TAG, "event process error: " + event, getRootCause(e));
             session.onError(e);
         }
     }
@@ -393,11 +395,22 @@
         if ((rport > 0) && (externalIp != null)) {
             mExternalIp = externalIp;
             mExternalPort = rport;
-            Log.d(TAG, " got external addr " + externalIp + ":" + rport
-                    + " on " + mSipStack);
+            if (DEBUG) {
+                Log.d(TAG, " got external addr " + externalIp + ":" + rport
+                        + " on " + mSipStack);
+            }
         }
     }
 
+    private Throwable getRootCause(Throwable exception) {
+        Throwable cause = exception.getCause();
+        while (cause != null) {
+            exception = cause;
+            cause = exception.getCause();
+        }
+        return exception;
+    }
+
     private SipSessionImpl createNewSession(RequestEvent event,
             ISipSessionListener listener, ServerTransaction transaction,
             int newState) throws SipException {
@@ -890,7 +903,9 @@
             if (expires != null && time < expires.getExpires()) {
                 time = expires.getExpires();
             }
-            Log.v(TAG, "Expiry time = " + time);
+            if (DEBUG) {
+                Log.v(TAG, "Expiry time = " + time);
+            }
             return time;
         }
 
@@ -1409,15 +1424,6 @@
             }
         }
 
-        private Throwable getRootCause(Throwable exception) {
-            Throwable cause = exception.getCause();
-            while (cause != null) {
-                exception = cause;
-                cause = exception.getCause();
-            }
-            return exception;
-        }
-
         private int getErrorCode(Throwable exception) {
             String message = exception.getMessage();
             if (exception instanceof UnknownHostException) {
@@ -1555,8 +1561,10 @@
                     try {
                         sendKeepAlive();
                     } catch (Throwable t) {
-                        Log.w(TAG, "keepalive error: "
-                                + mLocalProfile.getUriString(), getRootCause(t));
+                        if (DEBUG) {
+                            Log.w(TAG, "keepalive error: "
+                                    + mLocalProfile.getUriString(), getRootCause(t));
+                        }
                         // It's possible that the keepalive process is being stopped
                         // during session.sendKeepAlive() so need to check mRunning
                         // again here.
diff --git a/voip/java/com/android/server/sip/SipWakeLock.java b/voip/java/com/android/server/sip/SipWakeLock.java
index 52bc094..0c4d14c 100644
--- a/voip/java/com/android/server/sip/SipWakeLock.java
+++ b/voip/java/com/android/server/sip/SipWakeLock.java
@@ -22,8 +22,8 @@
 import java.util.HashSet;
 
 class SipWakeLock {
-    private static final boolean DEBUGV = SipService.DEBUGV;
-    private static final String TAG = SipService.TAG;
+    private static final boolean DEBUG = false;
+    private static final String TAG = "SipWakeLock";
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
     private PowerManager.WakeLock mTimerWakeLock;
@@ -34,9 +34,9 @@
     }
 
     synchronized void reset() {
+        if (DEBUG) Log.v(TAG, "reset count=" + mHolders.size());
         mHolders.clear();
         release(null);
-        if (DEBUGV) Log.v(TAG, "~~~ hard reset wakelock");
     }
 
     synchronized void acquire(long timeout) {
@@ -55,8 +55,7 @@
                     PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
         }
         if (!mWakeLock.isHeld()) mWakeLock.acquire();
-        if (DEBUGV) Log.v(TAG, "acquire wakelock: holder count="
-                + mHolders.size());
+        if (DEBUG) Log.v(TAG, "acquire count=" + mHolders.size());
     }
 
     synchronized void release(Object holder) {
@@ -65,7 +64,6 @@
                 && mWakeLock.isHeld()) {
             mWakeLock.release();
         }
-        if (DEBUGV) Log.v(TAG, "release wakelock: holder count="
-                + mHolders.size());
+        if (DEBUG) Log.v(TAG, "release count=" + mHolders.size());
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index aadcaad..82abe3a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -123,6 +123,8 @@
     private final LruCache<String, ScanResult> mScanResultCache;
 
     private String mInterfaceName;
+    /* Tethering interface could be seperate from wlan interface */
+    private String mTetherInterfaceName;
 
     private int mLastSignalLevel = -1;
     private String mLastBssid;
@@ -156,6 +158,14 @@
     /* Tracks sequence number on stop failure message */
     private int mSupplicantStopFailureToken = 0;
 
+    /**
+     * Tether state change notification time out
+     */
+    private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
+
+    /* Tracks sequence number on a tether notification time out */
+    private int mTetherToken = 0;
+
     private LinkProperties mLinkProperties;
 
     // Wakelock held during wifi start/stop and driver load/unload
@@ -240,10 +250,12 @@
     static final int CMD_REQUEST_AP_CONFIG                = BASE + 27;
     /* Response to access point configuration request */
     static final int CMD_RESPONSE_AP_CONFIG               = BASE + 28;
-    /* Set configuration on tether interface */
-    static final int CMD_TETHER_INTERFACE                 = BASE + 29;
+    /* Invoked when getting a tether state change notification */
+    static final int CMD_TETHER_STATE_CHANGE              = BASE + 29;
+    /* A delayed message sent to indicate tether state change failed to arrive */
+    static final int CMD_TETHER_NOTIFICATION_TIMED_OUT    = BASE + 30;
 
-    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 30;
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 31;
 
     /* Supplicant commands */
     /* Is supplicant alive ? */
@@ -294,8 +306,6 @@
     static final int CMD_SET_HIGH_PERF_MODE               = BASE + 77;
     /* Set the country code */
     static final int CMD_SET_COUNTRY_CODE                 = BASE + 80;
-    /* Request connectivity manager wake lock before driver stop */
-    static final int CMD_REQUEST_CM_WAKELOCK              = BASE + 81;
     /* Enables RSSI poll */
     static final int CMD_ENABLE_RSSI_POLL                 = BASE + 82;
     /* RSSI poll */
@@ -358,6 +368,10 @@
     private static final int SUCCESS = 1;
     private static final int FAILURE = -1;
 
+    /* Phone in emergency call back mode */
+    private static final int IN_ECM_STATE = 1;
+    private static final int NOT_IN_ECM_STATE = 0;
+
     /**
      * 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
@@ -455,12 +469,25 @@
     private State mSoftApStartingState = new SoftApStartingState();
     /* Soft ap is running */
     private State mSoftApStartedState = new SoftApStartedState();
+    /* Soft ap is running and we are waiting for tether notification */
+    private State mTetheringState = new TetheringState();
     /* Soft ap is running and we are tethered through connectivity service */
     private State mTetheredState = new TetheredState();
+    /* Waiting for untether confirmation to stop soft Ap */
+    private State mSoftApStoppingState = new SoftApStoppingState();
 
     /* Wait till p2p is disabled */
     private State mWaitForP2pDisableState = new WaitForP2pDisableState();
 
+    private class TetherStateChange {
+        ArrayList<String> available;
+        ArrayList<String> active;
+        TetherStateChange(ArrayList<String> av, ArrayList<String> ac) {
+            available = av;
+            active = ac;
+        }
+    }
+
 
     /**
      * One of  {@link WifiManager#WIFI_STATE_DISABLED},
@@ -562,7 +589,9 @@
                 public void onReceive(Context context, Intent intent) {
                     ArrayList<String> available = intent.getStringArrayListExtra(
                             ConnectivityManager.EXTRA_AVAILABLE_TETHER);
-                    sendMessage(CMD_TETHER_INTERFACE, available);
+                    ArrayList<String> active = intent.getStringArrayListExtra(
+                            ConnectivityManager.EXTRA_ACTIVE_TETHER);
+                    sendMessage(CMD_TETHER_STATE_CHANGE, new TetherStateChange(available, active));
                 }
             },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
 
@@ -603,7 +632,9 @@
             addState(mSupplicantStoppingState, mDefaultState);
             addState(mSoftApStartingState, mDefaultState);
             addState(mSoftApStartedState, mDefaultState);
+                addState(mTetheringState, mSoftApStartedState);
                 addState(mTetheredState, mSoftApStartedState);
+            addState(mSoftApStoppingState, mDefaultState);
             addState(mWaitForP2pDisableState, mDefaultState);
 
         setInitialState(mInitialState);
@@ -751,11 +782,11 @@
     /**
      * TODO: doc
      */
-    public void setDriverStart(boolean enable) {
+    public void setDriverStart(boolean enable, boolean ecm) {
         if (enable) {
             sendMessage(CMD_START_DRIVER);
         } else {
-            sendMessage(CMD_STOP_DRIVER);
+            sendMessage(obtainMessage(CMD_STOP_DRIVER, ecm ? IN_ECM_STATE : NOT_IN_ECM_STATE, 0));
         }
     }
 
@@ -1032,15 +1063,6 @@
         return result;
     }
 
-    /**
-     * Request a wakelock with connectivity service to
-     * keep the device awake until we hand-off from wifi
-     * to an alternate network
-     */
-    public void requestCmWakeLock() {
-        sendMessage(CMD_REQUEST_CM_WAKELOCK);
-    }
-
     public void updateBatteryWorkSource(WorkSource newSource) {
         synchronized (mRunningWifiUids) {
             try {
@@ -1139,6 +1161,7 @@
                         loge("Error tethering on " + intf);
                         return false;
                     }
+                    mTetherInterfaceName = intf;
                     return true;
                 }
             }
@@ -1165,11 +1188,27 @@
             loge("Error resetting interface " + mInterfaceName + ", :" + e);
         }
 
-        if (mCm.untether(mInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+        if (mCm.untether(mTetherInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
             loge("Untether initiate failed!");
         }
     }
 
+    private boolean isWifiTethered(ArrayList<String> active) {
+
+        checkAndSetConnectivityInstance();
+
+        String[] wifiRegexs = mCm.getTetherableWifiRegexs();
+        for (String intf : active) {
+            for (String regex : wifiRegexs) {
+                if (intf.matches(regex)) {
+                    return true;
+                }
+            }
+        }
+        // We found no interfaces that are tethered
+        return false;
+    }
+
     /**
      * Set the country code from the system setting value, if any.
      */
@@ -1800,7 +1839,8 @@
                 case CMD_START_AP_SUCCESS:
                 case CMD_START_AP_FAILURE:
                 case CMD_STOP_AP:
-                case CMD_TETHER_INTERFACE:
+                case CMD_TETHER_STATE_CHANGE:
+                case CMD_TETHER_NOTIFICATION_TIMED_OUT:
                 case CMD_START_SCAN:
                 case CMD_DISCONNECT:
                 case CMD_RECONNECT:
@@ -1820,7 +1860,6 @@
                 case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
-                case CMD_REQUEST_CM_WAKELOCK:
                 case CMD_CONNECT_NETWORK:
                 case CMD_SAVE_NETWORK:
                 case CMD_FORGET_NETWORK:
@@ -2541,16 +2580,25 @@
                     WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive);
                     break;
                 case CMD_STOP_DRIVER:
-                    /* Already doing a delayed stop */
-                    if (mInDelayedStop) {
+                    int mode = message.arg1;
+
+                    /* Already doing a delayed stop && not in ecm state */
+                    if (mInDelayedStop && mode != IN_ECM_STATE) {
                         if (DBG) log("Already in delayed stop");
                         break;
                     }
                     mInDelayedStop = true;
                     mDelayedStopCounter++;
                     if (DBG) log("Delayed stop message " + mDelayedStopCounter);
-                    sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER, mDelayedStopCounter,
-                            0), DELAYED_DRIVER_STOP_MS);
+
+                    if (mode == IN_ECM_STATE) {
+                        /* send a shut down immediately */
+                        sendMessage(obtainMessage(CMD_DELAYED_STOP_DRIVER, mDelayedStopCounter, 0));
+                    } else {
+                        /* send regular delayed shut down */
+                        sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER,
+                                mDelayedStopCounter, 0), DELAYED_DRIVER_STOP_MS);
+                    }
                     break;
                 case CMD_START_DRIVER:
                     if (mInDelayedStop) {
@@ -2977,10 +3025,6 @@
                     WifiNative.disconnectCommand();
                     transitionTo(mDisconnectingState);
                     break;
-                case CMD_REQUEST_CM_WAKELOCK:
-                    checkAndSetConnectivityInstance();
-                    mCm.requestNetworkTransitionWakelock(TAG);
-                    break;
                 case CMD_SET_SCAN_MODE:
                     if (message.arg1 == SCAN_ONLY_MODE) {
                         sendMessage(CMD_DISCONNECT);
@@ -3053,6 +3097,11 @@
         }
         @Override
         public void exit() {
+
+            /* Request a CS wakelock during transition to mobile */
+            checkAndSetConnectivityInstance();
+            mCm.requestNetworkTransitionWakelock(TAG);
+
             /* If a scan result is pending in connected state, the supplicant
              * is in SCAN_ONLY_MODE. Restore CONNECT_MODE on exit
              */
@@ -3284,7 +3333,7 @@
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
                 case CMD_STOP_PACKET_FILTERING:
-                case CMD_TETHER_INTERFACE:
+                case CMD_TETHER_STATE_CHANGE:
                 case WifiP2pService.P2P_ENABLE_PENDING:
                     deferMessage(message);
                     break;
@@ -3326,7 +3375,8 @@
                 case CMD_STOP_AP:
                     if (DBG) log("Stopping Soft AP");
                     setWifiApState(WIFI_AP_STATE_DISABLING);
-                    stopTethering();
+
+                    /* We have not tethered at this point, so we just shutdown soft Ap */
                     try {
                         mNwService.stopAccessPoint(mInterfaceName);
                     } catch(Exception e) {
@@ -3342,10 +3392,10 @@
                    loge("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);
+                case CMD_TETHER_STATE_CHANGE:
+                    TetherStateChange stateChange = (TetherStateChange) message.obj;
+                    if (startTethering(stateChange.available)) {
+                        transitionTo(mTetheringState);
                     }
                     break;
                 case WifiP2pService.P2P_ENABLE_PENDING:
@@ -3405,6 +3455,58 @@
         }
     }
 
+    class TetheringState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+            /* Send ourselves a delayed message to shut down if tethering fails to notify */
+            sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
+                    ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            switch(message.what) {
+                case CMD_TETHER_STATE_CHANGE:
+                    TetherStateChange stateChange = (TetherStateChange) message.obj;
+                    if (isWifiTethered(stateChange.active)) {
+                        transitionTo(mTetheredState);
+                    }
+                    return HANDLED;
+                case CMD_TETHER_NOTIFICATION_TIMED_OUT:
+                    if (message.arg1 == mTetherToken) {
+                        loge("Failed to get tether update, shutdown soft access point");
+                        setWifiApEnabled(null, false);
+                    }
+                    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:
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    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() {
@@ -3415,13 +3517,89 @@
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString() + "\n");
             switch(message.what) {
-               case CMD_TETHER_INTERFACE:
-                    // Ignore any duplicate interface available notifications
-                    // when in tethered state
+                case CMD_TETHER_STATE_CHANGE:
+                    TetherStateChange stateChange = (TetherStateChange) message.obj;
+                    if (!isWifiTethered(stateChange.active)) {
+                        loge("Tethering reports wifi as untethered!, shut down soft Ap");
+                        setWifiApEnabled(null, false);
+                    }
                     return HANDLED;
+                case CMD_STOP_AP:
+                    if (DBG) log("Untethering before stopping AP");
+                    setWifiApState(WIFI_AP_STATE_DISABLING);
+                    stopTethering();
+                    transitionTo(mSoftApStoppingState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
+            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            return HANDLED;
+        }
+    }
+
+    class SoftApStoppingState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+            /* Send ourselves a delayed message to shut down if tethering fails to notify */
+            sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
+                    ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
+
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            switch(message.what) {
+                case CMD_TETHER_STATE_CHANGE:
+                    TetherStateChange stateChange = (TetherStateChange) message.obj;
+
+                    /* Wait till wifi is untethered */
+                    if (isWifiTethered(stateChange.active)) break;
+
+                    try {
+                        mNwService.stopAccessPoint(mInterfaceName);
+                    } catch(Exception e) {
+                        loge("Exception in stopAccessPoint()");
+                    }
+                    transitionTo(mDriverLoadedState);
+                    break;
+                case CMD_TETHER_NOTIFICATION_TIMED_OUT:
+                    if (message.arg1 == mTetherToken) {
+                        loge("Failed to get tether update, force stop access point");
+                        try {
+                            mNwService.stopAccessPoint(mInterfaceName);
+                        } catch(Exception e) {
+                            loge("Exception in stopAccessPoint()");
+                        }
+                        transitionTo(mDriverLoadedState);
+                    }
+                    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:
+                case WifiP2pService.P2P_ENABLE_PENDING:
+                    deferMessage(message);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            return HANDLED;
         }
     }
 
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index b4cbd01..b27c60f 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -37,6 +37,7 @@
 import android.provider.Settings.Secure;
 import android.util.Log;
 
+import com.android.internal.R;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -68,7 +69,8 @@
 
     private static final boolean DBG = false;
     private static final String TAG = "WifiWatchdogStateMachine";
-    private static final String WATCHDOG_NOTIFICATION_ID = "Android.System.WifiWatchdog";
+    private static final String DISABLED_NETWORK_NOTIFICATION_ID = "WifiWatchdog.networkdisabled";
+    private static final String WALLED_GARDEN_NOTIFICATION_ID = "WifiWatchdog.walledgarden";
 
     private static final int WIFI_SIGNAL_LEVELS = 4;
     /**
@@ -148,6 +150,7 @@
     private ConnectedState mConnectedState = new ConnectedState();
     private DnsCheckingState mDnsCheckingState = new DnsCheckingState();
     private OnlineWatchState mOnlineWatchState = new OnlineWatchState();
+    private OnlineState mOnlineState = new OnlineState();
     private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState();
     private DelayWalledGardenState mDelayWalledGardenState = new DelayWalledGardenState();
     private WalledGardenState mWalledGardenState = new WalledGardenState();
@@ -161,6 +164,7 @@
     private int mMinDnsResponses;
     private int mDnsPingTimeoutMs;
     private long mBlacklistFollowupIntervalMs;
+    private boolean mPoorNetworkDetectionEnabled;
     private boolean mWalledGardenTestEnabled;
     private String mWalledGardenUrl;
 
@@ -185,7 +189,8 @@
      */
     public boolean mDisableAPNextFailure = false;
     private static boolean sWifiOnly = false;
-    private boolean mNotificationShown;
+    private boolean mDisabledNotificationShown;
+    private boolean mWalledGardenNotificationShown;
     public boolean mHasConnectedWifiManager = false;
 
     /**
@@ -223,6 +228,7 @@
                     addState(mWalledGardenState, mConnectedState);
                     addState(mBlacklistedApState, mConnectedState);
                     addState(mOnlineWatchState, mConnectedState);
+                    addState(mOnlineState, mConnectedState);
 
         setInitialState(mWatchdogDisabledState);
         updateSettings();
@@ -408,6 +414,10 @@
         mBlacklistFollowupIntervalMs = Secure.getLong(mContentResolver,
                 Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS,
                 DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS);
+        //TODO: enable this by default after changing watchdog behavior
+        //Also, update settings description
+        mPoorNetworkDetectionEnabled = getSettingsBoolean(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false);
         mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver,
                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true);
         mWalledGardenUrl = getSettingsStr(mContentResolver,
@@ -477,51 +487,76 @@
         mLastWalledGardenCheckTime = null;
         mNumCheckFailures = 0;
         mBssids.clear();
-        cancelNetworkNotification();
+        setDisabledNetworkNotificationVisible(false);
+        setWalledGardenNotificationVisible(false);
     }
 
-    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(String ssid) {
-        Resources r = Resources.getSystem();
-        CharSequence title =
-                r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled);
-        String msg = ssid +
-                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(WifiManager.ACTION_PICK_WIFI_NETWORK)
-                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
-            .setWhen(System.currentTimeMillis())
-            .setAutoCancel(true)
-            .getNotification();
-
-        NotificationManager notificationManager = (NotificationManager) mContext
-                .getSystemService(Context.NOTIFICATION_SERVICE);
-
-        notificationManager.notify(WATCHDOG_NOTIFICATION_ID, 1, wifiDisabledWarning);
-        mNotificationShown = true;
-    }
-
-    public void cancelNetworkNotification() {
-        if (mNotificationShown) {
-            NotificationManager notificationManager = (NotificationManager) mContext
-                    .getSystemService(Context.NOTIFICATION_SERVICE);
-            notificationManager.cancel(WATCHDOG_NOTIFICATION_ID, 1);
-            mNotificationShown = false;
+    private void setWalledGardenNotificationVisible(boolean visible) {
+        // If it should be hidden and it is already hidden, then noop
+        if (!visible && !mWalledGardenNotificationShown) {
+            return;
         }
+
+        Resources r = Resources.getSystem();
+        NotificationManager notificationManager = (NotificationManager) mContext
+            .getSystemService(Context.NOTIFICATION_SERVICE);
+
+        if (visible) {
+            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mWalledGardenUrl));
+            intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            CharSequence title = r.getString(R.string.wifi_available_sign_in, 0);
+            CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed,
+                    mConnectionInfo.getSSID());
+
+            Notification notification = new Notification();
+            notification.when = 0;
+            notification.icon = com.android.internal.R.drawable.stat_notify_wifi_in_range;
+            notification.flags = Notification.FLAG_AUTO_CANCEL;
+            notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+            notification.tickerText = title;
+            notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
+
+            notificationManager.notify(WALLED_GARDEN_NOTIFICATION_ID, 1, notification);
+        } else {
+            notificationManager.cancel(WALLED_GARDEN_NOTIFICATION_ID, 1);
+        }
+        mWalledGardenNotificationShown = visible;
+    }
+
+    private void setDisabledNetworkNotificationVisible(boolean visible) {
+        // If it should be hidden and it is already hidden, then noop
+        if (!visible && !mDisabledNotificationShown) {
+            return;
+        }
+
+        Resources r = Resources.getSystem();
+        NotificationManager notificationManager = (NotificationManager) mContext
+            .getSystemService(Context.NOTIFICATION_SERVICE);
+
+        if (visible) {
+            CharSequence title = r.getText(R.string.wifi_watchdog_network_disabled);
+            String msg = mConnectionInfo.getSSID() +
+                r.getText(R.string.wifi_watchdog_network_disabled_detailed);
+
+            Notification wifiDisabledWarning = new Notification.Builder(mContext)
+                .setSmallIcon(R.drawable.stat_sys_warning)
+                .setDefaults(Notification.DEFAULT_ALL)
+                .setTicker(title)
+                .setContentTitle(title)
+                .setContentText(msg)
+                .setContentIntent(PendingIntent.getActivity(mContext, 0,
+                            new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK)
+                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
+                .setWhen(System.currentTimeMillis())
+                .setAutoCancel(true)
+                .getNotification();
+
+            notificationManager.notify(DISABLED_NETWORK_NOTIFICATION_ID, 1, wifiDisabledWarning);
+        } else {
+            notificationManager.cancel(DISABLED_NETWORK_NOTIFICATION_ID, 1);
+        }
+        mDisabledNotificationShown = visible;
     }
 
     class DefaultState extends State {
@@ -576,9 +611,10 @@
                     NetworkInfo networkInfo = (NetworkInfo)
                             stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
 
+                    setDisabledNetworkNotificationVisible(false);
+                    setWalledGardenNotificationVisible(false);
                     switch (networkInfo.getState()) {
                         case CONNECTED:
-                            cancelNetworkNotification();
                             WifiInfo wifiInfo = (WifiInfo)
                                 stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                             if (wifiInfo == null) {
@@ -594,9 +630,13 @@
 
                             initConnection(wifiInfo);
                             mConnectionInfo = wifiInfo;
-                            updateBssids();
-                            transitionTo(mDnsCheckingState);
                             mNetEventCounter++;
+                            if (mPoorNetworkDetectionEnabled) {
+                                updateBssids();
+                                transitionTo(mDnsCheckingState);
+                            } else {
+                                transitionTo(mDelayWalledGardenState);
+                            }
                             break;
                         default:
                             mNetEventCounter++;
@@ -648,12 +688,18 @@
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case EVENT_SCAN_RESULTS_AVAILABLE:
-                    updateBssids();
+                    if (mPoorNetworkDetectionEnabled) {
+                        updateBssids();
+                    }
                     return HANDLED;
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
-                    // Stop current checks, but let state update
-                    transitionTo(mOnlineWatchState);
-                    return NOT_HANDLED;
+                    updateSettings();
+                    if (mPoorNetworkDetectionEnabled) {
+                        transitionTo(mOnlineWatchState);
+                    } else {
+                        transitionTo(mOnlineState);
+                    }
+                    return HANDLED;
             }
             return NOT_HANDLED;
         }
@@ -800,7 +846,11 @@
                         transitionTo(mWalledGardenState);
                     } else {
                         if (DBG) log("Walled garden test complete - online");
-                        transitionTo(mOnlineWatchState);
+                        if (mPoorNetworkDetectionEnabled) {
+                            transitionTo(mOnlineWatchState);
+                        } else {
+                            transitionTo(mOnlineState);
+                        }
                     }
                     return HANDLED;
                 default:
@@ -932,6 +982,13 @@
         }
     }
 
+
+    /* Child state of ConnectedState indicating that we are online
+     * and there is nothing to do
+     */
+    class OnlineState extends State {
+    }
+
     class DnsCheckFailureState extends State {
 
         @Override
@@ -974,7 +1031,7 @@
                 }
                 mWifiManager.disableNetwork(networkId, WifiConfiguration.DISABLED_DNS_FAILURE);
                 if (mShowDisabledNotification && mConnectionInfo.isExplicitConnect()) {
-                    displayDisabledNetworkNotification(mConnectionInfo.getSSID());
+                    setDisabledNetworkNotificationVisible(true);
                 }
                 transitionTo(mNotConnectedState);
             } else {
@@ -1007,8 +1064,12 @@
                 }
                 return HANDLED;
             }
-            popUpBrowser();
-            transitionTo(mOnlineWatchState);
+            setWalledGardenNotificationVisible(true);
+            if (mPoorNetworkDetectionEnabled) {
+                transitionTo(mOnlineWatchState);
+            } else {
+                transitionTo(mOnlineState);
+            }
             return HANDLED;
         }
     }