Merge "Notify Java side to start when transition into full screen mode without a reload." into jb-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 539b84e..0d8a7cda 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -132,6 +132,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClientCallback.java)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClientCallback.P)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClient.P)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/16.txt b/api/16.txt
index 25885fb..e4b098f 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -675,6 +675,7 @@
     field public static final int maxWidth = 16843039; // 0x101011f
     field public static final int measureAllChildren = 16843018; // 0x101010a
     field public static final int measureWithLargestChild = 16843476; // 0x10102d4
+    field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeType = 16842790; // 0x1010026
     field public static final int minDate = 16843583; // 0x101033f
@@ -1789,6 +1790,7 @@
     field public static final int Widget_DeviceDefault_Light_ListPopupWindow = 16974235; // 0x103019b
     field public static final int Widget_DeviceDefault_Light_ListView = 16974210; // 0x1030182
     field public static final int Widget_DeviceDefault_Light_ListView_DropDown = 16974205; // 0x103017d
+    field public static final int Widget_DeviceDefault_Light_MediaRouteButton = 16974296; // 0x10301d8
     field public static final int Widget_DeviceDefault_Light_PopupMenu = 16974236; // 0x103019c
     field public static final int Widget_DeviceDefault_Light_PopupWindow = 16974211; // 0x1030183
     field public static final int Widget_DeviceDefault_Light_ProgressBar = 16974212; // 0x1030184
@@ -1814,6 +1816,7 @@
     field public static final int Widget_DeviceDefault_ListPopupWindow = 16974180; // 0x1030164
     field public static final int Widget_DeviceDefault_ListView = 16974158; // 0x103014e
     field public static final int Widget_DeviceDefault_ListView_DropDown = 16974153; // 0x1030149
+    field public static final int Widget_DeviceDefault_MediaRouteButton = 16974295; // 0x10301d7
     field public static final int Widget_DeviceDefault_PopupMenu = 16974181; // 0x1030165
     field public static final int Widget_DeviceDefault_PopupWindow = 16974159; // 0x103014f
     field public static final int Widget_DeviceDefault_ProgressBar = 16974160; // 0x1030150
@@ -1905,6 +1908,7 @@
     field public static final int Widget_Holo_Light_ListPopupWindow = 16974043; // 0x10300db
     field public static final int Widget_Holo_Light_ListView = 16974018; // 0x10300c2
     field public static final int Widget_Holo_Light_ListView_DropDown = 16974013; // 0x10300bd
+    field public static final int Widget_Holo_Light_MediaRouteButton = 16974294; // 0x10301d6
     field public static final int Widget_Holo_Light_PopupMenu = 16974044; // 0x10300dc
     field public static final int Widget_Holo_Light_PopupWindow = 16974019; // 0x10300c3
     field public static final int Widget_Holo_Light_ProgressBar = 16974020; // 0x10300c4
@@ -1930,6 +1934,7 @@
     field public static final int Widget_Holo_ListPopupWindow = 16973997; // 0x10300ad
     field public static final int Widget_Holo_ListView = 16973975; // 0x1030097
     field public static final int Widget_Holo_ListView_DropDown = 16973970; // 0x1030092
+    field public static final int Widget_Holo_MediaRouteButton = 16974293; // 0x10301d5
     field public static final int Widget_Holo_PopupMenu = 16973998; // 0x10300ae
     field public static final int Widget_Holo_PopupWindow = 16973976; // 0x1030098
     field public static final int Widget_Holo_ProgressBar = 16973977; // 0x1030099
@@ -3671,6 +3676,23 @@
     method public android.view.Window startActivity(java.lang.String, android.content.Intent);
   }
 
+  public class MediaRouteActionProvider extends android.view.ActionProvider {
+    ctor public MediaRouteActionProvider(android.content.Context);
+    method public android.view.View onCreateActionView();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
+    method public void setRouteTypes(int);
+  }
+
+  public class MediaRouteButton extends android.view.View {
+    ctor public MediaRouteButton(android.content.Context);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet, int);
+    method public int getRouteTypes();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
+    method public void setRouteTypes(int);
+    method public void showDialog();
+  }
+
   public class NativeActivity extends android.app.Activity implements android.view.InputQueue.Callback android.view.SurfaceHolder.Callback2 android.view.ViewTreeObserver.OnGlobalLayoutListener {
     ctor public NativeActivity();
     method public void onGlobalLayout();
@@ -5317,6 +5339,7 @@
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
     field public static final java.lang.String LOCATION_SERVICE = "location";
+    field public static final java.lang.String MEDIA_ROUTER_SERVICE = "media_router";
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final int MODE_MULTI_PROCESS = 4; // 0x4
@@ -11486,6 +11509,87 @@
     field public static final int DEFAULT = 0; // 0x0
   }
 
+  public class MediaRouter {
+    method public void addCallback(int, android.media.MediaRouter.Callback);
+    method public void addUserRoute(android.media.MediaRouter.UserRouteInfo);
+    method public void clearUserRoutes();
+    method public android.media.MediaRouter.RouteCategory createRouteCategory(java.lang.CharSequence, boolean);
+    method public android.media.MediaRouter.RouteCategory createRouteCategory(int, boolean);
+    method public android.media.MediaRouter.UserRouteInfo createUserRoute(android.media.MediaRouter.RouteCategory);
+    method public android.media.MediaRouter.RouteCategory getCategoryAt(int);
+    method public int getCategoryCount();
+    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
+    method public int getRouteCount();
+    method public android.media.MediaRouter.RouteInfo getSelectedRoute(int);
+    method public void removeCallback(android.media.MediaRouter.Callback);
+    method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
+    method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
+    field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
+    field public static final int ROUTE_TYPE_USER = 8388608; // 0x800000
+  }
+
+  public static abstract class MediaRouter.Callback {
+    ctor public MediaRouter.Callback();
+    method public abstract void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public abstract void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public abstract void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+  }
+
+  public static class MediaRouter.RouteCategory {
+    method public java.lang.CharSequence getName();
+    method public java.lang.CharSequence getName(android.content.Context);
+    method public java.util.List<android.media.MediaRouter.RouteInfo> getRoutes(java.util.List<android.media.MediaRouter.RouteInfo>);
+    method public int getSupportedTypes();
+    method public boolean isGroupable();
+  }
+
+  public static class MediaRouter.RouteGroup extends android.media.MediaRouter.RouteInfo {
+    method public void addRoute(android.media.MediaRouter.RouteInfo);
+    method public void addRoute(android.media.MediaRouter.RouteInfo, int);
+    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
+    method public int getRouteCount();
+    method public void removeRoute(android.media.MediaRouter.RouteInfo);
+    method public void removeRoute(int);
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
+  }
+
+  public static class MediaRouter.RouteInfo {
+    method public android.media.MediaRouter.RouteCategory getCategory();
+    method public android.media.MediaRouter.RouteGroup getGroup();
+    method public android.graphics.drawable.Drawable getIconDrawable();
+    method public java.lang.CharSequence getName();
+    method public java.lang.CharSequence getName(android.content.Context);
+    method public java.lang.CharSequence getStatus();
+    method public int getSupportedTypes();
+  }
+
+  public static class MediaRouter.SimpleCallback extends android.media.MediaRouter.Callback {
+    ctor public MediaRouter.SimpleCallback();
+    method public void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+  }
+
+  public static class MediaRouter.UserRouteInfo extends android.media.MediaRouter.RouteInfo {
+    method public java.lang.Object getTag();
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
+    method public void setName(java.lang.CharSequence);
+    method public void setName(int);
+    method public void setRemoteControlClient(android.media.RemoteControlClient);
+    method public void setStatus(java.lang.CharSequence);
+    method public void setTag(java.lang.Object);
+  }
+
   public class MediaScannerConnection implements android.content.ServiceConnection {
     ctor public MediaScannerConnection(android.content.Context, android.media.MediaScannerConnection.MediaScannerConnectionClient);
     method public void connect();
@@ -22710,7 +22814,8 @@
   public abstract class ActionProvider {
     ctor public ActionProvider(android.content.Context);
     method public boolean hasSubMenu();
-    method public abstract android.view.View onCreateActionView();
+    method public abstract deprecated android.view.View onCreateActionView();
+    method public android.view.View onCreateActionView(android.view.MenuItem);
     method public boolean onPerformDefaultAction();
     method public void onPrepareSubMenu(android.view.SubMenu);
   }
@@ -23097,6 +23202,7 @@
     field public static final int KEYCODE_ALT_RIGHT = 58; // 0x3a
     field public static final int KEYCODE_APOSTROPHE = 75; // 0x4b
     field public static final int KEYCODE_APP_SWITCH = 187; // 0xbb
+    field public static final int KEYCODE_ASSIST = 219; // 0xdb
     field public static final int KEYCODE_AT = 77; // 0x4d
     field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6
     field public static final int KEYCODE_AVR_POWER = 181; // 0xb5
diff --git a/api/current.txt b/api/current.txt
index 3beaaa5..cd71bfd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -98,7 +98,6 @@
     field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
-    field public static final java.lang.String ROUTE_MEDIA_OUTPUT = "android.permission.ROUTE_MEDIA_OUTPUT";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -3680,6 +3679,7 @@
   public class MediaRouteActionProvider extends android.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context);
     method public android.view.View onCreateActionView();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
     method public void setRouteTypes(int);
   }
 
@@ -3688,7 +3688,9 @@
     ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet);
     ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet, int);
     method public int getRouteTypes();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
     method public void setRouteTypes(int);
+    method public void showDialog();
   }
 
   public class NativeActivity extends android.app.Activity implements android.view.InputQueue.Callback android.view.SurfaceHolder.Callback2 android.view.ViewTreeObserver.OnGlobalLayoutListener {
@@ -5337,6 +5339,7 @@
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
     field public static final java.lang.String LOCATION_SERVICE = "location";
+    field public static final java.lang.String MEDIA_ROUTER_SERVICE = "media_router";
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final int MODE_MULTI_PROCESS = 4; // 0x4
@@ -11511,8 +11514,8 @@
     method public void addUserRoute(android.media.MediaRouter.UserRouteInfo);
     method public void clearUserRoutes();
     method public android.media.MediaRouter.RouteCategory createRouteCategory(java.lang.CharSequence, boolean);
+    method public android.media.MediaRouter.RouteCategory createRouteCategory(int, boolean);
     method public android.media.MediaRouter.UserRouteInfo createUserRoute(android.media.MediaRouter.RouteCategory);
-    method public static android.media.MediaRouter forApplication(android.content.Context);
     method public android.media.MediaRouter.RouteCategory getCategoryAt(int);
     method public int getCategoryCount();
     method public android.media.MediaRouter.RouteInfo getRouteAt(int);
@@ -11521,56 +11524,69 @@
     method public void removeCallback(android.media.MediaRouter.Callback);
     method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
     method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
-    method public void setSelectedRouteVolume(int, float);
     field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
     field public static final int ROUTE_TYPE_USER = 8388608; // 0x800000
   }
 
-  public static abstract interface MediaRouter.Callback {
-    method public abstract void onRouteAdded(int, android.media.MediaRouter.RouteInfo);
-    method public abstract void onRouteChanged(android.media.MediaRouter.RouteInfo);
-    method public abstract void onRouteRemoved(int, android.media.MediaRouter.RouteInfo);
-    method public abstract void onRouteSelected(int, android.media.MediaRouter.RouteInfo);
-    method public abstract void onRouteUnselected(int, android.media.MediaRouter.RouteInfo);
-    method public abstract void onVolumeChanged(int, float);
+  public static abstract class MediaRouter.Callback {
+    ctor public MediaRouter.Callback();
+    method public abstract void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public abstract void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public abstract void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
   }
 
-  public class MediaRouter.RouteCategory {
+  public static class MediaRouter.RouteCategory {
     method public java.lang.CharSequence getName();
-    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
-    method public int getRouteCount();
+    method public java.lang.CharSequence getName(android.content.Context);
+    method public java.util.List<android.media.MediaRouter.RouteInfo> getRoutes(java.util.List<android.media.MediaRouter.RouteInfo>);
     method public int getSupportedTypes();
     method public boolean isGroupable();
   }
 
-  public class MediaRouter.RouteGroup extends android.media.MediaRouter.RouteInfo {
+  public static class MediaRouter.RouteGroup extends android.media.MediaRouter.RouteInfo {
     method public void addRoute(android.media.MediaRouter.RouteInfo);
     method public void addRoute(android.media.MediaRouter.RouteInfo, int);
+    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
+    method public int getRouteCount();
     method public void removeRoute(android.media.MediaRouter.RouteInfo);
     method public void removeRoute(int);
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
   }
 
-  public class MediaRouter.RouteInfo {
+  public static class MediaRouter.RouteInfo {
     method public android.media.MediaRouter.RouteCategory getCategory();
     method public android.media.MediaRouter.RouteGroup getGroup();
+    method public android.graphics.drawable.Drawable getIconDrawable();
     method public java.lang.CharSequence getName();
+    method public java.lang.CharSequence getName(android.content.Context);
     method public java.lang.CharSequence getStatus();
     method public int getSupportedTypes();
-    method public float getVolume();
+    method public java.lang.Object getTag();
+    method public void setTag(java.lang.Object);
   }
 
-  public static class MediaRouter.SimpleCallback implements android.media.MediaRouter.Callback {
+  public static class MediaRouter.SimpleCallback extends android.media.MediaRouter.Callback {
     ctor public MediaRouter.SimpleCallback();
-    method public void onRouteAdded(int, android.media.MediaRouter.RouteInfo);
-    method public void onRouteChanged(android.media.MediaRouter.RouteInfo);
-    method public void onRouteRemoved(int, android.media.MediaRouter.RouteInfo);
-    method public void onRouteSelected(int, android.media.MediaRouter.RouteInfo);
-    method public void onRouteUnselected(int, android.media.MediaRouter.RouteInfo);
-    method public void onVolumeChanged(int, float);
+    method public void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
   }
 
-  public class MediaRouter.UserRouteInfo extends android.media.MediaRouter.RouteInfo {
+  public static class MediaRouter.UserRouteInfo extends android.media.MediaRouter.RouteInfo {
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
     method public void setName(java.lang.CharSequence);
+    method public void setName(int);
+    method public void setRemoteControlClient(android.media.RemoteControlClient);
     method public void setStatus(java.lang.CharSequence);
   }
 
@@ -23186,6 +23202,7 @@
     field public static final int KEYCODE_ALT_RIGHT = 58; // 0x3a
     field public static final int KEYCODE_APOSTROPHE = 75; // 0x4b
     field public static final int KEYCODE_APP_SWITCH = 187; // 0xbb
+    field public static final int KEYCODE_ASSIST = 219; // 0xdb
     field public static final int KEYCODE_AT = 77; // 0x4d
     field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6
     field public static final int KEYCODE_AVR_POWER = 181; // 0xb5
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 1d5f207..225be9c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -160,7 +160,7 @@
     codec->setDitherImage(false);
     if (codec) {
         codec->decode(&stream, &bitmap,
-                SkBitmap::kRGB_565_Config,
+                SkBitmap::kARGB_8888_Config,
                 SkImageDecoder::kDecodePixels_Mode);
         delete codec;
     }
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 0bc7371..96a6438 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -53,11 +53,7 @@
         unlink(pkgdir);
         return -errno;
     }
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
+
     if (mkdir(libdir, 0755) < 0) {
         ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
         unlink(pkgdir);
@@ -75,6 +71,13 @@
         unlink(pkgdir);
         return -errno;
     }
+
+    if (chown(pkgdir, uid, gid) < 0) {
+        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libdir);
+        unlink(pkgdir);
+        return -errno;
+    }
     return 0;
 }
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4c35a8c..b902550 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -55,6 +55,7 @@
 import android.location.ILocationManager;
 import android.location.LocationManager;
 import android.media.AudioManager;
+import android.media.MediaRouter;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyManager;
@@ -288,6 +289,11 @@
                     return new AudioManager(ctx);
                 }});
 
+        registerService(MEDIA_ROUTER_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return new MediaRouter(ctx);
+                }});
+
         registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new ClipboardManager(ctx.getOuterContext(),
diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java
index 301b125..4860182 100644
--- a/core/java/android/app/MediaRouteActionProvider.java
+++ b/core/java/android/app/MediaRouteActionProvider.java
@@ -16,7 +16,10 @@
 
 package android.app;
 
+import com.android.internal.app.MediaRouteChooserDialogFragment;
+
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
 import android.util.Log;
@@ -33,11 +36,12 @@
     private MediaRouteButton mView;
     private int mRouteTypes;
     private final RouterCallback mRouterCallback = new RouterCallback();
+    private View.OnClickListener mExtendedSettingsListener;
 
     public MediaRouteActionProvider(Context context) {
         super(context);
         mContext = context;
-        mRouter = MediaRouter.forApplication(context);
+        mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
 
         // Start with live audio by default.
         // TODO Update this when new route types are added; segment by API level
@@ -76,23 +80,58 @@
         mView = new MediaRouteButton(mContext);
         mMenuItem.setVisible(mRouter.getRouteCount() > 1);
         mView.setRouteTypes(mRouteTypes);
+        mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
         return mView;
     }
 
     @Override
     public boolean onPerformDefaultAction() {
-        // Show routing dialog
+        final FragmentManager fm = getActivity().getFragmentManager();
+        // See if one is already attached to this activity.
+        MediaRouteChooserDialogFragment dialogFragment =
+                (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
+                MediaRouteChooserDialogFragment.FRAGMENT_TAG);
+        if (dialogFragment != null) {
+            Log.w(TAG, "onPerformDefaultAction(): Chooser dialog already showing!");
+            return false;
+        }
+
+        dialogFragment = new MediaRouteChooserDialogFragment();
+        dialogFragment.setExtendedSettingsClickListener(mExtendedSettingsListener);
+        dialogFragment.setRouteTypes(mRouteTypes);
+        dialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
         return true;
     }
 
+    private Activity getActivity() {
+        // Gross way of unwrapping the Activity so we can get the FragmentManager
+        Context context = mContext;
+        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        if (!(context instanceof Activity)) {
+            throw new IllegalStateException("The MediaRouteActionProvider's Context " +
+                    "is not an Activity.");
+        }
+
+        return (Activity) context;
+    }
+
+    public void setExtendedSettingsClickListener(View.OnClickListener listener) {
+        mExtendedSettingsListener = listener;
+        if (mView != null) {
+            mView.setExtendedSettingsClickListener(listener);
+        }
+    }
+
     private class RouterCallback extends MediaRouter.SimpleCallback {
         @Override
-        public void onRouteAdded(int type, RouteInfo info) {
+        public void onRouteAdded(MediaRouter router, RouteInfo info) {
             mMenuItem.setVisible(mRouter.getRouteCount() > 1);
         }
 
         @Override
-        public void onRouteRemoved(int type, RouteInfo info) {
+        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
             mMenuItem.setVisible(mRouter.getRouteCount() > 1);
         }
     }
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 3aabd5d..018b25d 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -17,8 +17,10 @@
 package android.app;
 
 import com.android.internal.R;
+import com.android.internal.app.MediaRouteChooserDialogFragment;
 
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
@@ -43,6 +45,9 @@
     private int mMinWidth;
     private int mMinHeight;
 
+    private OnClickListener mExtendedSettingsClickListener;
+    private MediaRouteChooserDialogFragment mDialogFragment;
+
     private static final int[] ACTIVATED_STATE_SET = {
         R.attr.state_activated
     };
@@ -58,7 +63,7 @@
     public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
-        mRouter = MediaRouter.forApplication(context);
+        mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
 
         TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
@@ -98,7 +103,7 @@
 
         if (mToggleMode) {
             if (mRemoteActive) {
-                mRouter.selectRoute(mRouteTypes, mRouter.getSystemAudioRoute());
+                mRouter.selectRouteInt(mRouteTypes, mRouter.getSystemAudioRoute());
             } else {
                 final int N = mRouter.getRouteCount();
                 for (int i = 0; i < N; i++) {
@@ -110,7 +115,7 @@
                 }
             }
         } else {
-            Log.d(TAG, "TODO: Implement the dialog!");
+            showDialog();
         }
 
         return handled;
@@ -260,24 +265,72 @@
         mRemoteIndicator.draw(canvas);
     }
 
+    public void setExtendedSettingsClickListener(OnClickListener listener) {
+        mExtendedSettingsClickListener = listener;
+        if (mDialogFragment != null) {
+            mDialogFragment.setExtendedSettingsClickListener(listener);
+        }
+    }
+
+    /**
+     * Asynchronously show the route chooser dialog.
+     * This will attach a {@link DialogFragment} to the containing Activity.
+     */
+    public void showDialog() {
+        final FragmentManager fm = getActivity().getFragmentManager();
+        if (mDialogFragment == null) {
+            // See if one is already attached to this activity.
+            mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
+                    MediaRouteChooserDialogFragment.FRAGMENT_TAG);
+        }
+        if (mDialogFragment != null) {
+            Log.w(TAG, "showDialog(): Already showing!");
+            return;
+        }
+
+        mDialogFragment = new MediaRouteChooserDialogFragment();
+        mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener);
+        mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() {
+            @Override
+            public void onDetached(MediaRouteChooserDialogFragment detachedFragment) {
+                mDialogFragment = null;
+            }
+        });
+        mDialogFragment.setRouteTypes(mRouteTypes);
+        mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
+    }
+
+    private Activity getActivity() {
+        // Gross way of unwrapping the Activity so we can get the FragmentManager
+        Context context = getContext();
+        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        if (!(context instanceof Activity)) {
+            throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
+        }
+
+        return (Activity) context;
+    }
+
     private class MediaRouteCallback extends MediaRouter.SimpleCallback {
         @Override
-        public void onRouteSelected(int type, RouteInfo info) {
+        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
             updateRemoteIndicator();
         }
 
         @Override
-        public void onRouteUnselected(int type, RouteInfo info) {
+        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
             updateRemoteIndicator();
         }
 
         @Override
-        public void onRouteAdded(int type, RouteInfo info) {
+        public void onRouteAdded(MediaRouter router, RouteInfo info) {
             updateRouteCount();
         }
 
         @Override
-        public void onRouteRemoved(int type, RouteInfo info) {
+        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
             updateRouteCount();
         }
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index caade70..bb497c0 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -911,7 +911,7 @@
      * </pre>
      */
     public static class Builder {
-        private static final int MAX_ACTION_BUTTONS = 2;
+        private static final int MAX_ACTION_BUTTONS = 3;
 
         private Context mContext;
 
@@ -1670,6 +1670,9 @@
                 contentView.setTextViewText(R.id.text, overflowText);
                 contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
                 contentView.setViewVisibility(R.id.line3, View.VISIBLE);
+            } else {
+                contentView.setViewVisibility(R.id.overflow_divider, View.GONE);
+                contentView.setViewVisibility(R.id.line3, View.GONE);
             }
 
             return contentView;
@@ -1812,6 +1815,7 @@
             // Remove the content text so line3 only shows if you have a summary
             final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null);
             mBuilder.mContentText = null;
+
             RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
             
             if (hadThreeLines) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 691ee30..e8bd546 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.graphics.Rect;
@@ -32,6 +33,7 @@
 import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.view.KeyEvent;
 
 import java.util.List;
@@ -837,4 +839,32 @@
         }
     }
 
+    /**
+     * Returns true if the global assist activity is available.
+     * @return True if the assistant is available.
+     *
+     * @hide
+     */
+    public final boolean isAssistantAvailable() {
+        Intent intent = getAssistIntent();
+        return intent != null
+                && mContext.getPackageManager().queryIntentActivities(intent,
+                        PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
+    }
+
+    /**
+     * Gets an intent to launch the global assist activity, or null if not available.
+     * @return The assist intent.
+     *
+     * @hide
+     */
+    public final Intent getAssistIntent() {
+        ComponentName globalSearchActivity = getGlobalSearchActivity();
+        if (globalSearchActivity != null) {
+            Intent intent = new Intent(Intent.ACTION_ASSIST);
+            intent.setPackage(globalSearchActivity.getPackageName());
+            return intent;
+        }
+        return null;
+    }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4c169d38..7588cda 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1528,6 +1528,8 @@
      * @see android.net.wifi.WifiManager
      * @see #AUDIO_SERVICE
      * @see android.media.AudioManager
+     * @see #MEDIA_ROUTER_SERVICE
+     * @see android.media.MediaRouter
      * @see #TELEPHONY_SERVICE
      * @see android.telephony.TelephonyManager
      * @see #INPUT_METHOD_SERVICE
@@ -1778,7 +1780,6 @@
      */
     public static final String NSD_SERVICE = "servicediscovery";
 
-
     /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.media.AudioManager} for handling management of volume,
@@ -1791,6 +1792,16 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.media.MediaRouter} for controlling and managing
+     * routing of media.
+     *
+     * @see #getSystemService
+     * @see android.media.MediaRouter
+     */
+    public static final String MEDIA_ROUTER_SERVICE = "media_router";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.telephony.TelephonyManager} for handling management the
      * telephony features of the device.
      *
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 70c0c48..90b4247 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -376,4 +376,7 @@
 
     void setPermissionEnforced(String permission, boolean enforced);
     boolean isPermissionEnforced(String permission);
+
+    /** Reflects current DeviceStorageMonitorService state */
+    boolean isStorageLow();
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b9811c82..f8898c1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -127,9 +127,13 @@
      */
     public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
         new PackageParser.SplitPermissionInfo[] {
+            // READ_EXTERNAL_STORAGE is always required when an app requests
+            // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
+            // write access without read access.  The hack here with the target
+            // target SDK version ensures that this grant is always done.
             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                     new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
-                    android.os.Build.VERSION_CODES.JELLY_BEAN),
+                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
             new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
                     new String[] { android.Manifest.permission.READ_CALL_LOG },
                     android.os.Build.VERSION_CODES.JELLY_BEAN),
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index c453a5d..d2bed48 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -456,6 +456,7 @@
         final int top = Math.max(dtop, 0);
         final int bottom = Math.min(getLineTop(getLineCount()), dbottom);
 
+        if (top >= bottom) return TextUtils.packRangeInLong(0, -1);
         return TextUtils.packRangeInLong(getLineForVertical(top), getLineForVertical(bottom));
     }
 
@@ -1695,8 +1696,14 @@
         return text.getSpans(start, end, type);
     }
 
+    private char getEllipsisChar(TextUtils.TruncateAt method) {
+        return (method == TextUtils.TruncateAt.END_SMALL) ?
+                ELLIPSIS_TWO_DOTS[0] :
+                ELLIPSIS_NORMAL[0];
+    }
+
     private void ellipsize(int start, int end, int line,
-                           char[] dest, int destoff) {
+                           char[] dest, int destoff, TextUtils.TruncateAt method) {
         int ellipsisCount = getEllipsisCount(line);
 
         if (ellipsisCount == 0) {
@@ -1710,7 +1717,7 @@
             char c;
 
             if (i == ellipsisStart) {
-                c = '\u2026'; // ellipsis
+                c = getEllipsisChar(method); // ellipsis
             } else {
                 c = '\uFEFF'; // 0-width space
             }
@@ -1784,7 +1791,7 @@
             TextUtils.getChars(mText, start, end, dest, destoff);
 
             for (int i = line1; i <= line2; i++) {
-                mLayout.ellipsize(start, end, i, dest, destoff);
+                mLayout.ellipsize(start, end, i, dest, destoff, mMethod);
             }
         }
 
@@ -1889,4 +1896,6 @@
     /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT =
         new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG });
 
+    /* package */ static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..."
+    /* package */ static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".."
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 299e115..6973b2e 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -745,7 +745,8 @@
         }
 
         float ellipsisWidth = paint.measureText(
-                (where == TextUtils.TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL);
+                (where == TextUtils.TruncateAt.END_SMALL) ?
+                        ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL, 0, 1);
         int ellipsisStart = 0;
         int ellipsisCount = 0;
         int len = lineEnd - lineStart;
@@ -985,9 +986,6 @@
 
     private static final double EXTRA_ROUNDING = 0.5;
 
-    private static final String ELLIPSIS_NORMAL = "\u2026"; // this is "..."
-    private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // this is ".."
-
     private static final int CHAR_FIRST_HIGH_SURROGATE = 0xD800;
     private static final int CHAR_LAST_LOW_SURROGATE = 0xDFFF;
 
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
index deed737..8e6147c 100644
--- a/core/java/android/text/style/StyleSpan.java
+++ b/core/java/android/text/style/StyleSpan.java
@@ -98,7 +98,6 @@
         }
 
         int fake = want & ~tf.getStyle();
-        fake |= tf.getStyle() & Typeface.BOLD;
 
         if ((fake & Typeface.BOLD) != 0) {
             paint.setFakeBoldText(true);
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index abd02cf..ecbf4bc 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -235,7 +235,6 @@
             }
 
             int fake = style & ~tf.getStyle();
-            fake |= tf.getStyle() & Typeface.BOLD;
 
             if ((fake & Typeface.BOLD) != 0) {
                 ds.setFakeBoldText(true);
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
index 3d74ed0..f194060 100644
--- a/core/java/android/text/style/TypefaceSpan.java
+++ b/core/java/android/text/style/TypefaceSpan.java
@@ -82,7 +82,6 @@
 
         Typeface tf = Typeface.create(family, oldStyle);
         int fake = oldStyle & ~tf.getStyle();
-        fake |= tf.getStyle() & Typeface.BOLD;
 
         if ((fake & Typeface.BOLD) != 0) {
             paint.setFakeBoldText(true);
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index 2a7dc18..17ce4f6 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -70,20 +70,19 @@
             implements ComponentCallbacks {
         private static CharacterTextSegmentIterator sInstance;
 
-        private final Context mAppContext;
+        private Locale mLocale;
 
         protected BreakIterator mImpl;
 
-        public static CharacterTextSegmentIterator getInstance(Context context) {
+        public static CharacterTextSegmentIterator getInstance(Locale locale) {
             if (sInstance == null) {
-                sInstance = new CharacterTextSegmentIterator(context);
+                sInstance = new CharacterTextSegmentIterator(locale);
             }
             return sInstance;
         }
 
-        private CharacterTextSegmentIterator(Context context) {
-            mAppContext = context.getApplicationContext();
-            Locale locale = mAppContext.getResources().getConfiguration().locale;
+        private CharacterTextSegmentIterator(Locale locale) {
+            mLocale = locale;
             onLocaleChanged(locale);
             ViewRootImpl.addConfigCallback(this);
         }
@@ -148,10 +147,9 @@
 
         @Override
         public void onConfigurationChanged(Configuration newConfig) {
-            Configuration oldConfig = mAppContext.getResources().getConfiguration();
-            final int changed = oldConfig.diff(newConfig);
-            if ((changed & ActivityInfo.CONFIG_LOCALE) != 0) {
-                Locale locale = newConfig.locale;
+            Locale locale = newConfig.locale;
+            if (!mLocale.equals(locale)) {
+                mLocale = locale;
                 onLocaleChanged(locale);
             }
         }
@@ -169,15 +167,15 @@
     static class WordTextSegmentIterator extends CharacterTextSegmentIterator {
         private static WordTextSegmentIterator sInstance;
 
-        public static WordTextSegmentIterator getInstance(Context context) {
+        public static WordTextSegmentIterator getInstance(Locale locale) {
             if (sInstance == null) {
-                sInstance = new WordTextSegmentIterator(context);
+                sInstance = new WordTextSegmentIterator(locale);
             }
             return sInstance;
         }
 
-        private WordTextSegmentIterator(Context context) {
-           super(context);
+        private WordTextSegmentIterator(Locale locale) {
+           super(locale);
         }
 
         @Override
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index aaa081c..4d1b836 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -79,6 +79,16 @@
     // be dequeued.
     private static final long DEFAULT_FRAME_DELAY = 10;
 
+    // The fake vsync delay in milliseconds.
+    // When the screen is off, we might not receive real vsync pulses from the hardware
+    // which would cause posted Choreographer callbacks to not run.  This is bad because
+    // messages in the Looper might be blocked behind a barrier that is scheduled to be
+    // removed by one of those Choreographer callback (see ViewRootImpl.doTraversals).
+    // Until the barrier is removed, those messages will not run.  To prevent starvation
+    // of the Looper, we synthesize fake vsync pulses at a reduced rate whenever the
+    // display hardware stops generating them.
+    private static final long FAKE_VSYNC_DELAY = 100;
+
     // The number of milliseconds between animation frames.
     private static volatile long sFrameDelay = DEFAULT_FRAME_DELAY;
 
@@ -103,11 +113,17 @@
     private static final boolean USE_FRAME_TIME = SystemProperties.getBoolean(
             "debug.choreographer.frametime", true);
 
+    // Set a limit to warn about skipped frames.
+    // Skipped frames imply jank.
+    private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
+            "debug.choreographer.skipwarning", 30);
+
     private static final long NANOS_PER_MS = 1000000;
 
     private static final int MSG_DO_FRAME = 0;
     private static final int MSG_DO_SCHEDULE_VSYNC = 1;
     private static final int MSG_DO_SCHEDULE_CALLBACK = 2;
+    private static final int MSG_FAKE_VSYNC = 3;
 
     // All frame callbacks posted by applications have this token.
     private static final Object FRAME_CALLBACK_TOKEN = new Object() {
@@ -486,13 +502,18 @@
             startNanos = System.nanoTime();
             final long jitterNanos = startNanos - frameTimeNanos;
             if (jitterNanos >= mFrameIntervalNanos) {
+                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
+                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
+                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
+                            + "The application may be doing too much work on its main thread.");
+                }
                 final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                 if (DEBUG) {
                     Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                             + "which is more than the frame interval of "
                             + (mFrameIntervalNanos * 0.000001f) + " ms!  "
-                            + "Setting frame time to " + (lastFrameOffset * 0.000001f)
-                            + " ms in the past.");
+                            + "Skipping " + skippedFrames + " frames and setting frame "
+                            + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
                 }
                 frameTimeNanos = startNanos - lastFrameOffset;
             }
@@ -500,7 +521,7 @@
             if (frameTimeNanos < mLastFrameTimeNanos) {
                 if (DEBUG) {
                     Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
-                            + "previously skipped frame.  Waiting for next vsync");
+                            + "previously skipped frame.  Waiting for next vsync.");
                 }
                 scheduleVsyncLocked();
                 return;
@@ -577,6 +598,13 @@
 
     private void scheduleVsyncLocked() {
         mDisplayEventReceiver.scheduleVsync();
+
+        // Post a message to simulate a fake vsync pulse at a reduced rate in case the
+        // display hardware stops generating them.  This ensures that Choreographer
+        // callbacks can continue to run even if the screen is off.
+        Message msg = mHandler.obtainMessage(MSG_FAKE_VSYNC);
+        msg.setAsynchronous(true);
+        mHandler.sendMessageDelayed(msg, FAKE_VSYNC_DELAY);
     }
 
     private boolean isRunningOnLooperThreadLocked() {
@@ -652,12 +680,19 @@
                 case MSG_DO_SCHEDULE_CALLBACK:
                     doScheduleCallback(msg.arg1);
                     break;
+                case MSG_FAKE_VSYNC:
+                    if (DEBUG) {
+                        Log.d(TAG, "Handling fake vsync while screen is off.");
+                    }
+                    doFrame(System.nanoTime(), 0);
+                    break;
             }
         }
     }
 
     private final class FrameDisplayEventReceiver extends DisplayEventReceiver
             implements Runnable {
+        private boolean mHavePendingVsync;
         private long mTimestampNanos;
         private int mFrame;
 
@@ -672,6 +707,27 @@
             // the message queue.  If there are no messages in the queue with timestamps
             // earlier than the frame time, then the vsync event will be processed immediately.
             // Otherwise, messages that predate the vsync event will be handled first.
+            if (mHavePendingVsync) {
+                if (DEBUG) {
+                    Log.d(TAG, "Already have a pending vsync event.  There should only be "
+                            + "one at a time but they can double up when a fake vsync "
+                            + "is handled in place of a real one.");
+                }
+                mHandler.removeCallbacks(this);
+            } else {
+                mHavePendingVsync = true;
+            }
+
+            long now = System.nanoTime();
+            if (timestampNanos > now) {
+                Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+                        + " ms in the future!  Check that graphics HAL is generating vsync "
+                        + "timestamps using the correct timebase.");
+                timestampNanos = now;
+            }
+
+            mHandler.removeMessages(MSG_FAKE_VSYNC);
+
             mTimestampNanos = timestampNanos;
             mFrame = frame;
             Message msg = Message.obtain(mHandler, this);
@@ -681,6 +737,7 @@
 
         @Override
         public void run() {
+            mHavePendingVsync = false;
             doFrame(mTimestampNanos, mFrame);
         }
     }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 0ae6b56..cb5a5e7 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1211,15 +1211,16 @@
             }
 
             if ((status & DisplayList.STATUS_INVOKE) != 0) {
-                scheduleFunctors(attachInfo);
+                scheduleFunctors(attachInfo, true);
             }
         }
 
-        private void scheduleFunctors(View.AttachInfo attachInfo) {
+        private void scheduleFunctors(View.AttachInfo attachInfo, boolean delayed) {
             mFunctorsRunnable.attachInfo = attachInfo;
             if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
                 // delay the functor callback by a few ms so it isn't polled constantly
-                attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
+                attachInfo.mHandler.postDelayed(mFunctorsRunnable,
+                                                delayed ? FUNCTOR_PROCESS_DELAY : 0);
             }
         }
 
@@ -1234,7 +1235,7 @@
         boolean attachFunctor(View.AttachInfo attachInfo, int functor) {
             if (mCanvas != null) {
                 mCanvas.attachFunctor(functor);
-                scheduleFunctors(attachInfo);
+                scheduleFunctors(attachInfo, false);
                 return true;
             }
             return false;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 1080229..c2a3e58 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -620,8 +620,11 @@
     public static final int KEYCODE_RO              = 217;
     /** Key code constant: Japanese kana key. */
     public static final int KEYCODE_KANA            = 218;
+    /** Key code constant: Assist key.
+     * Launches the global assist activity.  Not delivered to applications. */
+    public static final int KEYCODE_ASSIST          = 219;
 
-    private static final int LAST_KEYCODE           = KEYCODE_KANA;
+    private static final int LAST_KEYCODE           = KEYCODE_ASSIST;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -862,6 +865,7 @@
         names.append(KEYCODE_YEN, "KEYCODE_YEN");
         names.append(KEYCODE_RO, "KEYCODE_RO");
         names.append(KEYCODE_KANA, "KEYCODE_KANA");
+        names.append(KEYCODE_ASSIST, "KEYCODE_ASSIST");
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 5d2c1a7..73f94bc 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -152,10 +152,6 @@
     private float mPrevPressure;
     private long mTimeDelta;
 
-    private final float mEdgeSlop;
-    private float mRightSlopEdge;
-    private float mBottomSlopEdge;
-    private boolean mSloppyGesture;
     private boolean mInvalidGesture;
 
     // Pointer IDs currently responsible for the two fingers controlling the gesture
@@ -171,10 +167,8 @@
                     new InputEventConsistencyVerifier(this, 0) : null;
 
     public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
-        ViewConfiguration config = ViewConfiguration.get(context);
         mContext = context;
         mListener = listener;
-        mEdgeSlop = config.getScaledEdgeSlop();
     }
 
     public boolean onTouchEvent(MotionEvent event) {
@@ -193,171 +187,37 @@
             handled = false;
         } else if (!mGestureInProgress) {
             switch (action) {
-            case MotionEvent.ACTION_DOWN: {
-                mActiveId0 = event.getPointerId(0);
-                mActive0MostRecent = true;
-            }
-            break;
-
-            case MotionEvent.ACTION_UP:
-                reset();
+                case MotionEvent.ACTION_DOWN: {
+                    mActiveId0 = event.getPointerId(0);
+                    mActive0MostRecent = true;
+                }
                 break;
 
-            case MotionEvent.ACTION_POINTER_DOWN: {
-                // We have a new multi-finger gesture
+                case MotionEvent.ACTION_UP:
+                    reset();
+                    break;
 
-                // as orientation can change, query the metrics in touch down
-                DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
-                mRightSlopEdge = metrics.widthPixels - mEdgeSlop;
-                mBottomSlopEdge = metrics.heightPixels - mEdgeSlop;
+                case MotionEvent.ACTION_POINTER_DOWN: {
+                    // We have a new multi-finger gesture
+                    if (mPrevEvent != null) mPrevEvent.recycle();
+                    mPrevEvent = MotionEvent.obtain(event);
+                    mTimeDelta = 0;
 
-                if (mPrevEvent != null) mPrevEvent.recycle();
-                mPrevEvent = MotionEvent.obtain(event);
-                mTimeDelta = 0;
-
-                int index1 = event.getActionIndex();
-                int index0 = event.findPointerIndex(mActiveId0);
-                mActiveId1 = event.getPointerId(index1);
-                if (index0 < 0 || index0 == index1) {
-                    // Probably someone sending us a broken event stream.
-                    index0 = findNewActiveIndex(event, index0 == index1 ? -1 : mActiveId1, index0);
-                    mActiveId0 = event.getPointerId(index0);
-                }
-                mActive0MostRecent = false;
-
-                setContext(event);
-
-                // Check if we have a sloppy gesture. If so, delay
-                // the beginning of the gesture until we're sure that's
-                // what the user wanted. Sloppy gestures can happen if the
-                // edge of the user's hand is touching the screen, for example.
-                final float edgeSlop = mEdgeSlop;
-                final float rightSlop = mRightSlopEdge;
-                final float bottomSlop = mBottomSlopEdge;
-                float x0 = getRawX(event, index0);
-                float y0 = getRawY(event, index0);
-                float x1 = getRawX(event, index1);
-                float y1 = getRawY(event, index1);
-
-                boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop
-                        || x0 > rightSlop || y0 > bottomSlop;
-                boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop
-                        || x1 > rightSlop || y1 > bottomSlop;
-
-                if (p0sloppy && p1sloppy) {
-                    mFocusX = -1;
-                    mFocusY = -1;
-                    mSloppyGesture = true;
-                } else if (p0sloppy) {
-                    mFocusX = event.getX(index1);
-                    mFocusY = event.getY(index1);
-                    mSloppyGesture = true;
-                } else if (p1sloppy) {
-                    mFocusX = event.getX(index0);
-                    mFocusY = event.getY(index0);
-                    mSloppyGesture = true;
-                } else {
-                    mSloppyGesture = false;
-                    mGestureInProgress = mListener.onScaleBegin(this);
-                }
-            }
-            break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (mSloppyGesture) {
-                    // Initiate sloppy gestures if we've moved outside of the slop area.
-                    final float edgeSlop = mEdgeSlop;
-                    final float rightSlop = mRightSlopEdge;
-                    final float bottomSlop = mBottomSlopEdge;
+                    int index1 = event.getActionIndex();
                     int index0 = event.findPointerIndex(mActiveId0);
-                    int index1 = event.findPointerIndex(mActiveId1);
-
-                    float x0 = getRawX(event, index0);
-                    float y0 = getRawY(event, index0);
-                    float x1 = getRawX(event, index1);
-                    float y1 = getRawY(event, index1);
-
-                    boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop
-                            || x0 > rightSlop || y0 > bottomSlop;
-                    boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop
-                            || x1 > rightSlop || y1 > bottomSlop;
-
-                    if (p0sloppy) {
-                        // Do we have a different pointer that isn't sloppy?
-                        int index = findNewActiveIndex(event, mActiveId1, index0);
-                        if (index >= 0) {
-                            index0 = index;
-                            mActiveId0 = event.getPointerId(index);
-                            x0 = getRawX(event, index);
-                            y0 = getRawY(event, index);
-                            p0sloppy = false;
-                        }
+                    mActiveId1 = event.getPointerId(index1);
+                    if (index0 < 0 || index0 == index1) {
+                        // Probably someone sending us a broken event stream.
+                        index0 = findNewActiveIndex(event, mActiveId1, -1);
+                        mActiveId0 = event.getPointerId(index0);
                     }
+                    mActive0MostRecent = false;
 
-                    if (p1sloppy) {
-                        // Do we have a different pointer that isn't sloppy?
-                        int index = findNewActiveIndex(event, mActiveId0, index1);
-                        if (index >= 0) {
-                            index1 = index;
-                            mActiveId1 = event.getPointerId(index);
-                            x1 = getRawX(event, index);
-                            y1 = getRawY(event, index);
-                            p1sloppy = false;
-                        }
-                    }
+                    setContext(event);
 
-                    if(p0sloppy && p1sloppy) {
-                        mFocusX = -1;
-                        mFocusY = -1;
-                    } else if (p0sloppy) {
-                        mFocusX = event.getX(index1);
-                        mFocusY = event.getY(index1);
-                    } else if (p1sloppy) {
-                        mFocusX = event.getX(index0);
-                        mFocusY = event.getY(index0);
-                    } else {
-                        mSloppyGesture = false;
-                        mGestureInProgress = mListener.onScaleBegin(this);
-                    }
+                    mGestureInProgress = mListener.onScaleBegin(this);
+                    break;
                 }
-                break;
-
-            case MotionEvent.ACTION_POINTER_UP:
-                if (mSloppyGesture) {
-                    final int pointerCount = event.getPointerCount();
-                    final int actionIndex = event.getActionIndex();
-                    final int actionId = event.getPointerId(actionIndex);
-
-                    if (pointerCount > 2) {
-                        if (actionId == mActiveId0) {
-                            final int newIndex = findNewActiveIndex(event, mActiveId1, actionIndex);
-                            if (newIndex >= 0) mActiveId0 = event.getPointerId(newIndex);
-                        } else if (actionId == mActiveId1) {
-                            final int newIndex = findNewActiveIndex(event, mActiveId0, actionIndex);
-                            if (newIndex >= 0) mActiveId1 = event.getPointerId(newIndex);
-                        }
-                    } else {
-                        // Set focus point to the remaining finger
-                        final int index = event.findPointerIndex(actionId == mActiveId0 ?
-                                mActiveId1 : mActiveId0);
-                        if (index < 0) {
-                            mInvalidGesture = true;
-                            Log.e(TAG, "Invalid MotionEvent stream detected.", new Throwable());
-                            if (mGestureInProgress) {
-                                mListener.onScaleEnd(this);
-                            }
-                            return false;
-                        }
-
-                        mActiveId0 = event.getPointerId(index);
-
-                        mActive0MostRecent = true;
-                        mActiveId1 = -1;
-                        mFocusX = event.getX(index);
-                        mFocusY = event.getY(index);
-                    }
-                }
-                break;
             }
         } else {
             // Transform gesture in progress - attempt to handle it
@@ -381,8 +241,7 @@
                                 " with bad state while a gesture was in progress. " +
                                 "Did you forget to pass an event to " +
                                 "ScaleGestureDetector#onTouchEvent?");
-                        index0 = findNewActiveIndex(event,
-                                mActiveId0 == mActiveId1 ? -1 : mActiveId1, index0);
+                        index0 = findNewActiveIndex(event, mActiveId1, -1);
                         mActiveId0 = event.getPointerId(index0);
                     }
 
@@ -483,49 +342,19 @@
         return handled;
     }
 
-    private int findNewActiveIndex(MotionEvent ev, int otherActiveId, int oldIndex) {
+    private int findNewActiveIndex(MotionEvent ev, int otherActiveId, int removedPointerIndex) {
         final int pointerCount = ev.getPointerCount();
 
         // It's ok if this isn't found and returns -1, it simply won't match.
         final int otherActiveIndex = ev.findPointerIndex(otherActiveId);
-        int newActiveIndex = -1;
 
-        // Pick a new id and update tracking state. Only pick pointers not on the slop edges.
+        // Pick a new id and update tracking state.
         for (int i = 0; i < pointerCount; i++) {
-            if (i != oldIndex && i != otherActiveIndex) {
-                final float edgeSlop = mEdgeSlop;
-                final float rightSlop = mRightSlopEdge;
-                final float bottomSlop = mBottomSlopEdge;
-                float x = getRawX(ev, i);
-                float y = getRawY(ev, i);
-                if (x >= edgeSlop && y >= edgeSlop && x <= rightSlop && y <= bottomSlop) {
-                    newActiveIndex = i;
-                    break;
-                }
+            if (i != removedPointerIndex && i != otherActiveIndex) {
+                return i;
             }
         }
-
-        return newActiveIndex;
-    }
-
-    /**
-     * MotionEvent has no getRawX(int) method; simulate it pending future API approval.
-     */
-    private static float getRawX(MotionEvent event, int pointerIndex) {
-        if (pointerIndex < 0) return Float.MIN_VALUE;
-        if (pointerIndex == 0) return event.getRawX();
-        float offset = event.getRawX() - event.getX();
-        return event.getX(pointerIndex) + offset;
-    }
-
-    /**
-     * MotionEvent has no getRawY(int) method; simulate it pending future API approval.
-     */
-    private static float getRawY(MotionEvent event, int pointerIndex) {
-        if (pointerIndex < 0) return Float.MIN_VALUE;
-        if (pointerIndex == 0) return event.getRawY();
-        float offset = event.getRawY() - event.getY();
-        return event.getY(pointerIndex) + offset;
+        return -1;
     }
 
     private void setContext(MotionEvent curr) {
@@ -588,7 +417,6 @@
             mCurrEvent.recycle();
             mCurrEvent = null;
         }
-        mSloppyGesture = false;
         mGestureInProgress = false;
         mActiveId0 = -1;
         mActiveId1 = -1;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f005eeb..816b631 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6957,7 +6957,8 @@
                 CharSequence text = getIterableTextForAccessibility();
                 if (text != null && text.length() > 0) {
                     CharacterTextSegmentIterator iterator =
-                        CharacterTextSegmentIterator.getInstance(mContext);
+                        CharacterTextSegmentIterator.getInstance(
+                                mContext.getResources().getConfiguration().locale);
                     iterator.initialize(text.toString());
                     return iterator;
                 }
@@ -6966,7 +6967,8 @@
                 CharSequence text = getIterableTextForAccessibility();
                 if (text != null && text.length() > 0) {
                     WordTextSegmentIterator iterator =
-                        WordTextSegmentIterator.getInstance(mContext);
+                        WordTextSegmentIterator.getInstance(
+                                mContext.getResources().getConfiguration().locale);
                     iterator.initialize(text.toString());
                     return iterator;
                 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b5fff8a..51fd346 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -229,6 +229,7 @@
     boolean mWindowsAnimating;
     boolean mIsDrawing;
     int mLastSystemUiVisibility;
+    int mClientWindowLayoutFlags;
 
     // Pool of queued input events.
     private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
@@ -485,6 +486,8 @@
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
+                // Keep track of the actual window flags supplied by the client.
+                mClientWindowLayoutFlags = attrs.flags;
 
                 setAccessibilityFocusedHost(null);
 
@@ -671,6 +674,7 @@
     }
 
     public boolean attachFunctor(int functor) {
+        //noinspection SimplifiableIfStatement
         if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
             return mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor);
         }
@@ -678,7 +682,7 @@
     }
 
     public void detachFunctor(int functor) {
-        if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+        if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.detachFunctor(functor);
         }
     }
@@ -759,6 +763,8 @@
     void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
         synchronized (this) {
             int oldSoftInputMode = mWindowAttributes.softInputMode;
+            // Keep track of the actual window flags supplied by the client.
+            mClientWindowLayoutFlags = attrs.flags;
             // preserve compatible window flag if exists.
             int compatibleWindowFlag =
                 mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
@@ -767,7 +773,9 @@
             attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
             mWindowAttributesChangesFlag = mWindowAttributes.copyFrom(attrs);
             mWindowAttributes.flags |= compatibleWindowFlag;
-            
+
+            applyKeepScreenOnFlag(mWindowAttributes);
+
             if (newView) {
                 mSoftInputMode = attrs.softInputMode;
                 requestLayout();
@@ -999,6 +1007,18 @@
         }
     }
 
+    private void applyKeepScreenOnFlag(WindowManager.LayoutParams params) {
+        // Update window's global keep screen on flag: if a view has requested
+        // that the screen be kept on, then it is always set; otherwise, it is
+        // set to whatever the client last requested for the global state.
+        if (mAttachInfo.mKeepScreenOn) {
+            params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+        } else {
+            params.flags = (params.flags&~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+                    | (mClientWindowLayoutFlags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        }
+    }
+
     private boolean collectViewAttributes() {
         final View.AttachInfo attachInfo = mAttachInfo;
         if (attachInfo.mRecomputeGlobalAttributes) {
@@ -1016,9 +1036,7 @@
                     || attachInfo.mSystemUiVisibility != oldVis
                     || attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) {
                 WindowManager.LayoutParams params = mWindowAttributes;
-                if (attachInfo.mKeepScreenOn) {
-                    params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-                }
+                applyKeepScreenOnFlag(params);
                 params.subtreeSystemUiVisibility = attachInfo.mSystemUiVisibility;
                 params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners;
                 mView.dispatchWindowSystemUiVisiblityChanged(attachInfo.mSystemUiVisibility);
@@ -3908,10 +3926,9 @@
     }
     
     public void dumpGfxInfo(int[] info) {
+        info[0] = info[1] = 0;
         if (mView != null) {
             getGfxInfo(mView, info);
-        } else {
-            info[0] = info[1] = 0;
         }
     }
 
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 5d33cec..dd6b537 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -530,13 +530,16 @@
 
                     for (int i = 0; i < count; i++) {
                         ViewRootImpl root = mRoots[i];
+                        String name = getWindowName(root);
+                        pw.printf("\n\t%s", name);
+
                         HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
                         if (renderer != null) {
                             renderer.dumpGfxInfo(pw);
                         }
                     }
 
-                    pw.println("\nView hierarchy:");
+                    pw.println("\nView hierarchy:\n");
 
                     int viewsCount = 0;
                     int displayListsSize = 0;
@@ -546,15 +549,14 @@
                         ViewRootImpl root = mRoots[i];
                         root.dumpGfxInfo(info);
 
-                        String name = root.getClass().getName() + '@' +
-                                Integer.toHexString(hashCode());                        
-                        pw.printf("  %s: %d views, %.2f kB (display lists)",
+                        String name = getWindowName(root);
+                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
                                 name, info[0], info[1] / 1024.0f);
                         HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
                         if (renderer != null) {
                             pw.printf(", %d frames rendered", renderer.getFrameCount());
                         }
-                        pw.printf("\n");
+                        pw.printf("\n\n");
 
                         viewsCount += info[0];
                         displayListsSize += info[1];
@@ -570,6 +572,11 @@
         }        
     }
 
+    private static String getWindowName(ViewRootImpl root) {
+        return root.mWindowAttributes.getTitle() + "/" +
+                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+    }
+
     public void setStoppedState(IBinder token, boolean stopped) {
         synchronized (this) {
             if (mViews == null)
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index cc490bd..7dfb5bb 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -43,11 +43,6 @@
  * APIs.
  */
 class AccessibilityInjector {
-    // Default result returned from AndroidVox. Using true here means if the
-    // script fails, an accessibility service will always think that traversal
-    // has succeeded.
-    private static final String DEFAULT_ANDROIDVOX_RESULT = "true";
-
     // The WebViewClassic this injector is responsible for managing.
     private final WebViewClassic mWebViewClassic;
 
@@ -488,15 +483,19 @@
             switch (action) {
                 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
                 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
-                    final int granularity = arguments.getInt(
-                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
-                    mAccessibilityJSONObject.accumulate("granularity", granularity);
+                    if (arguments != null) {
+                        final int granularity = arguments.getInt(
+                                AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
+                        mAccessibilityJSONObject.accumulate("granularity", granularity);
+                    }
                     break;
                 case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT:
                 case AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT:
-                    final String element = arguments.getString(
-                            AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING);
-                    mAccessibilityJSONObject.accumulate("element", element);
+                    if (arguments != null) {
+                        final String element = arguments.getString(
+                                AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING);
+                        mAccessibilityJSONObject.accumulate("element", element);
+                    }
                     break;
             }
         } catch (JSONException e) {
@@ -505,9 +504,7 @@
 
         final String jsonString = mAccessibilityJSONObject.toString();
         final String jsCode = String.format(ACCESSIBILITY_ANDROIDVOX_TEMPLATE, jsonString);
-        final String result = mCallback.performAction(mWebView, jsCode, DEFAULT_ANDROIDVOX_RESULT);
-
-        return ("true".equalsIgnoreCase(result));
+        return mCallback.performAction(mWebView, jsCode);
     }
 
     /**
@@ -518,13 +515,13 @@
                 "javascript:(function() { %s.onResult(%d, %s); })();";
 
         // Time in milliseconds to wait for a result before failing.
-        private static final long RESULT_TIMEOUT = 200;
+        private static final long RESULT_TIMEOUT = 5000;
 
         private final AtomicInteger mResultIdCounter = new AtomicInteger();
         private final Object mResultLock = new Object();
         private final String mInterfaceName;
 
-        private String mResult = null;
+        private boolean mResult = false;
         private long mResultId = -1;
 
         private CallbackHandler(String interfaceName) {
@@ -536,29 +533,27 @@
          *
          * @param webView The WebView to perform the action on.
          * @param code JavaScript code that evaluates to a result.
-         * @param defaultResult The result to return if the action times out.
          * @return The result of the action, or false if it timed out.
          */
-        private String performAction(WebView webView, String code, String defaultResult) {
+        private boolean performAction(WebView webView, String code) {
             final int resultId = mResultIdCounter.getAndIncrement();
             final String url = String.format(
                     JAVASCRIPT_ACTION_TEMPLATE, mInterfaceName, resultId, code);
             webView.loadUrl(url);
 
-            return getResultAndClear(resultId, defaultResult);
+            return getResultAndClear(resultId);
         }
 
         /**
          * Gets the result of a request to perform an accessibility action.
          *
          * @param resultId The result id to match the result with the request.
-         * @param defaultResult The default result to return on timeout.
          * @return The result of the request.
          */
-        private String getResultAndClear(int resultId, String defaultResult) {
+        private boolean getResultAndClear(int resultId) {
             synchronized (mResultLock) {
                 final boolean success = waitForResultTimedLocked(resultId);
-                final String result = success ? mResult : defaultResult;
+                final boolean result = success ? mResult : false;
                 clearResultLocked();
                 return result;
             }
@@ -569,7 +564,7 @@
          */
         private void clearResultLocked() {
             mResultId = -1;
-            mResult = null;
+            mResult = false;
         }
 
         /**
@@ -620,7 +615,7 @@
 
             synchronized (mResultLock) {
                 if (resultId > mResultId) {
-                    mResult = result;
+                    mResult = Boolean.parseBoolean(result);
                     mResultId = resultId;
                 }
                 mResultLock.notifyAll();
diff --git a/core/java/android/webkit/AccessibilityInjectorFallback.java b/core/java/android/webkit/AccessibilityInjectorFallback.java
index 4d9c26c..783b3db 100644
--- a/core/java/android/webkit/AccessibilityInjectorFallback.java
+++ b/core/java/android/webkit/AccessibilityInjectorFallback.java
@@ -272,11 +272,19 @@
     boolean performAccessibilityAction(int action, Bundle arguments) {
         switch (action) {
             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
-            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
+            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
                 final int direction = getDirectionForAction(action);
                 final int axis = getAxisForGranularity(arguments.getInt(
                         AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT));
                 return traverseGivenAxis(direction, axis, true, null);
+            }
+            case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT:
+            case AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT: {
+                final int direction = getDirectionForAction(action);
+                // TODO: Add support for moving by object.
+                final int axis = NAVIGATION_AXIS_SENTENCE;
+                return traverseGivenAxis(direction, axis, true, null);
+            }
             default:
                 return false;
         }
@@ -291,8 +299,10 @@
      */
     private static int getDirectionForAction(int action) {
         switch (action) {
+            case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT:
             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
                 return NAVIGATION_DIRECTION_FORWARD;
+            case AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT:
             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
                 return NAVIGATION_DIRECTION_BACKWARD;
             default:
@@ -316,8 +326,8 @@
             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE:
                 return NAVIGATION_AXIS_SENTENCE;
             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH:
-                // TODO: Figure out what nextSibling() actually means.
-                return NAVIGATION_AXIS_SIBLING;
+                // TODO: This should map to object once we implement it.
+                return NAVIGATION_AXIS_SENTENCE;
             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE:
                 return NAVIGATION_AXIS_DOCUMENT;
             default:
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 354bb5a..1288613 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -22,7 +22,8 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
-import android.util.DisplayMetrics;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.EventLog;
 
 import java.util.Locale;
@@ -122,6 +123,7 @@
     private boolean         mLoadWithOverviewMode = false;
     private boolean         mEnableSmoothTransition = false;
     private boolean         mForceUserScalable = false;
+    private boolean         mPasswordEchoEnabled = true;
 
     // AutoFill Profile data
     public static class AutoFillProfile {
@@ -295,6 +297,13 @@
             mAllowUniversalAccessFromFileURLs = true;
             mAllowFileAccessFromFileURLs = true;
         }
+        try {
+            mPasswordEchoEnabled =
+                    Settings.System.getInt(context.getContentResolver(),
+                        Settings.System.TEXT_SHOW_PASSWORD) != 0;
+        } catch (SettingNotFoundException e) {
+            mPasswordEchoEnabled = true;
+        }
     }
 
     private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 611742b..da61e74 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -1316,7 +1316,7 @@
         case WebViewInputDispatcher.EVENT_TYPE_LONG_PRESS:
             HitTestResult hitTest = getHitTestResult();
             if (hitTest != null) {
-                performLongClick();
+                mWebView.performLongClick();
             }
             break;
         case WebViewInputDispatcher.EVENT_TYPE_DOUBLE_TAP:
@@ -7265,7 +7265,7 @@
                     // the states
                     mGotCenterDown = false;
                     mTrackballDown = false;
-                    performLongClick();
+                    mWebView.performLongClick();
                     break;
 
                 case WEBCORE_NEED_TOUCH_EVENTS:
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 39bc7c2..471f259 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -259,12 +259,10 @@
             // now compute what (if any) algorithmic styling is needed
             int typefaceStyle = tf != null ? tf.getStyle() : 0;
             int need = style & ~typefaceStyle;
-            need |= typefaceStyle & Typeface.BOLD;
             mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
             mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
         } else {
-            int typefaceStyle = tf != null ? tf.getStyle() : 0;
-            mTextPaint.setFakeBoldText((typefaceStyle & Typeface.BOLD) != 0);
+            mTextPaint.setFakeBoldText(false);
             mTextPaint.setTextSkewX(0);
             setSwitchTypeface(tf);
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 464a527..01617da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1237,12 +1237,10 @@
             // now compute what (if any) algorithmic styling is needed
             int typefaceStyle = tf != null ? tf.getStyle() : 0;
             int need = style & ~typefaceStyle;
-            need |= typefaceStyle & Typeface.BOLD; // keep bold in
             mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
             mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
         } else {
-            int typefaceStyle = tf != null ? tf.getStyle() : 0;
-            mTextPaint.setFakeBoldText((typefaceStyle & Typeface.BOLD) != 0);
+            mTextPaint.setFakeBoldText(false);
             mTextPaint.setTextSkewX(0);
             setTypeface(tf);
         }
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
new file mode 100644
index 0000000..e1a48be
--- /dev/null
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import com.android.internal.R;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.MediaRouteActionProvider;
+import android.app.MediaRouteButton;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteCategory;
+import android.media.MediaRouter.RouteGroup;
+import android.media.MediaRouter.RouteInfo;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.Checkable;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * This class implements the route chooser dialog for {@link MediaRouter}.
+ *
+ * @see MediaRouteButton
+ * @see MediaRouteActionProvider
+ */
+public class MediaRouteChooserDialogFragment extends DialogFragment {
+    private static final String TAG = "MediaRouteChooserDialogFragment";
+    public static final String FRAGMENT_TAG = "android:MediaRouteChooserDialogFragment";
+
+    private static final int[] ITEM_LAYOUTS = new int[] {
+        R.layout.media_route_list_item_top_header,
+        R.layout.media_route_list_item_section_header,
+        R.layout.media_route_list_item,
+        R.layout.media_route_list_item_checkable,
+        R.layout.media_route_list_item_collapse_group
+    };
+
+    MediaRouter mRouter;
+    private int mRouteTypes;
+
+    private LayoutInflater mInflater;
+    private LauncherListener mLauncherListener;
+    private View.OnClickListener mExtendedSettingsListener;
+    private RouteAdapter mAdapter;
+    private ListView mListView;
+
+    final RouteComparator mComparator = new RouteComparator();
+
+    public MediaRouteChooserDialogFragment() {
+        setStyle(STYLE_NO_TITLE, R.style.Theme_DeviceDefault_Dialog);
+    }
+
+    public void setLauncherListener(LauncherListener listener) {
+        mLauncherListener = listener;
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        if (mLauncherListener != null) {
+            mLauncherListener.onDetached(this);
+        }
+        if (mAdapter != null) {
+            mRouter.removeCallback(mAdapter.mCallback);
+            mAdapter = null;
+        }
+        mInflater = null;
+        mRouter = null;
+    }
+
+    /**
+     * Implemented by the MediaRouteButton that launched this dialog
+     */
+    public interface LauncherListener {
+        public void onDetached(MediaRouteChooserDialogFragment detachedFragment);
+    }
+
+    public void setExtendedSettingsClickListener(View.OnClickListener listener) {
+        mExtendedSettingsListener = listener;
+    }
+
+    public void setRouteTypes(int types) {
+        mRouteTypes = types;
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mInflater = inflater;
+        final View layout = inflater.inflate(R.layout.media_route_chooser_layout, container, false);
+        final View extendedSettingsButton = layout.findViewById(R.id.extended_settings);
+
+        if (mExtendedSettingsListener != null) {
+            extendedSettingsButton.setVisibility(View.VISIBLE);
+            extendedSettingsButton.setOnClickListener(mExtendedSettingsListener);
+        }
+
+        final ListView list = (ListView) layout.findViewById(R.id.list);
+        list.setItemsCanFocus(true);
+        list.setAdapter(mAdapter = new RouteAdapter());
+        list.setOnItemClickListener(mAdapter);
+
+        mListView = list;
+        mRouter.addCallback(mRouteTypes, mAdapter.mCallback);
+
+        mAdapter.scrollToSelectedItem();
+
+        return layout;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        return new RouteChooserDialog(getActivity(), getTheme());
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    private static class ViewHolder {
+        public TextView text1;
+        public TextView text2;
+        public ImageView icon;
+        public ImageButton expandGroupButton;
+        public RouteAdapter.ExpandGroupListener expandGroupListener;
+        public int position;
+        public CheckBox check;
+    }
+
+    private class RouteAdapter extends BaseAdapter implements ListView.OnItemClickListener {
+        private static final int VIEW_TOP_HEADER = 0;
+        private static final int VIEW_SECTION_HEADER = 1;
+        private static final int VIEW_ROUTE = 2;
+        private static final int VIEW_GROUPING_ROUTE = 3;
+        private static final int VIEW_GROUPING_DONE = 4;
+
+        private int mSelectedItemPosition = -1;
+        private final ArrayList<Object> mItems = new ArrayList<Object>();
+        final MediaRouterCallback mCallback = new MediaRouterCallback();
+
+        private RouteCategory mCategoryEditingGroups;
+        private RouteGroup mEditingGroup;
+
+        // Temporary lists for manipulation
+        private final ArrayList<RouteInfo> mCatRouteList = new ArrayList<RouteInfo>();
+        private final ArrayList<RouteInfo> mSortRouteList = new ArrayList<RouteInfo>();
+
+        private boolean mIgnoreUpdates;
+
+        RouteAdapter() {
+            update();
+        }
+
+        void update() {
+            /*
+             * This is kind of wacky, but our data sets are going to be
+             * fairly small on average. Ideally we should be able to do some of this stuff
+             * in-place instead.
+             *
+             * Basic idea: each entry in mItems represents an item in the list for quick access.
+             * Entries can be a RouteCategory (section header), a RouteInfo with a category of
+             * mCategoryEditingGroups (a flattened RouteInfo pulled out of its group, allowing
+             * the user to change the group),
+             */
+            if (mIgnoreUpdates) return;
+
+            mItems.clear();
+
+            final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
+            mSelectedItemPosition = -1;
+
+            List<RouteInfo> routes;
+            final int catCount = mRouter.getCategoryCount();
+            for (int i = 0; i < catCount; i++) {
+                final RouteCategory cat = mRouter.getCategoryAt(i);
+                routes = cat.getRoutes(mCatRouteList);
+
+                mItems.add(cat);
+
+                if (cat == mCategoryEditingGroups) {
+                    addGroupEditingCategoryRoutes(routes);
+                } else {
+                    addSelectableRoutes(selectedRoute, routes);
+                }
+
+                routes.clear();
+            }
+
+            notifyDataSetChanged();
+            if (mListView != null && mSelectedItemPosition >= 0) {
+                mListView.setItemChecked(mSelectedItemPosition, true);
+            }
+        }
+
+        void scrollToEditingGroup() {
+            if (mCategoryEditingGroups == null || mListView == null) return;
+
+            int pos = 0;
+            int bound = 0;
+            final int itemCount = mItems.size();
+            for (int i = 0; i < itemCount; i++) {
+                final Object item = mItems.get(i);
+                if (item != null && item == mCategoryEditingGroups) {
+                    bound = i;
+                }
+                if (item == null) {
+                    pos = i;
+                    break; // this is always below the category header; we can stop here.
+                }
+            }
+
+            mListView.smoothScrollToPosition(pos, bound);
+        }
+
+        void scrollToSelectedItem() {
+            if (mListView == null || mSelectedItemPosition < 0) return;
+
+            mListView.smoothScrollToPosition(mSelectedItemPosition);
+        }
+
+        void addSelectableRoutes(RouteInfo selectedRoute, List<RouteInfo> from) {
+            final int routeCount = from.size();
+            for (int j = 0; j < routeCount; j++) {
+                final RouteInfo info = from.get(j);
+                if (info == selectedRoute) {
+                    mSelectedItemPosition = mItems.size();
+                }
+                mItems.add(info);
+            }
+        }
+
+        void addGroupEditingCategoryRoutes(List<RouteInfo> from) {
+            // Unpack groups and flatten for presentation
+            // mSortRouteList will always be empty here.
+            final int topCount = from.size();
+            for (int i = 0; i < topCount; i++) {
+                final RouteInfo route = from.get(i);
+                final RouteGroup group = route.getGroup();
+                if (group == route) {
+                    // This is a group, unpack it.
+                    final int groupCount = group.getRouteCount();
+                    for (int j = 0; j < groupCount; j++) {
+                        final RouteInfo innerRoute = group.getRouteAt(j);
+                        mSortRouteList.add(innerRoute);
+                    }
+                } else {
+                    mSortRouteList.add(route);
+                }
+            }
+            // Sort by name. This will keep the route positions relatively stable even though they
+            // will be repeatedly added and removed.
+            Collections.sort(mSortRouteList, mComparator);
+
+            mItems.addAll(mSortRouteList);
+            mSortRouteList.clear();
+
+            mItems.add(null); // Sentinel reserving space for the "done" button.
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 5;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            final Object item = getItem(position);
+            if (item instanceof RouteCategory) {
+                return position == 0 ? VIEW_TOP_HEADER : VIEW_SECTION_HEADER;
+            } else if (item == null) {
+                return VIEW_GROUPING_DONE;
+            } else {
+                final RouteInfo info = (RouteInfo) item;
+                if (info.getCategory() == mCategoryEditingGroups) {
+                    return VIEW_GROUPING_ROUTE;
+                }
+                return VIEW_ROUTE;
+            }
+        }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return false;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            switch (getItemViewType(position)) {
+                case VIEW_ROUTE:
+                case VIEW_GROUPING_ROUTE:
+                case VIEW_GROUPING_DONE:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final int viewType = getItemViewType(position);
+
+            ViewHolder holder;
+            if (convertView == null) {
+                convertView = mInflater.inflate(ITEM_LAYOUTS[viewType], parent, false);
+                holder = new ViewHolder();
+                holder.position = position;
+                holder.text1 = (TextView) convertView.findViewById(R.id.text1);
+                holder.text2 = (TextView) convertView.findViewById(R.id.text2);
+                holder.icon = (ImageView) convertView.findViewById(R.id.icon);
+                holder.check = (CheckBox) convertView.findViewById(R.id.check);
+                holder.expandGroupButton = (ImageButton) convertView.findViewById(
+                        R.id.expand_button);
+                if (holder.expandGroupButton != null) {
+                    holder.expandGroupListener = new ExpandGroupListener();
+                    holder.expandGroupButton.setOnClickListener(holder.expandGroupListener);
+                }
+
+                final View fview = convertView;
+                final ListView list = (ListView) parent;
+                final ViewHolder fholder = holder;
+                convertView.setOnClickListener(new View.OnClickListener() {
+                    @Override public void onClick(View v) {
+                        list.performItemClick(fview, fholder.position, 0);
+                    }
+                });
+                convertView.setTag(holder);
+            } else {
+                holder = (ViewHolder) convertView.getTag();
+                holder.position = position;
+            }
+
+            switch (viewType) {
+                case VIEW_ROUTE:
+                case VIEW_GROUPING_ROUTE:
+                    bindItemView(position, holder);
+                    break;
+                case VIEW_SECTION_HEADER:
+                case VIEW_TOP_HEADER:
+                    bindHeaderView(position, holder);
+                    break;
+            }
+
+            convertView.setActivated(position == mSelectedItemPosition);
+
+            return convertView;
+        }
+
+        void bindItemView(int position, ViewHolder holder) {
+            RouteInfo info = (RouteInfo) mItems.get(position);
+            holder.text1.setText(info.getName(getActivity()));
+            final CharSequence status = info.getStatus();
+            if (TextUtils.isEmpty(status)) {
+                holder.text2.setVisibility(View.GONE);
+            } else {
+                holder.text2.setVisibility(View.VISIBLE);
+                holder.text2.setText(status);
+            }
+            Drawable icon = info.getIconDrawable();
+            if (icon != null) {
+                // Make sure we have a fresh drawable where it doesn't matter if we mutate it
+                icon = icon.getConstantState().newDrawable(getResources());
+            }
+            holder.icon.setImageDrawable(icon);
+            holder.icon.setVisibility(icon != null ? View.VISIBLE : View.GONE);
+
+            RouteCategory cat = info.getCategory();
+            boolean canGroup = false;
+            if (cat == mCategoryEditingGroups) {
+                RouteGroup group = info.getGroup();
+                holder.check.setEnabled(group.getRouteCount() > 1);
+                holder.check.setChecked(group == mEditingGroup);
+            } else {
+                if (cat.isGroupable()) {
+                    final RouteGroup group = (RouteGroup) info;
+                    canGroup = group.getRouteCount() > 1 ||
+                            getItemViewType(position - 1) == VIEW_ROUTE ||
+                            (position < getCount() - 1 &&
+                                    getItemViewType(position + 1) == VIEW_ROUTE);
+                }
+            }
+
+            if (holder.expandGroupButton != null) {
+                holder.expandGroupButton.setVisibility(canGroup ? View.VISIBLE : View.GONE);
+                holder.expandGroupListener.position = position;
+            }
+        }
+
+        void bindHeaderView(int position, ViewHolder holder) {
+            RouteCategory cat = (RouteCategory) mItems.get(position);
+            holder.text1.setText(cat.getName(getActivity()));
+        }
+
+        public int getSelectedRoutePosition() {
+            return mSelectedItemPosition;
+        }
+
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+            final int type = getItemViewType(position);
+            if (type == VIEW_SECTION_HEADER || type == VIEW_TOP_HEADER) {
+                return;
+            } else if (type == VIEW_GROUPING_DONE) {
+                finishGrouping();
+                return;
+            } else {
+                final Object item = getItem(position);
+                if (!(item instanceof RouteInfo)) {
+                    // Oops. Stale event running around? Skip it.
+                    return;
+                }
+
+                final RouteInfo route = (RouteInfo) item;
+                if (type == VIEW_ROUTE) {
+                    mRouter.selectRouteInt(mRouteTypes, route);
+                    dismiss();
+                } else if (type == VIEW_GROUPING_ROUTE) {
+                    final Checkable c = (Checkable) view;
+                    final boolean wasChecked = c.isChecked();
+
+                    mIgnoreUpdates = true;
+                    RouteGroup oldGroup = route.getGroup();
+                    if (!wasChecked && oldGroup != mEditingGroup) {
+                        // Assumption: in a groupable category oldGroup will never be null.
+                        if (mRouter.getSelectedRoute(mRouteTypes) == oldGroup) {
+                            // Old group was selected but is now empty. Select the group
+                            // we're manipulating since that's where the last route went.
+                            mRouter.selectRouteInt(mRouteTypes, mEditingGroup);
+                        }
+                        oldGroup.removeRoute(route);
+                        mEditingGroup.addRoute(route);
+                        c.setChecked(true);
+                    } else if (wasChecked && mEditingGroup.getRouteCount() > 1) {
+                        mEditingGroup.removeRoute(route);
+
+                        // In a groupable category this will add
+                        // the route into its own new group.
+                        mRouter.addRouteInt(route);
+                    }
+                    mIgnoreUpdates = false;
+                    update();
+                }
+            }
+        }
+
+        boolean isGrouping() {
+            return mCategoryEditingGroups != null;
+        }
+
+        void finishGrouping() {
+            mCategoryEditingGroups = null;
+            mEditingGroup = null;
+            getDialog().setCanceledOnTouchOutside(true);
+            update();
+            scrollToSelectedItem();
+        }
+
+        class ExpandGroupListener implements View.OnClickListener {
+            int position;
+
+            @Override
+            public void onClick(View v) {
+                // Assumption: this is only available for the user to click if we're presenting
+                // a groupable category, where every top-level route in the category is a group.
+                final RouteGroup group = (RouteGroup) getItem(position);
+                mEditingGroup = group;
+                mCategoryEditingGroups = group.getCategory();
+                getDialog().setCanceledOnTouchOutside(false);
+                mRouter.selectRouteInt(mRouteTypes, mEditingGroup);
+                update();
+                scrollToEditingGroup();
+            }
+        }
+
+        class MediaRouterCallback extends MediaRouter.Callback {
+            @Override
+            public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
+                update();
+            }
+
+            @Override
+            public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
+                update();
+            }
+
+            @Override
+            public void onRouteAdded(MediaRouter router, RouteInfo info) {
+                update();
+            }
+
+            @Override
+            public void onRouteRemoved(MediaRouter router, RouteInfo info) {
+                if (info == mEditingGroup) {
+                    finishGrouping();
+                }
+                update();
+            }
+
+            @Override
+            public void onRouteChanged(MediaRouter router, RouteInfo info) {
+                notifyDataSetChanged();
+            }
+
+            @Override
+            public void onRouteGrouped(MediaRouter router, RouteInfo info,
+                    RouteGroup group, int index) {
+                update();
+            }
+
+            @Override
+            public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
+                update();
+            }
+        }
+    }
+
+    class RouteComparator implements Comparator<RouteInfo> {
+        @Override
+        public int compare(RouteInfo lhs, RouteInfo rhs) {
+            return lhs.getName(getActivity()).toString()
+                    .compareTo(rhs.getName(getActivity()).toString());
+        }
+    }
+
+    class RouteChooserDialog extends Dialog {
+        public RouteChooserDialog(Context context, int theme) {
+            super(context, theme);
+        }
+
+        @Override
+        public void onBackPressed() {
+            if (mAdapter != null && mAdapter.isGrouping()) {
+                mAdapter.finishGrouping();
+            } else {
+                super.onBackPressed();
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index d61a579..d6f9e07 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -34,17 +34,19 @@
 
     public static final String SERVICE_INTERFACE = "android.net.VpnService";
 
+    public static final String DIALOGS_PACKAGE = "com.android.vpndialogs";
+
     public static final String LEGACY_VPN = "[Legacy VPN]";
 
     public static Intent getIntentForConfirmation() {
         Intent intent = new Intent();
-        intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ConfirmDialog");
+        intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ConfirmDialog");
         return intent;
     }
 
     public static PendingIntent getIntentForStatusPanel(Context context, VpnConfig config) {
         Intent intent = new Intent();
-        intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ManageDialog");
+        intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
         intent.putExtra("config", config);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
diff --git a/core/java/com/android/internal/view/CheckableLinearLayout.java b/core/java/com/android/internal/view/CheckableLinearLayout.java
new file mode 100644
index 0000000..3fb7cec
--- /dev/null
+++ b/core/java/com/android/internal/view/CheckableLinearLayout.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+
+public class CheckableLinearLayout extends LinearLayout implements Checkable {
+    private CheckBox mCheckBox;
+
+    public CheckableLinearLayout(Context context) {
+        super(context);
+        // TODO Auto-generated constructor stub
+    }
+
+    public CheckableLinearLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        // TODO Auto-generated constructor stub
+    }
+
+    public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        // TODO Auto-generated constructor stub
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mCheckBox = (CheckBox) findViewById(R.id.check);
+    }
+
+    @Override
+    public void setChecked(boolean checked) {
+        mCheckBox.setChecked(checked);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mCheckBox.isChecked();
+    }
+
+    @Override
+    public void toggle() {
+        mCheckBox.toggle();
+    }
+}
diff --git a/core/java/com/android/internal/view/ImageButtonNoParentPress.java b/core/java/com/android/internal/view/ImageButtonNoParentPress.java
new file mode 100644
index 0000000..a6cfd86
--- /dev/null
+++ b/core/java/com/android/internal/view/ImageButtonNoParentPress.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+public class ImageButtonNoParentPress extends ImageButton {
+
+    public ImageButtonNoParentPress(Context context) {
+        super(context);
+    }
+
+    public ImageButtonNoParentPress(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ImageButtonNoParentPress(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void setPressed(boolean pressed) {
+        // Normally parents propagate pressed state to their children.
+        // We don't want that to happen here; only press if our parent isn't.
+        super.setPressed(((ViewGroup) getParent()).isPressed() ? false : pressed);
+    }
+}
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
new file mode 100644
index 0000000..837b7b8
--- /dev/null
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -0,0 +1,1213 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget.multiwaveview;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Vibrator;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+
+/**
+ * A re-usable widget containing a center, outer ring and wave animation.
+ */
+public class GlowPadView extends View {
+    private static final String TAG = "GlowPadView";
+    private static final boolean DEBUG = false;
+
+    // Wave state machine
+    private static final int STATE_IDLE = 0;
+    private static final int STATE_START = 1;
+    private static final int STATE_FIRST_TOUCH = 2;
+    private static final int STATE_TRACKING = 3;
+    private static final int STATE_SNAP = 4;
+    private static final int STATE_FINISH = 5;
+
+    // Animation properties.
+    private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
+
+    public interface OnTriggerListener {
+        int NO_HANDLE = 0;
+        int CENTER_HANDLE = 1;
+        public void onGrabbed(View v, int handle);
+        public void onReleased(View v, int handle);
+        public void onTrigger(View v, int target);
+        public void onGrabbedStateChange(View v, int handle);
+        public void onFinishFinalAnimation();
+    }
+
+    // Tuneable parameters for animation
+    private static final int WAVE_ANIMATION_DURATION = 1200;
+    private static final int RETURN_TO_HOME_DELAY = 1200;
+    private static final int RETURN_TO_HOME_DURATION = 200;
+    private static final int HIDE_ANIMATION_DELAY = 200;
+    private static final int HIDE_ANIMATION_DURATION = 200;
+    private static final int SHOW_ANIMATION_DURATION = 200;
+    private static final int SHOW_ANIMATION_DELAY = 50;
+    private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
+    private static final int REVEAL_GLOW_DELAY = 0;
+    private static final int REVEAL_GLOW_DURATION = 0;
+
+    private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
+    private static final float TARGET_SCALE_EXPANDED = 1.0f;
+    private static final float TARGET_SCALE_COLLAPSED = 0.8f;
+    private static final float RING_SCALE_EXPANDED = 1.0f;
+    private static final float RING_SCALE_COLLAPSED = 0.5f;
+
+    private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
+    private AnimationBundle mWaveAnimations = new AnimationBundle();
+    private AnimationBundle mTargetAnimations = new AnimationBundle();
+    private AnimationBundle mGlowAnimations = new AnimationBundle();
+    private ArrayList<String> mTargetDescriptions;
+    private ArrayList<String> mDirectionDescriptions;
+    private OnTriggerListener mOnTriggerListener;
+    private TargetDrawable mHandleDrawable;
+    private TargetDrawable mOuterRing;
+    private Vibrator mVibrator;
+
+    private int mFeedbackCount = 3;
+    private int mVibrationDuration = 0;
+    private int mGrabbedState;
+    private int mActiveTarget = -1;
+    private float mGlowRadius;
+    private float mWaveCenterX;
+    private float mWaveCenterY;
+    private int mMaxTargetHeight;
+    private int mMaxTargetWidth;
+
+    private float mOuterRadius = 0.0f;
+    private float mSnapMargin = 0.0f;
+    private boolean mDragging;
+    private int mNewTargetResources;
+
+    private class AnimationBundle extends ArrayList<Tweener> {
+        private static final long serialVersionUID = 0xA84D78726F127468L;
+        private boolean mSuspended;
+
+        public void start() {
+            if (mSuspended) return; // ignore attempts to start animations
+            final int count = size();
+            for (int i = 0; i < count; i++) {
+                Tweener anim = get(i);
+                anim.animator.start();
+            }
+        }
+
+        public void cancel() {
+            final int count = size();
+            for (int i = 0; i < count; i++) {
+                Tweener anim = get(i);
+                anim.animator.cancel();
+            }
+            clear();
+        }
+
+        public void stop() {
+            final int count = size();
+            for (int i = 0; i < count; i++) {
+                Tweener anim = get(i);
+                anim.animator.end();
+            }
+            clear();
+        }
+
+        public void setSuspended(boolean suspend) {
+            mSuspended = suspend;
+        }
+    };
+
+    private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
+            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
+            dispatchOnFinishFinalAnimation();
+        }
+    };
+
+    private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
+            ping();
+            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
+            dispatchOnFinishFinalAnimation();
+        }
+    };
+
+    private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
+        public void onAnimationUpdate(ValueAnimator animation) {
+            invalidate();
+        }
+    };
+
+    private boolean mAnimatingTargets;
+    private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
+            if (mNewTargetResources != 0) {
+                internalSetTargetResources(mNewTargetResources);
+                mNewTargetResources = 0;
+                hideTargets(false, false);
+            }
+            mAnimatingTargets = false;
+        }
+    };
+    private int mTargetResourceId;
+    private int mTargetDescriptionsResourceId;
+    private int mDirectionDescriptionsResourceId;
+    private boolean mAlwaysTrackFinger;
+    private int mHorizontalInset;
+    private int mVerticalInset;
+    private int mGravity = Gravity.TOP;
+    private boolean mInitialLayout = true;
+    private Tweener mBackgroundAnimator;
+    private PointCloud mPointCloud;
+    private float mInnerRadius;
+
+    public GlowPadView(Context context) {
+        this(context, null);
+    }
+
+    public GlowPadView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        Resources res = context.getResources();
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlowPadView);
+        mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
+        mOuterRadius = a.getDimension(R.styleable.GlowPadView_outerRadius, mOuterRadius);
+        mSnapMargin = a.getDimension(R.styleable.GlowPadView_snapMargin, mSnapMargin);
+        mVibrationDuration = a.getInt(R.styleable.GlowPadView_vibrationDuration,
+                mVibrationDuration);
+        mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
+                mFeedbackCount);
+        mHandleDrawable = new TargetDrawable(res,
+                a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+        mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+        mOuterRing = new TargetDrawable(res,
+                getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
+
+        mAlwaysTrackFinger = a.getBoolean(R.styleable.GlowPadView_alwaysTrackFinger, false);
+
+        int pointId = getResourceId(a, R.styleable.GlowPadView_pointDrawable);
+        Drawable pointDrawable = pointId != 0 ? res.getDrawable(pointId) : null;
+        mGlowRadius = a.getDimension(R.styleable.GlowPadView_glowRadius, 0.0f);
+
+        TypedValue outValue = new TypedValue();
+
+        // Read array of target drawables
+        if (a.getValue(R.styleable.GlowPadView_targetDrawables, outValue)) {
+            internalSetTargetResources(outValue.resourceId);
+        }
+        if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
+            throw new IllegalStateException("Must specify at least one target drawable");
+        }
+
+        // Read array of target descriptions
+        if (a.getValue(R.styleable.GlowPadView_targetDescriptions, outValue)) {
+            final int resourceId = outValue.resourceId;
+            if (resourceId == 0) {
+                throw new IllegalStateException("Must specify target descriptions");
+            }
+            setTargetDescriptionsResourceId(resourceId);
+        }
+
+        // Read array of direction descriptions
+        if (a.getValue(R.styleable.GlowPadView_directionDescriptions, outValue)) {
+            final int resourceId = outValue.resourceId;
+            if (resourceId == 0) {
+                throw new IllegalStateException("Must specify direction descriptions");
+            }
+            setDirectionDescriptionsResourceId(resourceId);
+        }
+
+        a.recycle();
+
+        // Use gravity attribute from LinearLayout
+        a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
+        mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
+        a.recycle();
+
+        setVibrateEnabled(mVibrationDuration > 0);
+
+        assignDefaultsIfNeeded();
+
+        mPointCloud = new PointCloud(pointDrawable);
+        mPointCloud.makePointCloud(mInnerRadius, mOuterRadius);
+        mPointCloud.glowManager.setRadius(mGlowRadius);
+    }
+
+    private int getResourceId(TypedArray a, int id) {
+        TypedValue tv = a.peekValue(id);
+        return tv == null ? 0 : tv.resourceId;
+    }
+
+    private void dump() {
+        Log.v(TAG, "Outer Radius = " + mOuterRadius);
+        Log.v(TAG, "SnapMargin = " + mSnapMargin);
+        Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
+        Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
+        Log.v(TAG, "GlowRadius = " + mGlowRadius);
+        Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
+        Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
+    }
+
+    public void suspendAnimations() {
+        mWaveAnimations.setSuspended(true);
+        mTargetAnimations.setSuspended(true);
+        mGlowAnimations.setSuspended(true);
+    }
+
+    public void resumeAnimations() {
+        mWaveAnimations.setSuspended(false);
+        mTargetAnimations.setSuspended(false);
+        mGlowAnimations.setSuspended(false);
+        mWaveAnimations.start();
+        mTargetAnimations.start();
+        mGlowAnimations.start();
+    }
+
+    @Override
+    protected int getSuggestedMinimumWidth() {
+        // View should be large enough to contain the background + handle and
+        // target drawable on either edge.
+        return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
+    }
+
+    @Override
+    protected int getSuggestedMinimumHeight() {
+        // View should be large enough to contain the unlock ring + target and
+        // target drawable on either edge
+        return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
+    }
+
+    private int resolveMeasured(int measureSpec, int desired)
+    {
+        int result = 0;
+        int specSize = MeasureSpec.getSize(measureSpec);
+        switch (MeasureSpec.getMode(measureSpec)) {
+            case MeasureSpec.UNSPECIFIED:
+                result = desired;
+                break;
+            case MeasureSpec.AT_MOST:
+                result = Math.min(specSize, desired);
+                break;
+            case MeasureSpec.EXACTLY:
+            default:
+                result = specSize;
+        }
+        return result;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int minimumWidth = getSuggestedMinimumWidth();
+        final int minimumHeight = getSuggestedMinimumHeight();
+        int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
+        int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
+        computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
+        setMeasuredDimension(computedWidth, computedHeight);
+    }
+
+    private void switchToState(int state, float x, float y) {
+        switch (state) {
+            case STATE_IDLE:
+                deactivateTargets();
+                hideGlow(0, 0, 0.0f, null);
+                startBackgroundAnimation(0, 0.0f);
+                mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+                mHandleDrawable.setAlpha(1.0f);
+                break;
+
+            case STATE_START:
+                startBackgroundAnimation(0, 0.0f);
+                break;
+
+            case STATE_FIRST_TOUCH:
+                mHandleDrawable.setAlpha(0.0f);
+                deactivateTargets();
+                showTargets(true);
+                startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
+                setGrabbedState(OnTriggerListener.CENTER_HANDLE);
+                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                    announceTargets();
+                }
+                break;
+
+            case STATE_TRACKING:
+                mHandleDrawable.setAlpha(0.0f);
+                showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 1.0f, null);
+                break;
+
+            case STATE_SNAP:
+                // TODO: Add transition states (see list_selector_background_transition.xml)
+                mHandleDrawable.setAlpha(0.0f);
+                showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 0.0f, null);
+                break;
+
+            case STATE_FINISH:
+                doFinish();
+                break;
+        }
+    }
+
+    private void showGlow(int duration, int delay, float finalAlpha,
+            AnimatorListener finishListener) {
+        mGlowAnimations.cancel();
+        mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
+                "ease", Ease.Cubic.easeIn,
+                "delay", delay,
+                "alpha", finalAlpha,
+                "onUpdate", mUpdateListener,
+                "onComplete", finishListener));
+        mGlowAnimations.start();
+    }
+
+    private void hideGlow(int duration, int delay, float finalAlpha,
+            AnimatorListener finishListener) {
+        mGlowAnimations.cancel();
+        mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
+                "ease", Ease.Quart.easeOut,
+                "delay", delay,
+                "alpha", finalAlpha,
+                "x", 0.0f,
+                "y", 0.0f,
+                "onUpdate", mUpdateListener,
+                "onComplete", finishListener));
+        mGlowAnimations.start();
+    }
+
+    private void deactivateTargets() {
+        final int count = mTargetDrawables.size();
+        for (int i = 0; i < count; i++) {
+            TargetDrawable target = mTargetDrawables.get(i);
+            target.setState(TargetDrawable.STATE_INACTIVE);
+        }
+        mActiveTarget = -1;
+    }
+
+    /**
+     * Dispatches a trigger event to listener. Ignored if a listener is not set.
+     * @param whichTarget the target that was triggered.
+     */
+    private void dispatchTriggerEvent(int whichTarget) {
+        vibrate();
+        if (mOnTriggerListener != null) {
+            mOnTriggerListener.onTrigger(this, whichTarget);
+        }
+    }
+
+    private void dispatchOnFinishFinalAnimation() {
+        if (mOnTriggerListener != null) {
+            mOnTriggerListener.onFinishFinalAnimation();
+        }
+    }
+
+    private void doFinish() {
+        final int activeTarget = mActiveTarget;
+        final boolean targetHit =  activeTarget != -1;
+
+        if (targetHit) {
+            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+
+            highlightSelected(activeTarget);
+
+            // Inform listener of any active targets.  Typically only one will be active.
+            hideGlow(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
+            dispatchTriggerEvent(activeTarget);
+            if (!mAlwaysTrackFinger) {
+                // Force ring and targets to finish animation to final expanded state
+                mTargetAnimations.stop();
+            }
+        } else {
+            // Animate handle back to the center based on current state.
+            hideGlow(HIDE_ANIMATION_DURATION, 0, 0.0f, mResetListenerWithPing);
+            hideTargets(true, false);
+        }
+
+        setGrabbedState(OnTriggerListener.NO_HANDLE);
+    }
+
+    private void highlightSelected(int activeTarget) {
+        // Highlight the given target and fade others
+        mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+        hideUnselected(activeTarget);
+    }
+
+    private void hideUnselected(int active) {
+        for (int i = 0; i < mTargetDrawables.size(); i++) {
+            if (i != active) {
+                mTargetDrawables.get(i).setAlpha(0.0f);
+            }
+        }
+    }
+
+    private void hideTargets(boolean animate, boolean expanded) {
+        mTargetAnimations.cancel();
+        // Note: these animations should complete at the same time so that we can swap out
+        // the target assets asynchronously from the setTargetResources() call.
+        mAnimatingTargets = animate;
+        final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
+        final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
+
+        final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
+        final int length = mTargetDrawables.size();
+        final TimeInterpolator interpolator = Ease.Cubic.easeOut;
+        for (int i = 0; i < length; i++) {
+            TargetDrawable target = mTargetDrawables.get(i);
+            target.setState(TargetDrawable.STATE_INACTIVE);
+            mTargetAnimations.add(Tweener.to(target, duration,
+                    "ease", interpolator,
+                    "alpha", 0.0f,
+                    "scaleX", targetScale,
+                    "scaleY", targetScale,
+                    "delay", delay,
+                    "onUpdate", mUpdateListener));
+        }
+
+        final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
+        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
+                "ease", interpolator,
+                "alpha", 0.0f,
+                "scaleX", ringScaleTarget,
+                "scaleY", ringScaleTarget,
+                "delay", delay,
+                "onUpdate", mUpdateListener,
+                "onComplete", mTargetUpdateListener));
+
+        mTargetAnimations.start();
+    }
+
+    private void showTargets(boolean animate) {
+        mTargetAnimations.stop();
+        mAnimatingTargets = animate;
+        final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
+        final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
+        final int length = mTargetDrawables.size();
+        for (int i = 0; i < length; i++) {
+            TargetDrawable target = mTargetDrawables.get(i);
+            target.setState(TargetDrawable.STATE_INACTIVE);
+            mTargetAnimations.add(Tweener.to(target, duration,
+                    "ease", Ease.Cubic.easeOut,
+                    "alpha", 1.0f,
+                    "scaleX", 1.0f,
+                    "scaleY", 1.0f,
+                    "delay", delay,
+                    "onUpdate", mUpdateListener));
+        }
+        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
+                "ease", Ease.Cubic.easeOut,
+                "alpha", 1.0f,
+                "scaleX", 1.0f,
+                "scaleY", 1.0f,
+                "delay", delay,
+                "onUpdate", mUpdateListener,
+                "onComplete", mTargetUpdateListener));
+
+        mTargetAnimations.start();
+    }
+
+    private void vibrate() {
+        if (mVibrator != null) {
+            mVibrator.vibrate(mVibrationDuration);
+        }
+    }
+
+    private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
+        Resources res = getContext().getResources();
+        TypedArray array = res.obtainTypedArray(resourceId);
+        final int count = array.length();
+        ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
+        for (int i = 0; i < count; i++) {
+            TypedValue value = array.peekValue(i);
+            TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
+            drawables.add(target);
+        }
+        array.recycle();
+        return drawables;
+    }
+
+    private void internalSetTargetResources(int resourceId) {
+        final ArrayList<TargetDrawable> targets = loadDrawableArray(resourceId);
+        mTargetDrawables = targets;
+        mTargetResourceId = resourceId;
+
+        int maxWidth = mHandleDrawable.getWidth();
+        int maxHeight = mHandleDrawable.getHeight();
+        final int count = targets.size();
+        for (int i = 0; i < count; i++) {
+            TargetDrawable target = targets.get(i);
+            maxWidth = Math.max(maxWidth, target.getWidth());
+            maxHeight = Math.max(maxHeight, target.getHeight());
+        }
+        if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
+            mMaxTargetWidth = maxWidth;
+            mMaxTargetHeight = maxHeight;
+            requestLayout(); // required to resize layout and call updateTargetPositions()
+        } else {
+            updateTargetPositions(mWaveCenterX, mWaveCenterY);
+            updatePointCloudPosition(mWaveCenterX, mWaveCenterY);
+        }
+    }
+
+    /**
+     * Loads an array of drawables from the given resourceId.
+     *
+     * @param resourceId
+     */
+    public void setTargetResources(int resourceId) {
+        if (mAnimatingTargets) {
+            // postpone this change until we return to the initial state
+            mNewTargetResources = resourceId;
+        } else {
+            internalSetTargetResources(resourceId);
+        }
+    }
+
+    public int getTargetResourceId() {
+        return mTargetResourceId;
+    }
+
+    /**
+     * Sets the resource id specifying the target descriptions for accessibility.
+     *
+     * @param resourceId The resource id.
+     */
+    public void setTargetDescriptionsResourceId(int resourceId) {
+        mTargetDescriptionsResourceId = resourceId;
+        if (mTargetDescriptions != null) {
+            mTargetDescriptions.clear();
+        }
+    }
+
+    /**
+     * Gets the resource id specifying the target descriptions for accessibility.
+     *
+     * @return The resource id.
+     */
+    public int getTargetDescriptionsResourceId() {
+        return mTargetDescriptionsResourceId;
+    }
+
+    /**
+     * Sets the resource id specifying the target direction descriptions for accessibility.
+     *
+     * @param resourceId The resource id.
+     */
+    public void setDirectionDescriptionsResourceId(int resourceId) {
+        mDirectionDescriptionsResourceId = resourceId;
+        if (mDirectionDescriptions != null) {
+            mDirectionDescriptions.clear();
+        }
+    }
+
+    /**
+     * Gets the resource id specifying the target direction descriptions.
+     *
+     * @return The resource id.
+     */
+    public int getDirectionDescriptionsResourceId() {
+        return mDirectionDescriptionsResourceId;
+    }
+
+    /**
+     * Enable or disable vibrate on touch.
+     *
+     * @param enabled
+     */
+    public void setVibrateEnabled(boolean enabled) {
+        if (enabled && mVibrator == null) {
+            mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+        } else {
+            mVibrator = null;
+        }
+    }
+
+    /**
+     * Starts wave animation.
+     *
+     */
+    public void ping() {
+        if (mFeedbackCount > 0) {
+            startWaveAnimation();
+        }
+    }
+
+    private void stopAndHideWaveAnimation() {
+        mWaveAnimations.cancel();
+        mPointCloud.waveManager.setAlpha(0.0f);
+    }
+
+    private void startWaveAnimation() {
+        mWaveAnimations.cancel();
+        mPointCloud.waveManager.setAlpha(1.0f);
+        mPointCloud.waveManager.setRadius(mHandleDrawable.getWidth()/2.0f);
+        mWaveAnimations.add(Tweener.to(mPointCloud.waveManager, WAVE_ANIMATION_DURATION,
+                "ease", Ease.Linear.easeNone,
+                "delay", 0,
+                "radius", 2.0f * mOuterRadius,
+                "onUpdate", mUpdateListener,
+                "onComplete",
+                new AnimatorListenerAdapter() {
+                    public void onAnimationEnd(Animator animator) {
+                        mPointCloud.waveManager.setRadius(0.0f);
+                        mPointCloud.waveManager.setAlpha(0.0f);
+                    }
+                }));
+        mWaveAnimations.start();
+    }
+
+    /**
+     * Resets the widget to default state and cancels all animation. If animate is 'true', will
+     * animate objects into place. Otherwise, objects will snap back to place.
+     *
+     * @param animate
+     */
+    public void reset(boolean animate) {
+        mGlowAnimations.stop();
+        mTargetAnimations.stop();
+        startBackgroundAnimation(0, 0.0f);
+        stopAndHideWaveAnimation();
+        hideTargets(animate, false);
+        hideGlow(0, 0, 1.0f, null);
+        Tweener.reset();
+    }
+
+    private void startBackgroundAnimation(int duration, float alpha) {
+        final Drawable background = getBackground();
+        if (mAlwaysTrackFinger && background != null) {
+            if (mBackgroundAnimator != null) {
+                mBackgroundAnimator.animator.cancel();
+            }
+            mBackgroundAnimator = Tweener.to(background, duration,
+                    "ease", Ease.Cubic.easeIn,
+                    "alpha", (int)(255.0f * alpha),
+                    "delay", SHOW_ANIMATION_DELAY);
+            mBackgroundAnimator.animator.start();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        final int action = event.getAction();
+        boolean handled = false;
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                if (DEBUG) Log.v(TAG, "*** DOWN ***");
+                handleDown(event);
+                handleMove(event);
+                handled = true;
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (DEBUG) Log.v(TAG, "*** MOVE ***");
+                handleMove(event);
+                handled = true;
+                break;
+
+            case MotionEvent.ACTION_UP:
+                if (DEBUG) Log.v(TAG, "*** UP ***");
+                handleMove(event);
+                handleUp(event);
+                handled = true;
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+                if (DEBUG) Log.v(TAG, "*** CANCEL ***");
+                handleMove(event);
+                handleCancel(event);
+                handled = true;
+                break;
+        }
+        invalidate();
+        return handled ? true : super.onTouchEvent(event);
+    }
+
+    private void updateGlowPosition(float x, float y) {
+        mPointCloud.glowManager.setX(x);
+        mPointCloud.glowManager.setY(y);
+    }
+
+    private void handleDown(MotionEvent event) {
+        float eventX = event.getX();
+        float eventY = event.getY();
+        switchToState(STATE_START, eventX, eventY);
+        if (!trySwitchToFirstTouchState(eventX, eventY)) {
+            mDragging = false;
+        } else {
+            updateGlowPosition(eventX, eventY);
+        }
+    }
+
+    private void handleUp(MotionEvent event) {
+        if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
+        switchToState(STATE_FINISH, event.getX(), event.getY());
+    }
+
+    private void handleCancel(MotionEvent event) {
+        if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
+
+        // We should drop the active target here but it interferes with
+        // moving off the screen in the direction of the navigation bar. At some point we may
+        // want to revisit how we handle this. For now we'll allow a canceled event to
+        // activate the current target.
+
+        // mActiveTarget = -1; // Drop the active target if canceled.
+
+        switchToState(STATE_FINISH, event.getX(), event.getY());
+    }
+
+    private void handleMove(MotionEvent event) {
+        int activeTarget = -1;
+        final int historySize = event.getHistorySize();
+        ArrayList<TargetDrawable> targets = mTargetDrawables;
+        int ntargets = targets.size();
+        float x = 0.0f;
+        float y = 0.0f;
+        for (int k = 0; k < historySize + 1; k++) {
+            float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
+            float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
+            // tx and ty are relative to wave center
+            float tx = eventX - mWaveCenterX;
+            float ty = eventY - mWaveCenterY;
+            float touchRadius = (float) Math.sqrt(dist2(tx, ty));
+            final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
+            float limitX = tx * scale;
+            float limitY = ty * scale;
+            double angleRad = Math.atan2(-ty, tx);
+
+            if (!mDragging) {
+                trySwitchToFirstTouchState(eventX, eventY);
+            }
+
+            if (mDragging) {
+                // For multiple targets, snap to the one that matches
+                final float snapRadius = mOuterRadius - mSnapMargin;
+                final float snapDistance2 = snapRadius * snapRadius;
+                // Find first target in range
+                for (int i = 0; i < ntargets; i++) {
+                    TargetDrawable target = targets.get(i);
+
+                    double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
+                    double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
+                    if (target.isEnabled()) {
+                        boolean angleMatches =
+                            (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
+                            (angleRad + 2 * Math.PI > targetMinRad &&
+                             angleRad + 2 * Math.PI <= targetMaxRad);
+                        if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
+                            activeTarget = i;
+                        }
+                    }
+                }
+            }
+            x = limitX;
+            y = limitY;
+        }
+
+        if (!mDragging) {
+            return;
+        }
+
+        if (activeTarget != -1) {
+            switchToState(STATE_SNAP, x,y);
+            updateGlowPosition(x, y);
+        } else {
+            switchToState(STATE_TRACKING, x, y);
+            updateGlowPosition(x, y);
+        }
+
+        if (mActiveTarget != activeTarget) {
+            // Defocus the old target
+            if (mActiveTarget != -1) {
+                TargetDrawable target = targets.get(mActiveTarget);
+                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
+                    target.setState(TargetDrawable.STATE_INACTIVE);
+                }
+            }
+            // Focus the new target
+            if (activeTarget != -1) {
+                TargetDrawable target = targets.get(activeTarget);
+                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
+                    target.setState(TargetDrawable.STATE_FOCUSED);
+                }
+                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                    String targetContentDescription = getTargetDescription(activeTarget);
+                    announceText(targetContentDescription);
+                }
+            }
+        }
+        mActiveTarget = activeTarget;
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+            final int action = event.getAction();
+            switch (action) {
+                case MotionEvent.ACTION_HOVER_ENTER:
+                    event.setAction(MotionEvent.ACTION_DOWN);
+                    break;
+                case MotionEvent.ACTION_HOVER_MOVE:
+                    event.setAction(MotionEvent.ACTION_MOVE);
+                    break;
+                case MotionEvent.ACTION_HOVER_EXIT:
+                    event.setAction(MotionEvent.ACTION_UP);
+                    break;
+            }
+            onTouchEvent(event);
+            event.setAction(action);
+        }
+        return super.onHoverEvent(event);
+    }
+
+    /**
+     * Sets the current grabbed state, and dispatches a grabbed state change
+     * event to our listener.
+     */
+    private void setGrabbedState(int newState) {
+        if (newState != mGrabbedState) {
+            if (newState != OnTriggerListener.NO_HANDLE) {
+                vibrate();
+            }
+            mGrabbedState = newState;
+            if (mOnTriggerListener != null) {
+                if (newState == OnTriggerListener.NO_HANDLE) {
+                    mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
+                } else {
+                    mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
+                }
+                mOnTriggerListener.onGrabbedStateChange(this, newState);
+            }
+        }
+    }
+
+    private boolean trySwitchToFirstTouchState(float x, float y) {
+        final float tx = x - mWaveCenterX;
+        final float ty = y - mWaveCenterY;
+        if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledGlowRadiusSquared()) {
+            if (DEBUG) Log.v(TAG, "** Handle HIT");
+            switchToState(STATE_FIRST_TOUCH, x, y);
+            updateGlowPosition(tx, ty);
+            mDragging = true;
+            return true;
+        }
+        return false;
+    }
+
+    private void assignDefaultsIfNeeded() {
+        if (mOuterRadius == 0.0f) {
+            mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
+        }
+        if (mSnapMargin == 0.0f) {
+            mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                    SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
+        }
+        if (mInnerRadius == 0.0f) {
+            mInnerRadius = mHandleDrawable.getWidth() / 10.0f;
+        }
+    }
+
+    private void computeInsets(int dx, int dy) {
+        final int layoutDirection = getResolvedLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.LEFT:
+                mHorizontalInset = 0;
+                break;
+            case Gravity.RIGHT:
+                mHorizontalInset = dx;
+                break;
+            case Gravity.CENTER_HORIZONTAL:
+            default:
+                mHorizontalInset = dx / 2;
+                break;
+        }
+        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
+            case Gravity.TOP:
+                mVerticalInset = 0;
+                break;
+            case Gravity.BOTTOM:
+                mVerticalInset = dy;
+                break;
+            case Gravity.CENTER_VERTICAL:
+            default:
+                mVerticalInset = dy / 2;
+                break;
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        final int width = right - left;
+        final int height = bottom - top;
+
+        // Target placement width/height. This puts the targets on the greater of the ring
+        // width or the specified outer radius.
+        final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
+        final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
+        float newWaveCenterX = mHorizontalInset
+                + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
+        float newWaveCenterY = mVerticalInset
+                + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
+
+        if (mInitialLayout) {
+            stopAndHideWaveAnimation();
+            hideTargets(false, false);
+            mInitialLayout = false;
+        }
+
+        mOuterRing.setPositionX(newWaveCenterX);
+        mOuterRing.setPositionY(newWaveCenterY);
+
+        mHandleDrawable.setPositionX(newWaveCenterX);
+        mHandleDrawable.setPositionY(newWaveCenterY);
+
+        updateTargetPositions(newWaveCenterX, newWaveCenterY);
+        updatePointCloudPosition(newWaveCenterX, newWaveCenterY);
+        updateGlowPosition(newWaveCenterX, newWaveCenterY);
+
+        mWaveCenterX = newWaveCenterX;
+        mWaveCenterY = newWaveCenterY;
+
+        if (DEBUG) dump();
+    }
+
+    private void updateTargetPositions(float centerX, float centerY) {
+        // Reposition the target drawables if the view changed.
+        ArrayList<TargetDrawable> targets = mTargetDrawables;
+        final int size = targets.size();
+        final float alpha = (float) (-2.0f * Math.PI / size);
+        for (int i = 0; i < size; i++) {
+            final TargetDrawable targetIcon = targets.get(i);
+            final float angle = alpha * i;
+            targetIcon.setPositionX(centerX);
+            targetIcon.setPositionY(centerY);
+            targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
+            targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
+        }
+    }
+
+    private void updatePointCloudPosition(float centerX, float centerY) {
+        mPointCloud.setCenter(centerX, centerY);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        mPointCloud.draw(canvas);
+        mOuterRing.draw(canvas);
+        final int ntargets = mTargetDrawables.size();
+        for (int i = 0; i < ntargets; i++) {
+            TargetDrawable target = mTargetDrawables.get(i);
+            if (target != null) {
+                target.draw(canvas);
+            }
+        }
+        mHandleDrawable.draw(canvas);
+    }
+
+    public void setOnTriggerListener(OnTriggerListener listener) {
+        mOnTriggerListener = listener;
+    }
+
+    private float square(float d) {
+        return d * d;
+    }
+
+    private float dist2(float dx, float dy) {
+        return dx*dx + dy*dy;
+    }
+
+    private float getScaledGlowRadiusSquared() {
+        final float scaledTapRadius;
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mGlowRadius;
+        } else {
+            scaledTapRadius = mGlowRadius;
+        }
+        return square(scaledTapRadius);
+    }
+
+    private void announceTargets() {
+        StringBuilder utterance = new StringBuilder();
+        final int targetCount = mTargetDrawables.size();
+        for (int i = 0; i < targetCount; i++) {
+            String targetDescription = getTargetDescription(i);
+            String directionDescription = getDirectionDescription(i);
+            if (!TextUtils.isEmpty(targetDescription)
+                    && !TextUtils.isEmpty(directionDescription)) {
+                String text = String.format(directionDescription, targetDescription);
+                utterance.append(text);
+            }
+            if (utterance.length() > 0) {
+                announceText(utterance.toString());
+            }
+        }
+    }
+
+    private void announceText(String text) {
+        setContentDescription(text);
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        setContentDescription(null);
+    }
+
+    private String getTargetDescription(int index) {
+        if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
+            mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
+            if (mTargetDrawables.size() != mTargetDescriptions.size()) {
+                Log.w(TAG, "The number of target drawables must be"
+                        + " equal to the number of target descriptions.");
+                return null;
+            }
+        }
+        return mTargetDescriptions.get(index);
+    }
+
+    private String getDirectionDescription(int index) {
+        if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
+            mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
+            if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
+                Log.w(TAG, "The number of target drawables must be"
+                        + " equal to the number of direction descriptions.");
+                return null;
+            }
+        }
+        return mDirectionDescriptions.get(index);
+    }
+
+    private ArrayList<String> loadDescriptions(int resourceId) {
+        TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
+        final int count = array.length();
+        ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
+        for (int i = 0; i < count; i++) {
+            String contentDescription = array.getString(i);
+            targetContentDescriptions.add(contentDescription);
+        }
+        array.recycle();
+        return targetContentDescriptions;
+    }
+
+    public int getResourceIdForTarget(int index) {
+        final TargetDrawable drawable = mTargetDrawables.get(index);
+        return drawable == null ? 0 : drawable.getResourceId();
+    }
+
+    public void setEnableTarget(int resourceId, boolean enabled) {
+        for (int i = 0; i < mTargetDrawables.size(); i++) {
+            final TargetDrawable target = mTargetDrawables.get(i);
+            if (target.getResourceId() == resourceId) {
+                target.setEnabled(enabled);
+                break; // should never be more than one match
+            }
+        }
+    }
+
+    /**
+     * Gets the position of a target in the array that matches the given resource.
+     * @param resourceId
+     * @return the index or -1 if not found
+     */
+    public int getTargetPosition(int resourceId) {
+        for (int i = 0; i < mTargetDrawables.size(); i++) {
+            final TargetDrawable target = mTargetDrawables.get(i);
+            if (target.getResourceId() == resourceId) {
+                return i; // should never be more than one match
+            }
+        }
+        return -1;
+    }
+
+    private boolean replaceTargetDrawables(Resources res, int existingResourceId,
+            int newResourceId) {
+        if (existingResourceId == 0 || newResourceId == 0) {
+            return false;
+        }
+
+        boolean result = false;
+        final ArrayList<TargetDrawable> drawables = mTargetDrawables;
+        final int size = drawables.size();
+        for (int i = 0; i < size; i++) {
+            final TargetDrawable target = drawables.get(i);
+            if (target != null && target.getResourceId() == existingResourceId) {
+                target.setDrawable(res, newResourceId);
+                result = true;
+            }
+        }
+
+        if (result) {
+            requestLayout(); // in case any given drawable's size changes
+        }
+
+        return result;
+    }
+
+    /**
+     * Searches the given package for a resource to use to replace the Drawable on the
+     * target with the given resource id
+     * @param component of the .apk that contains the resource
+     * @param name of the metadata in the .apk
+     * @param existingResId the resource id of the target to search for
+     * @return true if found in the given package and replaced at least one target Drawables
+     */
+    public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
+                int existingResId) {
+        if (existingResId == 0) return false;
+
+        try {
+            PackageManager packageManager = mContext.getPackageManager();
+            // Look for the search icon specified in the activity meta-data
+            Bundle metaData = packageManager.getActivityInfo(
+                    component, PackageManager.GET_META_DATA).metaData;
+            if (metaData != null) {
+                int iconResId = metaData.getInt(name);
+                if (iconResId != 0) {
+                    Resources res = packageManager.getResourcesForActivity(component);
+                    return replaceTargetDrawables(res, existingResId, iconResId);
+                }
+            }
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Failed to swap drawable; "
+                    + component.flattenToShortString() + " not found", e);
+        } catch (Resources.NotFoundException nfe) {
+            Log.w(TAG, "Failed to swap drawable from "
+                    + component.flattenToShortString(), nfe);
+        }
+        return false;
+    }
+}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 89dbd1b..10804c0 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -117,11 +117,8 @@
     private float mWaveCenterY;
     private int mMaxTargetHeight;
     private int mMaxTargetWidth;
-    private float mHorizontalOffset;
-    private float mVerticalOffset;
 
     private float mOuterRadius = 0.0f;
-    private float mHitRadius = 0.0f;
     private float mSnapMargin = 0.0f;
     private boolean mDragging;
     private int mNewTargetResources;
@@ -215,10 +212,6 @@
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveView);
         mOuterRadius = a.getDimension(R.styleable.MultiWaveView_outerRadius, mOuterRadius);
-//        mHorizontalOffset = a.getDimension(R.styleable.MultiWaveView_horizontalOffset,
-//                mHorizontalOffset);
-//        mVerticalOffset = a.getDimension(R.styleable.MultiWaveView_verticalOffset, mVerticalOffset);
-        mHitRadius = a.getDimension(R.styleable.MultiWaveView_hitRadius, mHitRadius);
         mSnapMargin = a.getDimension(R.styleable.MultiWaveView_snapMargin, mSnapMargin);
         mVibrationDuration = a.getInt(R.styleable.MultiWaveView_vibrationDuration,
                 mVibrationDuration);
@@ -230,7 +223,6 @@
         mOuterRing = new TargetDrawable(res,
                 a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
         mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
-        mGravity = a.getInt(R.styleable.MultiWaveView_gravity, Gravity.TOP);
 
         // Read array of chevron drawables
         TypedValue outValue = new TypedValue();
@@ -244,24 +236,6 @@
             }
         }
 
-        // Support old-style chevron specification if new specification not found
-        if (mChevronDrawables.size() == 0) {
-            final int chevronResIds[] = {
-                    R.styleable.MultiWaveView_rightChevronDrawable,
-                    R.styleable.MultiWaveView_topChevronDrawable,
-                    R.styleable.MultiWaveView_leftChevronDrawable,
-                    R.styleable.MultiWaveView_bottomChevronDrawable
-            };
-
-            for (int i = 0; i < chevronResIds.length; i++) {
-                TypedValue typedValue = a.peekValue(chevronResIds[i]);
-                for (int k = 0; k < mFeedbackCount; k++) {
-                    mChevronDrawables.add(
-                        typedValue != null ? new TargetDrawable(res, typedValue.resourceId) : null);
-                }
-            }
-        }
-
         // Read array of target drawables
         if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
             internalSetTargetResources(outValue.resourceId);
@@ -289,21 +263,24 @@
         }
 
         a.recycle();
+
+        // Use gravity attribute from LinearLayout
+        a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
+        mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
+        a.recycle();
+
         setVibrateEnabled(mVibrationDuration > 0);
         assignDefaultsIfNeeded();
     }
 
     private void dump() {
         Log.v(TAG, "Outer Radius = " + mOuterRadius);
-        Log.v(TAG, "HitRadius = " + mHitRadius);
         Log.v(TAG, "SnapMargin = " + mSnapMargin);
         Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
         Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
         Log.v(TAG, "TapRadius = " + mTapRadius);
         Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
         Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
-        Log.v(TAG, "HorizontalOffset = " + mHorizontalOffset);
-        Log.v(TAG, "VerticalOffset = " + mVerticalOffset);
     }
 
     public void suspendAnimations() {
@@ -843,7 +820,6 @@
         final int historySize = event.getHistorySize();
         ArrayList<TargetDrawable> targets = mTargetDrawables;
         int ntargets = targets.size();
-        final boolean singleTarget = ntargets == 1;
         float x = 0.0f;
         float y = 0.0f;
         for (int k = 0; k < historySize + 1; k++) {
@@ -856,31 +832,29 @@
             final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
             float limitX = tx * scale;
             float limitY = ty * scale;
+            double angleRad = Math.atan2(-ty, tx);
 
             if (!mDragging) {
                 trySwitchToFirstTouchState(eventX, eventY);
             }
 
             if (mDragging) {
-                if (singleTarget) {
-                    // Snap to outer ring if there's only one target
-                    float snapRadius = mOuterRadius - mSnapMargin;
-                    if (touchRadius > snapRadius) {
-                        activeTarget = 0;
-                    }
-                } else {
-                    // For more than one target, snap to the closest one less than hitRadius away.
-                    float best = Float.MAX_VALUE;
-                    final float hitRadius2 = mHitRadius * mHitRadius;
-                    // Find first target in range
-                    for (int i = 0; i < ntargets; i++) {
-                        TargetDrawable target = targets.get(i);
-                        float dx = limitX - target.getX();
-                        float dy = limitY - target.getY();
-                        float dist2 = dx*dx + dy*dy;
-                        if (target.isEnabled() && dist2 < hitRadius2 && dist2 < best) {
+                // For multiple targets, snap to the one that matches
+                final float snapRadius = mOuterRadius - mSnapMargin;
+                final float snapDistance2 = snapRadius * snapRadius;
+                // Find first target in range
+                for (int i = 0; i < ntargets; i++) {
+                    TargetDrawable target = targets.get(i);
+
+                    double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
+                    double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
+                    if (target.isEnabled()) {
+                        boolean angleMatches =
+                            (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
+                            (angleRad + 2 * Math.PI > targetMinRad &&
+                             angleRad + 2 * Math.PI <= targetMaxRad);
+                        if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
                             activeTarget = i;
-                            best = dist2;
                         }
                     }
                 }
@@ -895,10 +869,7 @@
 
         if (activeTarget != -1) {
             switchToState(STATE_SNAP, x,y);
-            TargetDrawable target = targets.get(activeTarget);
-            final float newX = singleTarget ? x : target.getX();
-            final float newY = singleTarget ? y : target.getY();
-            moveHandleTo(newX, newY, false);
+            moveHandleTo(x, y, false);
         } else {
             switchToState(STATE_TRACKING, x, y);
             moveHandleTo(x, y, false);
@@ -992,10 +963,6 @@
         if (mOuterRadius == 0.0f) {
             mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
         }
-        if (mHitRadius == 0.0f) {
-            // Use the radius of inscribed circle of the first target.
-            mHitRadius = mTargetDrawables.get(0).getWidth() / 2.0f;
-        }
         if (mSnapMargin == 0.0f) {
             mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                     SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
@@ -1042,9 +1009,9 @@
         // width or the specified outer radius.
         final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
         final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
-        float newWaveCenterX = mHorizontalOffset + mHorizontalInset
+        float newWaveCenterX = mHorizontalInset
                 + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
-        float newWaveCenterY = mVerticalOffset + mVerticalInset
+        float newWaveCenterY = mVerticalInset
                 + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
 
         if (mInitialLayout) {
diff --git a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
new file mode 100644
index 0000000..2ef8c78
--- /dev/null
+++ b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget.multiwaveview;
+
+import java.util.ArrayList;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.util.FloatMath;
+import android.util.Log;
+
+public class PointCloud {
+    private static final float MIN_POINT_SIZE = 2.0f;
+    private static final float MAX_POINT_SIZE = 4.0f;
+    private static final int INNER_POINTS = 8;
+    private static final String TAG = "PointCloud";
+    private ArrayList<Point> mPointCloud = new ArrayList<Point>();
+    private Drawable mDrawable;
+    private float mCenterX;
+    private float mCenterY;
+    private Paint mPaint;
+    private float mScale = 1.0f;
+    private static final float PI = (float) Math.PI;
+
+    // These allow us to have multiple concurrent animations.
+    WaveManager waveManager = new WaveManager();
+    GlowManager glowManager = new GlowManager();
+    private float mOuterRadius;
+
+    public class WaveManager {
+        private float radius = 50;
+        private float width = 200.0f; // TODO: Make configurable
+        private float alpha = 0.0f;
+        public void setRadius(float r) {
+            radius = r;
+        }
+
+        public float getRadius() {
+            return radius;
+        }
+
+        public void setAlpha(float a) {
+            alpha = a;
+        }
+
+        public float getAlpha() {
+            return alpha;
+        }
+    };
+
+    public class GlowManager {
+        private float x;
+        private float y;
+        private float radius = 0.0f;
+        private float alpha = 0.0f;
+
+        public void setX(float x1) {
+            x = x1;
+        }
+
+        public float getX() {
+            return x;
+        }
+
+        public void setY(float y1) {
+            y = y1;
+        }
+
+        public float getY() {
+            return y;
+        }
+
+        public void setAlpha(float a) {
+            alpha = a;
+        }
+
+        public float getAlpha() {
+            return alpha;
+        }
+
+        public void setRadius(float r) {
+            radius = r;
+        }
+
+        public float getRadius() {
+            return radius;
+        }
+    }
+
+    class Point {
+        float x;
+        float y;
+        float radius;
+
+        public Point(float x2, float y2, float r) {
+            x = (float) x2;
+            y = (float) y2;
+            radius = r;
+        }
+    }
+
+    public PointCloud(Drawable drawable) {
+        mPaint = new Paint();
+        mPaint.setFilterBitmap(true);
+        mPaint.setColor(Color.rgb(255, 255, 255)); // TODO: make configurable
+        mPaint.setAntiAlias(true);
+        mPaint.setDither(true);
+
+        mDrawable = drawable;
+        if (mDrawable != null) {
+            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+        }
+    }
+
+    public void setCenter(float x, float y) {
+        mCenterX = x;
+        mCenterY = y;
+    }
+
+    public void makePointCloud(float innerRadius, float outerRadius) {
+        if (innerRadius == 0) {
+            Log.w(TAG, "Must specify an inner radius");
+            return;
+        }
+        mOuterRadius = outerRadius;
+        mPointCloud.clear();
+        final float pointAreaRadius =  (outerRadius - innerRadius);
+        final float ds = (2.0f * PI * innerRadius / INNER_POINTS);
+        final int bands = (int) Math.round(pointAreaRadius / ds);
+        final float dr = pointAreaRadius / bands;
+        float r = innerRadius;
+        for (int b = 0; b <= bands; b++, r += dr) {
+            float circumference = 2.0f * PI * r;
+            final int pointsInBand = (int) (circumference / ds);
+            float eta = PI/2.0f;
+            float dEta = 2.0f * PI / pointsInBand;
+            for (int i = 0; i < pointsInBand; i++) {
+                float x = r * FloatMath.cos(eta);
+                float y = r * FloatMath.sin(eta);
+                eta += dEta;
+                mPointCloud.add(new Point(x, y, r));
+            }
+        }
+    }
+
+    public void setScale(float scale) {
+        mScale  = scale;
+    }
+
+    public float getScale() {
+        return mScale;
+    }
+
+    private static float hypot(float x, float y) {
+        return FloatMath.sqrt(x*x + y*y);
+    }
+
+    private static float max(float a, float b) {
+        return a > b ? a : b;
+    }
+
+    public int getAlphaForPoint(Point point) {
+        // Contribution from positional glow
+        float glowDistance = hypot(glowManager.x - point.x, glowManager.y - point.y);
+        float glowAlpha = 0.0f;
+        if (glowDistance < glowManager.radius) {
+            float cosf = FloatMath.cos(PI * 0.5f * glowDistance / glowManager.radius);
+            glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cosf, 0.5f));
+        }
+
+        // Compute contribution from Wave
+        float radius = hypot(point.x, point.y);
+        float distanceToWaveRing = Math.abs(radius - waveManager.radius);
+        float waveAlpha = 0.0f;
+        if (distanceToWaveRing < waveManager.width * 0.5f) {
+            float cosf = FloatMath.cos(PI * 0.5f * distanceToWaveRing / waveManager.width);
+            waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cosf, 15.0f));
+        }
+
+        return (int) (max(glowAlpha, waveAlpha) * 255);
+    }
+
+    private float interp(float min, float max, float f) {
+        return min + (max - min) * f;
+    }
+
+    public void draw(Canvas canvas) {
+        ArrayList<Point> points = mPointCloud;
+        final float cx = mDrawable != null ? (-mDrawable.getIntrinsicWidth() / 2) : 0;
+        final float cy = mDrawable != null ? (-mDrawable.getIntrinsicHeight() / 2) : 0;
+        canvas.save(Canvas.MATRIX_SAVE_FLAG);
+        canvas.scale(mScale, mScale, mCenterX, mCenterY);
+        for (int i = 0; i < points.size(); i++) {
+            Point point = points.get(i);
+            final float pointSize = interp(MAX_POINT_SIZE, MIN_POINT_SIZE,
+                    point.radius / mOuterRadius);
+            final float px = point.x + cx + mCenterX;
+            final float py = point.y + cy + mCenterY;
+            int alpha = getAlphaForPoint(point);
+
+            if (alpha == 0) continue;
+
+            if (mDrawable != null) {
+                canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                float s = pointSize / MAX_POINT_SIZE;
+                canvas.scale(s, s, px, py);
+                canvas.translate(px, py);
+                mDrawable.setAlpha(alpha);
+                mDrawable.draw(canvas);
+                canvas.restore();
+            } else {
+                mPaint.setAlpha(alpha);
+                canvas.drawCircle(px, py, pointSize, mPaint);
+            }
+        }
+        canvas.restore();
+    }
+
+}
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
index 0df211a..34447ef 100644
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ b/core/jni/android_bluetooth_HeadsetBase.cpp
@@ -115,7 +115,7 @@
     pfd.fd = fd;
     pfd.events = POLLIN;
     *err = errno = 0;
-    int ret = poll(&pfd, 1, timeout_ms);
+    int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, timeout_ms));
     if (ret < 0) {
         ALOGE("poll() error\n");
         *err = errno;
@@ -136,7 +136,7 @@
     while ((int)(bufit - buf) < (len - 1))
     {
         errno = 0;
-        int rc = read(fd, bufit, 1);
+        int rc = TEMP_FAILURE_RETRY(read(fd, bufit, 1));
 
         if (!rc)
             break;
@@ -427,7 +427,7 @@
             {
                 char ch;
                 errno = 0;
-                int nr = read(nat->rfcomm_sock, &ch, 1);
+                int nr = TEMP_FAILURE_RETRY(read(nat->rfcomm_sock, &ch, 1));
                 /* It should be that nr != 1 because we just opened a socket
                    and we haven't sent anything over it for the other side to
                    respond... but one can't be paranoid enough.
diff --git a/core/jni/android_database_SQLiteCommon.cpp b/core/jni/android_database_SQLiteCommon.cpp
index 46009bd..eefcb74 100644
--- a/core/jni/android_database_SQLiteCommon.cpp
+++ b/core/jni/android_database_SQLiteCommon.cpp
@@ -16,6 +16,8 @@
 
 #include "android_database_SQLiteCommon.h"
 
+#include <utils/String8.h>
+
 namespace android {
 
 /* throw a SQLiteException with a message appropriate for the error in handle */
@@ -37,7 +39,8 @@
         // the error message may contain more information than the error code
         // because it is based on the extended error code rather than the simplified
         // error code that SQLite normally returns.
-        throw_sqlite3_exception(env, sqlite3_errcode(handle), sqlite3_errmsg(handle), message);
+        throw_sqlite3_exception(env, sqlite3_extended_errcode(handle),
+                sqlite3_errmsg(handle), message);
     } else {
         // we use SQLITE_OK so that a generic SQLiteException is thrown;
         // any code not specified in the switch statement below would do.
@@ -49,9 +52,7 @@
  * should only be used when the database connection is not available because the
  * error information will not be quite as rich */
 void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
-    char temp[21];
-    sprintf(temp, "error code %d", errcode);
-    throw_sqlite3_exception(env, errcode, temp, message);
+    throw_sqlite3_exception(env, errcode, "unknown error", message);
 }
 
 /* throw a SQLiteException for a given error code, sqlite3message, and
@@ -60,7 +61,7 @@
 void throw_sqlite3_exception(JNIEnv* env, int errcode,
                              const char* sqlite3Message, const char* message) {
     const char* exceptionClass;
-    switch (errcode) {
+    switch (errcode & 0xff) { /* mask off extended error code */
         case SQLITE_IOERR:
             exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
             break;
@@ -119,19 +120,15 @@
             break;
     }
 
-    if (sqlite3Message != NULL && message != NULL) {
-        char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3);
-        if (fullMessage != NULL) {
-            strcpy(fullMessage, sqlite3Message);
-            strcat(fullMessage, ": ");
-            strcat(fullMessage, message);
-            jniThrowException(env, exceptionClass, fullMessage);
-            free(fullMessage);
-        } else {
-            jniThrowException(env, exceptionClass, sqlite3Message);
+    if (sqlite3Message) {
+        String8 fullMessage;
+        fullMessage.append(sqlite3Message);
+        fullMessage.appendFormat(" (code %d)", errcode); // print extended error code
+        if (message) {
+            fullMessage.append(": ");
+            fullMessage.append(message);
         }
-    } else if (sqlite3Message != NULL) {
-        jniThrowException(env, exceptionClass, sqlite3Message);
+        jniThrowException(env, exceptionClass, fullMessage.string());
     } else {
         jniThrowException(env, exceptionClass, message);
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9698018..6546fed 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -636,12 +636,6 @@
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signature" />
 
-    <!-- Allows an application to route media output to other devices. -->
-    <permission android:name="android.permission.ROUTE_MEDIA_OUTPUT"
-                android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-                android:label="@string/permlab_route_media_output"
-                android:description="@string/permdesc_route_media_output" />
-
     <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
     <!-- =========================================== -->
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..983c45e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_group_collapse.png b/core/res/res/drawable-hdpi/ic_media_group_collapse.png
new file mode 100644
index 0000000..89abf2c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_group_collapse.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_group_expand.png b/core/res/res/drawable-hdpi/ic_media_group_expand.png
new file mode 100644
index 0000000..d9470b2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_group_expand.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..056c3f17
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_group_collapse.png b/core/res/res/drawable-mdpi/ic_media_group_collapse.png
new file mode 100644
index 0000000..34454ac
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_group_collapse.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_group_expand.png b/core/res/res/drawable-mdpi/ic_media_group_expand.png
new file mode 100644
index 0000000..8ce5a44
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_group_expand.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..cbd039a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_group_collapse.png b/core/res/res/drawable-xhdpi/ic_media_group_collapse.png
new file mode 100644
index 0000000..2fb7428
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_group_collapse.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_group_expand.png b/core/res/res/drawable-xhdpi/ic_media_group_expand.png
new file mode 100644
index 0000000..5755b9d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_group_expand.png
Binary files differ
diff --git a/core/res/res/drawable/item_background_activated_holo_dark.xml b/core/res/res/drawable/item_background_activated_holo_dark.xml
new file mode 100644
index 0000000..9cbf6ab
--- /dev/null
+++ b/core/res/res/drawable/item_background_activated_holo_dark.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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">
+
+    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
+    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_light" />
+    <item android:state_focused="true"  android:state_enabled="false"                              android:drawable="@drawable/list_selector_disabled_holo_light" />
+    <item android:state_focused="true"                                android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
+    <item android:state_focused="false"                               android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
+    <item android:state_focused="true"                                                             android:drawable="@drawable/list_focused_holo" />
+    <item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
+    <item                                                                                          android:drawable="@color/transparent" />
+</selector>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index a666077..356e7cf 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -82,7 +82,7 @@
             android:drawablePadding="4dip"
             />
 
-        <com.android.internal.widget.multiwaveview.MultiWaveView
+        <com.android.internal.widget.multiwaveview.GlowPadView
             android:id="@+id/unlock_widget"
             android:orientation="horizontal"
             android:layout_width="wrap_content"
@@ -94,13 +94,14 @@
             android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
             android:directionDescriptions="@array/lockscreen_direction_descriptions"
             android:handleDrawable="@drawable/ic_lockscreen_handle"
-            android:waveDrawable="@drawable/ic_lockscreen_outerring"
-            android:outerRadius="@dimen/multiwaveview_target_placement_radius"
-            android:snapMargin="@dimen/multiwaveview_snap_margin"
-            android:hitRadius="@dimen/multiwaveview_hit_radius"
-            android:chevronDrawables="@array/lockscreen_chevron_drawables"
-            android:feedbackCount="3"
+            android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+            android:outerRadius="@dimen/glowpadview_target_placement_radius"
+            android:innerRadius="@dimen/glowpadview_inner_radius"
+            android:snapMargin="@dimen/glowpadview_snap_margin"
+            android:feedbackCount="1"
             android:vibrationDuration="20"
+            android:glowRadius="@dimen/glowpadview_glow_radius"
+            android:pointDrawable="@drawable/ic_lockscreen_glowdot"
             />
 
         <!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 17a3c84..cb1cb21 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -82,7 +82,7 @@
             android:layout_alignParentTop="true"
             android:drawablePadding="4dip"/>
 
-        <com.android.internal.widget.multiwaveview.MultiWaveView
+        <com.android.internal.widget.multiwaveview.GlowPadView
             android:id="@+id/unlock_widget"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -94,13 +94,14 @@
             android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
             android:directionDescriptions="@array/lockscreen_direction_descriptions"
             android:handleDrawable="@drawable/ic_lockscreen_handle"
-            android:waveDrawable="@drawable/ic_lockscreen_outerring"
-            android:outerRadius="@dimen/multiwaveview_target_placement_radius"
-            android:snapMargin="@dimen/multiwaveview_snap_margin"
-            android:hitRadius="@dimen/multiwaveview_hit_radius"
-            android:chevronDrawables="@array/lockscreen_chevron_drawables"
-            android:feedbackCount="3"
+            android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+            android:outerRadius="@dimen/glowpadview_target_placement_radius"
+            android:innerRadius="@dimen/glowpadview_inner_radius"
+            android:snapMargin="@dimen/glowpadview_snap_margin"
+            android:feedbackCount="1"
             android:vibrationDuration="20"
+            android:glowRadius="@dimen/glowpadview_glow_radius"
+            android:pointDrawable="@drawable/ic_lockscreen_glowdot"
         />
 
         <!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index 78a01dd..7231ead 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -41,7 +41,6 @@
                 android:layout_height="wrap_content"
                 android:layout_marginLeft="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginBottom="100dip"
                 android:layout_marginRight="64dip"
                 android:layout_alignParentTop="true"
                 android:layout_alignParentLeft="true"/>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 2dcb774..91f65e9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -123,7 +123,7 @@
         android:layout_width="match_parent"
         android:layout_height="302dip">
 
-        <com.android.internal.widget.multiwaveview.MultiWaveView
+        <com.android.internal.widget.multiwaveview.GlowPadView
             android:id="@+id/unlock_widget"
             android:orientation="horizontal"
             android:layout_width="match_parent"
@@ -135,13 +135,14 @@
             android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
             android:directionDescriptions="@array/lockscreen_direction_descriptions"
             android:handleDrawable="@drawable/ic_lockscreen_handle"
-            android:waveDrawable="@drawable/ic_lockscreen_outerring"
-            android:outerRadius="@dimen/multiwaveview_target_placement_radius"
-            android:snapMargin="@dimen/multiwaveview_snap_margin"
-            android:hitRadius="@dimen/multiwaveview_hit_radius"
-            android:chevronDrawables="@array/lockscreen_chevron_drawables"
-            android:feedbackCount="3"
+            android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+            android:outerRadius="@dimen/glowpadview_target_placement_radius"
+            android:innerRadius="@dimen/glowpadview_inner_radius"
+            android:snapMargin="@dimen/glowpadview_snap_margin"
+            android:feedbackCount="1"
             android:vibrationDuration="20"
+            android:glowRadius="@dimen/glowpadview_glow_radius"
+            android:pointDrawable="@drawable/ic_lockscreen_glowdot"
             />
 
         <TextView
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 10ddd1e..8b9d8e4 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -129,24 +129,25 @@
     <Space android:layout_width="64dip" android:layout_rowSpan="7" />
 
     <!-- Column 2 -->
-    <com.android.internal.widget.multiwaveview.MultiWaveView
+    <com.android.internal.widget.multiwaveview.GlowPadView
         android:id="@+id/unlock_widget"
         android:layout_width="302dip"
         android:layout_height="match_parent"
         android:layout_rowSpan="7"
-        android:gravity="center"
+        android:gravity="left|center_vertical"
 
         android:targetDrawables="@array/lockscreen_targets_with_camera"
         android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
         android:directionDescriptions="@array/lockscreen_direction_descriptions"
         android:handleDrawable="@drawable/ic_lockscreen_handle"
-        android:waveDrawable="@drawable/ic_lockscreen_outerring"
-        android:outerRadius="@dimen/multiwaveview_target_placement_radius"
-        android:snapMargin="@dimen/multiwaveview_snap_margin"
-        android:hitRadius="@dimen/multiwaveview_hit_radius"
-        android:chevronDrawables="@array/lockscreen_chevron_drawables"
-        android:feedbackCount="3"
+        android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+        android:outerRadius="@dimen/glowpadview_target_placement_radius"
+        android:innerRadius="@dimen/glowpadview_inner_radius"
+        android:snapMargin="@dimen/glowpadview_snap_margin"
+        android:feedbackCount="1"
         android:vibrationDuration="20"
+        android:glowRadius="@dimen/glowpadview_glow_radius"
+        android:pointDrawable="@drawable/ic_lockscreen_glowdot"
         />
 
     <!-- Music transport control -->
diff --git a/core/res/res/layout/media_route_chooser_layout.xml b/core/res/res/layout/media_route_chooser_layout.xml
new file mode 100644
index 0000000..731c0d0
--- /dev/null
+++ b/core/res/res/layout/media_route_chooser_layout.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical"
+              android:showDividers="middle"
+              android:divider="?android:attr/dividerHorizontal">
+    <LinearLayout android:layout_width="match_parent"
+                  android:layout_height="?android:attr/listPreferredItemHeight"
+                  android:gravity="center_vertical"
+                  android:padding="8dp">
+        <ImageView android:id="@+id/volume_icon"
+                   android:layout_width="48dp"
+                   android:layout_height="48dp"
+                   android:src="@android:drawable/ic_audio_vol"
+                   android:gravity="center"
+                   android:scaleType="center" />
+        <SeekBar android:id="@+id/volume_slider"
+                 android:layout_width="0dp"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:layout_marginLeft="8dp"
+                 android:layout_marginRight="8dp" />
+        <ImageButton android:id="@+id/extended_settings"
+                     android:layout_width="48dp"
+                     android:layout_height="48dp"
+                     android:background="?android:attr/selectableItemBackground"
+                     android:src="@android:drawable/ic_sysbar_quicksettings"
+                     android:visibility="gone" />
+    </LinearLayout>
+    <ListView android:id="@id/list"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content" />
+</LinearLayout>
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
new file mode 100644
index 0000000..ba1aaf2
--- /dev/null
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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="match_parent"
+              android:layout_height="?android:attr/listPreferredItemHeight"
+              android:background="@drawable/item_background_activated_holo_dark"
+              android:gravity="center_vertical">
+
+    <ImageView android:layout_width="56dp"
+               android:layout_height="56dp"
+               android:scaleType="center"
+               android:id="@+id/icon"
+               android:visibility="gone" />
+
+    <LinearLayout android:layout_width="0dp"
+                  android:layout_height="match_parent"
+                  android:layout_weight="1"
+                  android:orientation="vertical"
+                  android:gravity="left|center_vertical"
+                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+
+        <TextView android:id="@android:id/text1"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:ellipsize="marquee"
+                  android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView android:id="@android:id/text2"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:ellipsize="marquee"
+                  android:textAppearance="?android:attr/textAppearanceSmall" />
+    </LinearLayout>
+
+    <com.android.internal.view.ImageButtonNoParentPress
+        android:layout_width="56dp"
+        android:layout_height="56dp"
+        android:id="@+id/expand_button"
+        android:background="?android:attr/selectableItemBackground"
+        android:src="@drawable/ic_media_group_expand"
+        android:scaleType="center"
+        android:visibility="gone" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/media_route_list_item_checkable.xml b/core/res/res/layout/media_route_list_item_checkable.xml
new file mode 100644
index 0000000..d0bffb6
--- /dev/null
+++ b/core/res/res/layout/media_route_list_item_checkable.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<com.android.internal.view.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="?android:attr/listPreferredItemHeight"
+              android:background="?android:attr/selectableItemBackground"
+              android:gravity="center_vertical">
+
+    <ImageView android:layout_width="56dp"
+               android:layout_height="56dp"
+               android:scaleType="center"
+               android:id="@+id/icon"
+               android:visibility="gone" />
+
+    <LinearLayout android:layout_width="0dp"
+                  android:layout_height="match_parent"
+                  android:layout_weight="1"
+                  android:orientation="vertical"
+                  android:gravity="left|center_vertical"
+                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+
+        <TextView android:id="@android:id/text1"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:ellipsize="marquee"
+                  android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView android:id="@android:id/text2"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:ellipsize="marquee"
+                  android:textAppearance="?android:attr/textAppearanceSmall" />
+    </LinearLayout>
+
+    <CheckBox
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="16dp"
+        android:id="@+id/check"
+        android:focusable="false"
+        android:clickable="false" />
+
+</com.android.internal.view.CheckableLinearLayout>
diff --git a/core/res/res/layout/media_route_list_item_collapse_group.xml b/core/res/res/layout/media_route_list_item_collapse_group.xml
new file mode 100644
index 0000000..d605c18
--- /dev/null
+++ b/core/res/res/layout/media_route_list_item_collapse_group.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:background="?android:attr/selectableItemBackground">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/listPreferredItemHeightSmall"
+        android:background="#19ffffff"
+        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:gravity="center_vertical">
+
+        <TextView android:layout_width="0dp"
+                  android:layout_height="wrap_content"
+                  android:layout_weight="1"
+                  android:singleLine="true"
+                  android:ellipsize="marquee"
+                  android:text="@string/media_route_chooser_grouping_done"
+                  android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_media_group_collapse"
+            android:scaleType="center" />
+
+    </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/media_route_list_item_section_header.xml b/core/res/res/layout/media_route_list_item_section_header.xml
new file mode 100644
index 0000000..04bd0ea
--- /dev/null
+++ b/core/res/res/layout/media_route_list_item_section_header.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:paddingTop="16dp">
+    <TextView
+        android:id="@android:id/text1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:background="#19ffffff"
+        android:textStyle="bold"
+        android:textAllCaps="true"
+        android:gravity="center_vertical"
+        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:minHeight="24dp"
+        />
+</FrameLayout>
diff --git a/core/res/res/layout/media_route_list_item_top_header.xml b/core/res/res/layout/media_route_list_item_top_header.xml
new file mode 100644
index 0000000..75decd3
--- /dev/null
+++ b/core/res/res/layout/media_route_list_item_top_header.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceSmall"
+    android:background="#19ffffff"
+    android:textStyle="bold"
+    android:textAllCaps="true"
+    android:gravity="center_vertical"
+    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:minHeight="24dp"
+/>
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index d377882..0b3386b 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -108,9 +108,8 @@
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
-                android:layout_marginBottom="8dp"
+                android:layout_marginBottom="10dp"
                 android:layout_marginRight="8dp"
-                android:layout_marginTop="2dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 android:maxLines="8"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 675bdce..a19bc2b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"vee uit"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksaksies"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Min spasie oor"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tabletbergingspasie raak nou min."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Foon bergingspasie raak laag."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Kanselleer"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokluidsprekers"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-klank"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Stelsel"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f71f35f..d2cb8bc 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -478,7 +478,7 @@
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"የማረጋገጫ የምስጋና የምስክር ወረቀትን ለመጠየቅ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"የአውታረ መረብ ግኑኝነቶችን እይ"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"መተግበሪያው እንደ የትኛዎቹ አውታረ መረቦች እንዳሉ እና እንደተገናኙ ያሉ የአውታረ መረብ ግንኙነቶች መረጃዎችን እንዲያይ ይፈቅድለታል።"</string>
-    <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"ሙሉ የአውታረ መረብ መድረሻ"</string>
+    <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"ሙሉ የአውታረ መረብ መዳረሻ"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"መተግበሪያው የአውታረ መረብ መሰኪያዎችን እንዲፈጥር እና ብጁ የአውታረ መረብ ፕሮቶኮሎችን እንዲጠቀም ይፈቅድለታል። አሳሹ እና ሌሎች መተግበሪያዎች ውሂብ ወደ በይነመረብ የመላኪያ መንገዶችን ስለሚያቀርቡውሂብ ወደ በይነመረብ ለመላክ ይህ ፍቃድ አያስፈልግም።"</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"የአውታረ መረብ ቅንብሮች እና ትራፊክ ለውጥ/ አቋርጥ"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"የአውታረ መረብ ቅንጅቶችን ለመለወጥ እና ለማቋረጥ እና ሁሉንም የአውታረ መረብ ትራፊክ ለመመርመር፤ለምሳሌ ወኪል እና የማንኛውም APN ወደብ ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች ሊቆጣጠሩ፣ አቅጣጫ ሊያስቀይሩ ፣ ወይም ያለአንተ እውቅና የአውታረ መረብ ፓኬቶችን ሊቀይሩ ይችላሉ፡፡"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"ሰርዝ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"ግቤት ሜተድ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"የፅሁፍ እርምጃዎች"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"ቦታ አንሷል"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"የጡባዊ ማከማቻ ቦታ እያነሰ ነው።"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"የስልክ ማከማቻ ቦታ እያነሰ ነው።"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"እሺ"</string>
     <string name="cancel" msgid="6442560571259935130">"ይቅር"</string>
     <string name="yes" msgid="5362982303337969312">"እሺ"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"የትከል ድምፅ ማጉያዎች"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ድምጽ"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"ስርዓት"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b9595d1..aea32a8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"طريقة الإرسال"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"إجراءات النص"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"المساحة منخفضة"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"انخفضت مساحة تخزين الجهاز اللوحي."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"مساحة تخزين الهاتف منخفضة."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"موافق"</string>
     <string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
     <string name="yes" msgid="5362982303337969312">"موافق"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"مكبرات صوت للإرساء"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"صوت HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"النظام"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b68761b..bfe0e27 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"выдаліць"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метад уводу"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дзеянні з тэкстам"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Мала месца"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"На планшэце застаецца мала памяці."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"На тэлефоне мала памяці."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"ОК"</string>
     <string name="cancel" msgid="6442560571259935130">"Адмяніць"</string>
     <string name="yes" msgid="5362982303337969312">"ОК"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Дынамікі станцыi"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-аўдыёвыхад"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Сістэма"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 80a38e1..a972258 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"изтриване"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод на въвеждане"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Действия с текста"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Мястото не достига"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Мястото в хранилището на таблета намалява."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Мястото в хранилището на телефона намалява."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Отказ"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Докинг станц.: Високогов."</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI аудио"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f7dbb47..8f8fb1d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -361,15 +361,15 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"modificació targeta contacte"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet que l\'aplicació pugui canviar o afegir informació del perfil personal emmagatzemada al dispositiu, com ara el teu nom i la teva informació de contacte. Això significa que l\'aplicació et pot identificar i enviar la informació del teu perfil a altres persones."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"llegeix el teu tauler d\'activitat social"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet que l\'aplicació accedeixi i sincronitzi actualitzacions socials teves i dels teus amics. Vés amb compte en compartir informació: això permet que l\'aplicació llegeix comunicacions entre tu i els teus amics a les xarxes socials, independentment de la confidencialitat. Nota: És possible que aquest permís no s\'apliqui a totes les xarxes socials."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet que l\'aplicació accedeixi i sincronitzi actualitzacions socials teves i dels teus amics. Vés amb compte en compartir informació: això permet que l\'aplicació llegeixi comunicacions entre tu i els teus amics a les xarxes socials, independentment de la confidencialitat. Nota: És possible que aquest permís no s\'apliqui a totes les xarxes socials."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escriu al tauler d\'activitat social"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permet que l\'aplicació mostri actualitzacions socials dels teus amics. Vés amb compte en compartir informació: això permet que l\'aplicació produeixi missatges que pot semblar que provinguin d\'un amic. Nota: És possible que aquest permís no s\'apliqui a totes les xarxes socials."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"llegeix els esdeveniments del calendari més informació confidencial"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permet que l\'aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta, inclosos els dels amics o dels companys de feina. Aquesta acció pot permetre que l\'aplicació comparteixi o desi les dades del teu calendari, sense tenir en compte la confidencialitat."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permet que l\'aplicació llegeixi tots els esdeveniments del calendari emmagatzemats al telèfon, inclosos els dels amics o dels companys de feina. Aquesta acció pot permetre que l\'aplicació comparteixi o desi les dades del teu calendari, sense tenir en compte la confidencialitat."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"afegeix o modifica els esdeveniments del calendari i envia correus electrònics als clients sense el coneixement dels propietaris"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permet que l\'aplicació afegeixi, elimini o canviï esdeveniments que pots modificar a la tauleta, inclosos d\'amics o de companys de feina. Aquesta acció pot permetre que l\'aplicació enviï missatges que sembli que provinguin dels propietaris del calendari o que modifiqui esdeveniments sense el coneixement dels propietaris."</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permet que l\'aplicació afegeixi, elimini o canviï esdeveniments que pots modificar al telèfon, inclosos d\'amics o de companys de feina. Aquesta acció pot permetre que l\'aplicació enviï missatges que sembli que provinguin dels propietaris del calendari o que modifiqui esdeveniments sense el coneixement dels propietaris."</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permet que l\'aplicació afegeixi, elimini o canviï esdeveniments que pots modificar a la tauleta, inclosos els d\'amics o de companys de feina. Aquesta acció pot permetre que l\'aplicació enviï missatges que sembli que provinguin dels propietaris del calendari o que modifiqui esdeveniments sense el coneixement dels propietaris."</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permet que l\'aplicació afegeixi, elimini o canviï esdeveniments que pots modificar al telèfon, inclosos els d\'amics o de companys de feina. Aquesta acció pot permetre que l\'aplicació enviï missatges que sembli que provinguin dels propietaris del calendari o que modifiqui esdeveniments sense el coneixement dels propietaris."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"crear orígens d\'ubicacions fictícies per fer proves"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Crea fonts d\'ubicació fictícies per provar o per instal·lar un proveïdor d\'ubicació nou. Aquesta acció permet que l\'aplicació substitueixi la ubicació o l\'estat que retornen altres fonts d\'ubicació, com ara el GPS o altres proveïdors d\'ubicació."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accedir a ordres del proveïdor d\'ubicació addicionals"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"suprimeix"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Queda poc espai"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"L\'espai d\'emmagatzematge de la tauleta comença a ser escàs."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Comença a quedar poc espai d\'emmagatzematge al telèfon."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"D\'acord"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
     <string name="yes" msgid="5362982303337969312">"D\'acord"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus del connector"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Àudio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f3b927a..35f0480 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"smazat"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metoda zadávání dat"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operace s textem"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Málo paměti"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"V tabletu zbývá málo místa pro ukládání dat."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"V telefonu zbývá málo místa pro ukládání dat."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Zrušit"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvuk HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 8a68f54..6bc5f9f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"slet"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inputmetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Der er ikke så meget plads tilbage"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Der er næsten ikke mere plads på tabletcomputeren."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Der er næsten ikke mere plads på telefonen."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuller"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1036,7 +1037,7 @@
     <string name="sms_control_no" msgid="625438561395534982">"Afvis"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile netværk er utilgængeligt, indtil du genstarter med et gyldigt SIM-kort."</string>
-    <string name="sim_done_button" msgid="827949989369963775">"Udfør"</string>
+    <string name="sim_done_button" msgid="827949989369963775">"Afslut"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kort blev tilføjet"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Genstart din enhed for at få adgang til mobilnetværket."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Genstart"</string>
@@ -1127,7 +1128,7 @@
     <string name="ime_action_search" msgid="658110271822807811">"Søg"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Send"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Næste"</string>
-    <string name="ime_action_done" msgid="8971516117910934605">"Udfør"</string>
+    <string name="ime_action_done" msgid="8971516117910934605">"Afslut"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"Forrige"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Udfør"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Ring til nummer"\n"ved hjælp af <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockstationens højttalere"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-lyd"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 25c1bf9..2bd623b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -639,7 +639,7 @@
     <string name="emailTypeMobile" msgid="119919005321166205">"Mobil"</string>
     <string name="postalTypeCustom" msgid="8903206903060479902">"Benutzerdefiniert"</string>
     <string name="postalTypeHome" msgid="8165756977184483097">"Privat"</string>
-    <string name="postalTypeWork" msgid="5268172772387694495">"Geschäftlich"</string>
+    <string name="postalTypeWork" msgid="5268172772387694495">"Büro"</string>
     <string name="postalTypeOther" msgid="2726111966623584341">"Sonstige"</string>
     <string name="imTypeCustom" msgid="2074028755527826046">"Benutzerdefiniert"</string>
     <string name="imTypeHome" msgid="6241181032954263892">"Privat"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"Löschen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Eingabemethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textaktionen"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Geringer Speicher"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Kaum noch Tablet-Speicher frei"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Kaum noch Telefonspeicher frei"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Abbruch"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock-Lautsprecher"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-Audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1392d9d..9f50ca3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"διαγραφή"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Μέθοδος εισόδου"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ενέργειες κειμένου"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Απομένει λίγος ελεύθερος χώρος"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Έχει απομείνει λίγος ελεύθερος αποθηκευτικός χώρος στο tablet."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Έχει απομείνει λίγος ελεύθερος αποθηκευτικός χώρος στο τηλέφωνο."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Ακύρωση"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Ηχεία βάσης σύνδεσης"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Ήχος HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Σύστημα"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5837e50..1386ad5 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"delete"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Input method"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Text actions"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Low on space"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tablet storage space is getting low."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Phone storage space is getting low."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6b56b5c..c58b08e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -209,7 +209,7 @@
     <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Permite que la aplicación envíe mensajes SMS, lo que puede generar cargos inesperados. Las aplicaciones malintencionadas pueden causarte gastos imprevistos al enviar mensajes sin tu confirmación."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"leer tus mensajes de texto (SMS o MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Permite que la aplicación consulte los mensajes SMS almacenados en la tableta o en la tarjeta SIM. La aplicación puede utilizar este permiso para leer todos los mensajes SMS, independientemente de cuál sea su contenido o su nivel de confidencialidad."</string>
-    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite que la aplicación consulte los mensajes SMS almacenados en el teléfono o en la tarjeta SIM. La aplicación puede utilizar este permiso para leer todos los mensajes SMS, independientemente de cuál sea su contenido o su nivel de confidencialidad."</string>
+    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite que la aplicación consulte los mensajes SMS almacenados en el dispositivo o en la tarjeta SIM. La aplicación puede utilizar este permiso para leer todos los mensajes SMS, independientemente de cuál sea su contenido o su nivel de confidencialidad."</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"editar tus mensajes de texto (SMS o MMS)"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Permite que la aplicación escriba en mensajes SMS almacenados en tu tableta o tarjeta SIM. Las aplicaciones maliciosas pueden eliminar tus mensajes."</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permite que la aplicación escriba en mensajes SMS almacenados en tu dispositivo o tarjeta SIM. Las aplicaciones maliciosas pueden eliminar tus mensajes."</string>
@@ -302,7 +302,7 @@
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que la aplicación haga que algunas de sus partes se mantengan persistentes en la memoria. Esto puede limitar la memoria disponible para otras aplicaciones y ralentizar la tableta."</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Permite que la aplicación haga que algunas de sus partes se mantengan persistentes en la memoria. Esto puede limitar la memoria disponible para otras aplicaciones y ralentizar el teléfono."</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Permite que la aplicación haga que algunas de sus partes se mantengan persistentes en la memoria. Esto puede limitar la memoria disponible para otras aplicaciones y ralentizar el dispositivo."</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"eliminar aplicaciones"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Permite que la aplicación elimine paquetes de Android. Las aplicaciones maliciosas pueden utilizar este permiso para eliminar aplicaciones importantes."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"eliminar datos de otras aplicaciones"</string>
@@ -343,16 +343,16 @@
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Permite que la aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el dispositivo tarde más en inicializarse y que la aplicación ralentice el funcionamiento general del dispositivo al estar en ejecución constante."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar emisiones pegajosas"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar la tableta o hacer que funcione de manera inestable al forzarla a utilizar mucha memoria."</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar el teléfono o hacer que funcione de manera inestable al forzarlo a utilizar mucha memoria."</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar el dispositivo o hacer que funcione de manera inestable al forzarlo a utilizar mucha memoria."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"leer tus contactos"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite que la aplicación consulte información sobre los contactos almacenados en la tableta, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite que la aplicación consulte información sobre contactos almacenados en el teléfono, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite que la aplicación consulte información sobre los contactos almacenados en la tableta, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite que la aplicación consulte información sobre contactos almacenados en el dispositivo, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modificar tus contactos"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite que la aplicación modifique los datos de los contactos almacenados en la tableta, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite que la aplicación modifique los datos de los contactos almacenados en el teléfono, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite que la aplicación modifique los datos de los contactos almacenados en la tableta, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite que la aplicación modifique los datos de los contactos almacenados en el dispositivo, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"leer el registro de llamadas"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite que la aplicación consulte el registro de llamadas de la tableta, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones pueden utilizar este permiso para guardar los datos del registro de llamadas, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite que la aplicación consulte el registro de llamadas del teléfono, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones pueden utilizar este permiso para guardar los datos del registro de llamadas, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite que la aplicación consulte el registro de llamadas del dispositivo, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones pueden utilizar este permiso para guardar los datos del registro de llamadas, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"escribir en el registro de llamadas"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite que la aplicación modifique el registro de llamadas de la tableta, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite que la aplicación modifique el registro de llamadas del dispositivo, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas."</string>
@@ -366,10 +366,10 @@
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permite que la aplicación muestre actualizaciones de las redes sociales de tus amigos. Ten cuidado al compartir información, ya que la aplicación puede generar mensajes que parezcan proceder de amigos. Nota: Este permiso no se puede utilizar en todas las redes sociales."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"Leer eventos de calendario e información confidencial"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite que la aplicación consulte todos los eventos de calendario almacenados en la tableta, incluidos los de amigos y compañeros de trabajo. La aplicación puede utilizar este permiso para compartir o guardar datos del calendario del usuario sin tener en cuenta si son privados o confidenciales."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite que la aplicación consulte todos los eventos de calendario almacenados en el teléfono, incluidos los de amigos y compañeros de trabajo. La aplicación puede utilizar este permiso para compartir o guardar los datos del calendario sin tener en cuenta si son privados o confidenciales."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite que la aplicación consulte todos los eventos de calendario almacenados en el dispositivo, incluidos los de amigos y compañeros de trabajo. La aplicación puede utilizar este permiso para compartir o guardar los datos del calendario sin tener en cuenta si son privados o confidenciales."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"Agregar o modificar los eventos de calendario y enviar un correo a los invitados sin que los propietarios lo sepan"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite que la aplicación agregue, elimine y cambie eventos que se pueden modificar en la tableta, incluidos los de amigos o compañeros de trabajo. La aplicación puede utilizar este permiso para enviar mensajes que parezcan proceder de propietarios de un calendario o para modificar eventos sin el consentimiento de los propietarios."</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite que la aplicación agregue, elimine y cambie eventos que se pueden modificar en el teléfono, incluidos los de amigos o compañeros de trabajo. La aplicación puede utilizar este permiso para enviar mensajes que parezcan proceder de propietarios de un calendario o para modificar los eventos sin el consentimiento de los propietarios."</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite que la aplicación agregue, elimine y cambie eventos que se pueden modificar en el dispositivo, incluidos los de amigos o compañeros de trabajo. La aplicación puede utilizar este permiso para enviar mensajes que parezcan proceder de propietarios de un calendario o para modificar los eventos sin el consentimiento de los propietarios."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"crear fuentes de ubicación de prueba"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Esto autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acceder a comandos adicionales del proveedor del lugar"</string>
@@ -378,7 +378,7 @@
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ubicación exacta (GPS)"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) de la tableta. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) del teléfono. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) del dispositivo. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
     <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ubicación aproximada (basada en red)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Permite acceder a la ubicación aproximada a través de proveedores de ubicación que utilizan fuentes de conexión como torres de telefonía móvil y redes Wi-Fi. Cuando estos servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación aproximada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acceder a SurfaceFlinger"</string>
@@ -469,7 +469,7 @@
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Permite que la aplicación haga llamadas a los autenticadores de cuentas."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"buscar cuentas en el dispositivo"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Permite que la aplicación obtenga una lista de las cuentas reconocidas por la tableta, entre las que se pueden incluir las cuentas creadas por las aplicaciones que hayas instalado."</string>
-    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite que la aplicación obtenga una lista de las cuentas reconocidas por el teléfono, entre las que se pueden incluir las cuentas creadas por las aplicaciones que hayas instalado."</string>
+    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite que la aplicación obtenga una lista de las cuentas reconocidas por el dispositivo, entre las que se pueden incluir las cuentas creadas por las aplicaciones que hayas instalado."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"crear cuentas y establecer contraseñas"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Permite que la aplicación utilice las capacidades del autenticador de cuentas del administrador de cuentas, incluida la creación de cuentas y la obtención y configuración de sus contraseñas."</string>
     <string name="permlab_manageAccounts" msgid="4983126304757177305">"agregar o eliminar cuentas"</string>
@@ -489,31 +489,31 @@
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"cambiar la configuración del uso de datos del fondo"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permite que la aplicación cambe la configuración de uso de los datos de referencia."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"ver conexiones Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite que la aplicación vea información sobre la conexión a redes Wi-Fi, por ejemplo, si la conexión Wi-Fi está habilitada y cuál es el nombre de los dispositivos Wi-Fi conectados."</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite que la aplicación vea información sobre la conexión a redes Wi-Fi, por ejemplo, si la conexión Wi-Fi está activada y cuál es el nombre de los dispositivos Wi-Fi conectados."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"conectarse y desconectarse de la red Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite que la aplicación se conecte a puntos de acceso Wi-Fi y se desconecte de ellos, y que realice modificaciones en la configuración de las redes Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepción de multidifusión Wi-Fi"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo a la tableta. Utiliza más batería que el modo de no multidifusión."</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo al teléfono. Utiliza más batería que el modo de no multidifusión."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo a la tableta. Utiliza más batería que el modo que no es de multidifusión."</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo a tu dispositivo. Utiliza más batería que el modo que no es de multidifusión."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acceder a la configuración de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure la tableta Bluetooth local y descubra y se sincronice con dispositivos remotos."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que la aplicación configure el dispositivo Bluetooth local y descubra y se sincronice con dispositivos remotos."</string>
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ver conexiones WiMAX"</string>
-    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que la aplicación determine si está habilitada la conexión WiMAX y que obtenga información sobre las redes WiMAX que están conectadas."</string>
+    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que la aplicación determine si está activada la conexión WiMAX y que obtenga información sobre las redes WiMAX que están conectadas."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar el estado de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte la tableta a una red WiMAX y que la desconecte de ella."</string>
-    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el teléfono a una red WiMAX y que lo desconecte de ella."</string>
+    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el dispositivo a una red WiMAX y que lo desconecte de ella."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación vea la configuración de Bluetooth de la tableta y que cree y acepte conexiones con los dispositivos sincronizados."</string>
-    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación vea la configuración de Bluetooth del teléfono y que cree y acepte conexiones con los dispositivos sincronizados."</string>
+    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación vea la configuración de Bluetooth del dispositivo y que cree y acepte conexiones con los dispositivos sincronizados."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar la Transmisión de datos en proximidad"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivar el bloqueo de pantalla"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que la aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Por ejemplo, el teléfono puede inhabilitar el bloqueo del teclado cuando recibe una llamada telefónica y volver a habilitarlo cuando finaliza la llamada."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que la aplicación desactive el bloqueo del teclado y cualquier protección con contraseña asociada. Por ejemplo, el dispositivo puede desactivar el bloqueo del teclado cuando recibe una llamada telefónica y volver a activarlo cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Este permiso permite que la aplicación consulte la configuración de sincronización de una cuenta. Esto permite, por ejemplo, determinar si la aplicación Personas está sincronizada con una cuenta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar y desactivar la sincronización"</string>
-    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Permite que la aplicación modifique la configuración de sincronización de una cuenta. Este permiso se puede utilizar, por ejemplo, para habilitar la sincronización de la aplicación Personas con una cuenta."</string>
+    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Permite que la aplicación modifique la configuración de sincronización de una cuenta. Este permiso se puede utilizar, por ejemplo, para activar la sincronización de la aplicación Personas con una cuenta."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"leer estadística de sincronización"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Permite que la aplicación consulte las estadísticas de sincronización de una cuenta, por ejemplo, el historial de eventos sincronizados y la cantidad de datos sincronizados."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"leer canales suscritos"</string>
@@ -787,7 +787,7 @@
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Permite que la aplicación consulte el historial de todas las URL visitadas por el navegador, y todos sus marcadores. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"escribir marcadores web e historial"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en la tableta. La aplicación puede utilizar este permiso para borrar o modificar datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en el teléfono. La aplicación puede utilizar este permiso para borrar o modificar los datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en el dispositivo. La aplicación puede utilizar este permiso para borrar o modificar los datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"programar una alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Poco espacio de almacenamiento"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Está quedando poco espacio de almacenamiento en el tablet."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Hay poco espacio de almacenamiento en el dispositivo."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Aceptar"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="yes" msgid="5362982303337969312">"Aceptar"</string>
@@ -1284,9 +1285,11 @@
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Siempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Solo una vez"</string>
     <string name="default_audio_route_name" product="tablet" msgid="6890731863195399186">"Altavoces de la tableta"</string>
-    <string name="default_audio_route_name" product="default" msgid="4551396562363128432">"Altavoz del teléfono"</string>
+    <string name="default_audio_route_name" product="default" msgid="4551396562363128432">"Altavoz del dispositivo"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index eb3b2be..127abb5 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada de texto"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Poco espacio"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Se está agotando el espacio de almacenamiento del tablet."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Se está agotando el espacio de almacenamiento del teléfono."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Aceptar"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="yes" msgid="5362982303337969312">"Aceptar"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 1822650..6266353 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"kustuta"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sisestusmeetod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoimingud"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Vähe ruumi"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tahvelarvuti mäluruumi hakkab väheks jääma."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Telefonimälu hakkab väheks jääma."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Tühista"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doki kõlarid"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI heli"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Süsteem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 0373fc7..fcfbc0f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -194,7 +194,7 @@
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"گسترش دادن/جمع کردن نوار وضعیت"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"به برنامه اجازه می‎دهد تا نوار ابزار را جمع کند یا باز کند."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ترسیم مجدد مسیر تماس‌های خروجی"</string>
-    <string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"به برنامه اجازه می‎دهد تماس‌های خروجی را پردازش کند و شماره‎هایی که باید گرفته شوند را تغییر دهد. این مجوز به برنامه امکان می‌دهد به کنترل، هدایت یا جلوگیری از تماس‌های خروجی بپردازد."</string>
+    <string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"به برنامه اجازه می‎دهد تماس‌های خروجی را پردازش کند و شماره‎هایی که باید گرفته شوند را تغییر دهد. این مجوز به برنامه امکان می‌دهد به کنترل، هدایت مجدد یا جلوگیری از تماس‌های خروجی بپردازد."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"دریافت پیام‌های نوشتاری (پیامک)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"به برنامه اجازه می‌دهد پیامک‌ها را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"دریافت پیام‌های نوشتاری (MMS)"</string>
@@ -204,9 +204,9 @@
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"خواندن پیام‌های پخش سلولی"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"به برنامه اجازه می‎دهد پیامهای پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی تحویل داده می‎شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‎شود، ممکن است برنامه‎های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"ارسال پیامک ها"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌های را برای شما ایجاد کنند."</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"ارسال پیامک بدون تأیید"</string>
-    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌های را برای شما ایجاد کنند."</string>
+    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"خواندن پیام‌های نوشتاری شما (پیامک یا MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در رایانه لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آنها بخواند."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در تلفن یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آنها بخواند."</string>
@@ -220,7 +220,7 @@
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"بازیابی جزئیات برنامه‌های در حال اجرا"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"به برنامه اجازه می‎دهد تا اطلاعات مفصلی مربوط به کارهایی که در حال حاضر و اخیراً اجرا می‎شوند را بازیابی کند. برنامه‎های مخرب می‎توانند اطلاعات شخصی مربوط به برنامه‎های دیگر را پیدا کنند."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"تنظیم مجدد ترتیب برنامه‎های در حال اجرا"</string>
-    <string name="permdesc_reorderTasks" msgid="7734217754877439351">"به برنامه اجازه می‎دهد تا کارها را به پیش‌زمینه و پس‌زمینه منتقل کند. برنامه‎ ممکن است بدون ورودی شما این کار را انجام دهد."</string>
+    <string name="permdesc_reorderTasks" msgid="7734217754877439351">"به برنامه اجازه می‎دهد تا کارها را به پیش‌زمینه و پس‌زمینه منتقل کند. برنامه‎ ممکن است بدون دخالت شما این کار را انجام دهد."</string>
     <string name="permlab_removeTasks" msgid="6821513401870377403">"متوقف کردن برنامه‎های در حال اجرا"</string>
     <string name="permdesc_removeTasks" msgid="1394714352062635493">"به برنامه اجازه می‎دهد تا کارها را حذف کند و برنامه‎های آنها را متوقف کند. برنامه‎های مخرب می‌توانند در اجرای برنامه‎های دیگر اختلال ایجاد ‎کنند."</string>
     <string name="permlab_startAnyActivity" msgid="2918768238045206456">"شروع هر نوع فعالیت"</string>
@@ -345,8 +345,8 @@
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانه لوحی شود."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری تلفن شود."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"خواندن مخاطبین شما"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری با افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"اصلاح مخاطبین شما"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
@@ -359,23 +359,23 @@
     <string name="permlab_readProfile" msgid="4701889852612716678">"خواندن کارت تماس شما"</string>
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را به دیگران ارسال کند."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را برای دیگران ارسال کنند."</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را برای دیگران ارسال کند."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه می‌دهد به به‌روزرسانی‌های اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آنها را همگام‌سازی کند. دقت کنید که هنگام اشتراک‌گذاری -- این ویژگی به برنامه اجازه می‌دهد ارتباطات بین شما و دوستان شما را در شبکه‌های اجتماعی، صرفنظر از محرمانگی آنها بخواند. توجه: این مجوز ممکن است در همه شبکه‌های اجتماعی اجرا نشود."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه می‌دهد به به‌روزرسانی‌های اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آنها را همگام‌سازی کند. دقت کنید که هنگام اشتراک‌گذاری -- این ویژگی به برنامه اجازه می‌دهد ارتباطات بین شما و دوستان شما را در شبکه‌های اجتماعی، صرفنظر از محرمانه بودن آنها بخواند. توجه: این مجوز ممکن است در همه شبکه‌های اجتماعی اجرا نشود."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"به برنامه اجازه می‌دهد به‌روزرسانی‌های اجتماعی از طرف دوستان شما را نمایش دهد. دقت کنید هنگام اشتراک‌گذاری اطلاعات -- این ویژگی به برنامه اجازه می‌دهد پیام‌هایی را که به نظر می‌رسد از طرف یکی از دوستان شما باشد ایجاد کند. توجه: این مجوز در همه شبکه‌های اجتماعی قابل اجرا نمی‌باشد."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"خواندن رویدادهای تقویم به همراه اطلاعات محرمانه"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آنها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در تلفن شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آنها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال ایمیل به مهمانان بدون دخالت مالک"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانه لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهند. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهند. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانه لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"منابع مکان کاذب برای تست"</string>
-    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS و ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
+    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"دسترسی به فرمان های بیشتر ارائه دهنده مکان"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"به برنامه اجازه می‎دهد تا به فرمان‌های ارائه‎دهنده موقعیت مکانی دیگری دسترسی داشته باشد. این ویژگی ممکن است باعث مختل شدن عملکرد GPS یا دیگر منابع موقعیت مکانی توسط این برنامه شود."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string>
-    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS و ارائه‌دهندگان موقعیت مکانی را نادیده بگ"</string>
+    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"موقعیت مکانی دقیق (GPS)"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در رایانه لوحی خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در تلفن خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
@@ -441,7 +441,7 @@
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"اصلاح کردن حالت تلفن"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"به برنامه اجازه می‎دهد ویژگیهای دستگاه را کنترل کند. برنامه‎ای که این مجوز را دارد می‎تواند بدون اطلاع شما تعویض شبکه داشته باشد، رادیوی تلفن را روشن یا خاموش کند و کارهایی از این قبیل را انجام دهد."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه می‌دهد به ویژگی‌های تلفن دستگاه شما دسترسی بپدا کند. این مجوز به برنامه اجازه می‌دهد شماره تلفن و شناسه‌های دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه می‌دهد به ویژگی‌های تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه می‌دهد شماره تلفن و شناسه‌های دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانه لوحی"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"به برنامه اجازه می‎دهد تا از غیرفعال شدن رایانه لوحی جلوگیری کند."</string>
@@ -493,8 +493,8 @@
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"اتصال به Wi-Fi و قطع اتصال از آن"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"به برنامه اجازه می‎دهد تا به نقاط دسترسی Wi-Fi وصل شود و ارتباط خود را با آنها قطع کند و تغییراتی را در پیکربندی دستگاه برای شبکه‎های Wi-Fi ایجاد کند."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"دریافت چندگانه Wi-Fi را مجاز می کند"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانه لوحی شما بپردازند. این از قدرت بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به تلفن شما بپردازند. این از قدرت بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانه لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه می‎دهد تا رایانه لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها جفت شود."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاههای راه دور را پیدا کند و با آنها جفت شود."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"عملکردهای متنی"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"فضا کم است"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"فضای ذخیره رایانه لوحی در حال کم شدن است."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"فضای ذخیره سازی تلفن در حال کم شدن است."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"تأیید"</string>
     <string name="cancel" msgid="6442560571259935130">"لغو"</string>
     <string name="yes" msgid="5362982303337969312">"تأیید"</string>
@@ -1080,8 +1081,8 @@
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"همه فایلهای ذخیره شده در حافظه USB پاک خواهد شد. این عمل را نمی‎توان برگرداند!"</string>
     <string name="extmedia_format_message" product="default" msgid="14131895027543830">"تمام اطلاعات روی کارت شما از بین می‎رود."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"قالب"</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"رفع عیب USB متصل شد"</string>
-    <string name="adb_active_notification_message" msgid="1016654627626476142">"غیرفعال کردن اشکال زدایی USB را لمس کنید."</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"اتصال رفع عیب USB"</string>
+    <string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string>
     <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روش‌های ورودی"</string>
     <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه کلید فیزیکی"</string>
@@ -1119,8 +1120,8 @@
     <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"به برنامه اجازه می‎دهد آمار جمع‎آوری شده کاربرد قطعه را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"کپی کردن محتوا"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"به برنامه اجازه می‎دهد تا سرویس پیش فرض را فراخوانی کند و محتوا را کپی کند. برای استفاده برنامه‎های عادی مورد نیاز نیست."</string>
-    <string name="permlab_route_media_output" msgid="1642024455750414694">"ترسیم مسیر خروجی رسانه"</string>
-    <string name="permdesc_route_media_output" msgid="4932818749547244346">"به یک برنامه اجازه می‌دهد خروجی رسانه را در دستگاه‌های خارجی دیگر ترسیم مسیر کند."</string>
+    <string name="permlab_route_media_output" msgid="1642024455750414694">"تعیین مسیر خروجی رسانه"</string>
+    <string name="permdesc_route_media_output" msgid="4932818749547244346">"به یک برنامه اجازه می‌دهد خروجی رسانه را به دستگاه‌های خارجی دیگر تعیین مسیر کند."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"دوبار لمس کنید تا بزرگنمایی کنترل شود"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"افزودن ابزارک انجام نشد."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"برو"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه اتصال"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"صدای HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"سیستم"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 742f425..5888acf 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -934,9 +934,8 @@
     <string name="deleteText" msgid="7070985395199629156">"poista"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Syöttötapa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoiminnot"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Tila vähissä"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tablet-laitteen tallennustila on vähissä."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Puhelimen tallennustila on vähissä."</string>
+    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Tallennustila loppumassa"</string>
+    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Kaikki järjestelmätoiminnot eivät välttämättä toimi"</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Peruuta"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1288,5 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Telineen kaiuttimet"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-ääni"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Järjestelmä"</string>
+    <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 233e3fe..99c7627 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"supprimer"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mode de saisie"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Actions sur le texte"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Espace disponible faible"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"La mémoire de la tablette est bientôt pleine."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"La mémoire du téléphone commence à être pleine."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index bb458a5..dbb3878 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"हटाएं"</string>
     <string name="inputMethod" msgid="1653630062304567879">"इनपुट विधि"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"पाठ क्रियाएं"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"स्‍थान की कमी"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"टेबलेट संग्रहण स्‍थान कम हो रहा है."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"फ़ोन संग्रहण स्‍थान कम हो रहा है."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"ठीक"</string>
     <string name="cancel" msgid="6442560571259935130">"रद्द करें"</string>
     <string name="yes" msgid="5362982303337969312">"ठीक"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डॉक स्‍पीकर"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ऑडियो"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्‍टम"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e5a096e..dbe54ea 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -196,9 +196,9 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"preusmjeravanje odlaznih poziva"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"Aplikaciji omogućuje obradu odlaznih poziva i promjenu broja za biranje. Ta dozvola aplikaciji omogućuje nadziranje, preusmjeravanje ili sprječavanje odlaznih poziva."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"primanje tekstnih poruka (SMS)"</string>
-    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogućuje primanje i obradu SMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj a da vam ih ne prikaže."</string>
+    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogućuje primanje i obradu SMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstnih poruka (MMS)"</string>
-    <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj a da vam ih ne prikaže."</string>
+    <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"primanje hitnih odašiljanja"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Omogućuje aplikaciji primanje i obradu poruka hitnih odašiljanja. Ta je dozvola dostupna samo aplikacijama sustava."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string>
@@ -214,7 +214,7 @@
     <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Omogućuje aplikaciji pisanje u SMS poruke pohranjene na vašem tabletnom računalu ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Omogućuje aplikaciji pisanje u SMS poruke pohranjene na telefonu ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"primanje tekstnih poruka (WAP)"</string>
-    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogućuje primanje i obradu WAP poruka. Ta dozvola uključuje mogućnost nadziranja ili brisanja vama poslanih poruka a da vam ih ne prikaže."</string>
+    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogućuje primanje i obradu WAP poruka. Ta dozvola uključuje mogućnost nadziranja ili brisanja vama poslanih poruka, a da vam ih ne prikaže."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"dohvaćanje pokrenutih aplikacija"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Aplikaciji omogućuje dohvaćanje informacija o trenutačnim i nedavnim tekućim zadacima. To aplikaciji može omogućiti otkrivanje informacija o tome koje se aplikacije upotrebljavaju na uređaju."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dohvaćanje pojedinosti o pokrenutim aplikacijama"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje s tekstom"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Prostora ima sve manje"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Prostora za pohranjivanje na tabletnom uređaju ima sve manje."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Prostora za pohranjivanje na telefonu ima sve manje."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"U redu"</string>
     <string name="cancel" msgid="6442560571259935130">"Odustani"</string>
     <string name="yes" msgid="5362982303337969312">"U redu"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici postolja"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sustav"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 1f83a18..79e3119 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"törlés"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Beviteli mód"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Műveletek szöveggel"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Kevés a hely"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"A táblagép tárhelye kezd elfogyni."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Kevés a szabad tárhely a telefonban."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Mégse"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkolóegység hangszórója"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audió"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Rendszer"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 79fa856..28cc099 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -388,9 +388,9 @@
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
-    <string name="permdesc_recordAudio" msgid="4906839301087980680">"Memungkinkan aplikasi merekam audio dengan mikrofon. Izin ini memungkinkan aplikasi merekam audio kapan pun tanpa konfirmasi Anda."</string>
+    <string name="permdesc_recordAudio" msgid="4906839301087980680">"Memungkinkan aplikasi merekam audio dengan mikrofon. Izin ini memungkinkan aplikasi merekam audio kapan saja tanpa konfirmasi Anda."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
-    <string name="permdesc_camera" msgid="8497216524735535009">"Memungkinkan aplikasi mengambil gambar dan video dengan kamera. Izin ini memungkinkan aplikasi menggunakan kamera setiap saat tanpa konfirmasi Anda."</string>
+    <string name="permdesc_camera" msgid="8497216524735535009">"Memungkinkan aplikasi mengambil gambar dan video dengan kamera. Izin ini memungkinkan aplikasi menggunakan kamera kapan saja tanpa konfirmasi Anda."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"noaktifkan tablet secara permanen"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"nonaktifkan ponsel secara permanen"</string>
     <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"Mengizinkan apl menonaktifkan seluruh tablet secara permanen. Ini sangat berbahaya."</string>
@@ -501,8 +501,8 @@
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Lihat sambungan WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang tersambung."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Ubah status WiMAX"</string>
-    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Memungkinkan aplikasi menyambung tablet ke dan memutus tablet dari jaringan WiMAX."</string>
-    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Memungkinkan aplikasi menyambung ke dan memutus ponsel dari jaringan WiMAX."</string>
+    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string>
+    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"sandingkan dengan perangkat Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"hapus"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metode masukan"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Ruang penyimpanan tinggal sedikit"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang penyimpanan tablet semakin sedikit."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Ruang penyimpanan ponsel tersisa sedikit."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Oke"</string>
     <string name="cancel" msgid="6442560571259935130">"Batal"</string>
     <string name="yes" msgid="5362982303337969312">"Oke"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pengeras suara dok"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1bcd98f..bf7a168 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -204,9 +204,9 @@
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lettura di messaggi cell broadcast"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le applicazioni dannose potrebbero interferire con il rendimento o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"invio SMS"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"Consente all\'applicazione di inviare messaggi SMS. Ciò potrebbe comportare costi imprevisti. Le applicazioni dannose potrebbero generare dei costi inviando messaggi senza la tua conferma."</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"Consente all\'applicazione di inviare messaggi SMS. Ciò potrebbe comportare costi imprevisti. Applicazioni dannose potrebbero generare dei costi inviando messaggi senza la tua conferma."</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"invio di messaggi SMS senza conferma"</string>
-    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Consente all\'applicazione di inviare messaggi SMS. Ciò potrebbe comportare costi imprevisti. Le applicazioni dannose potrebbero generare dei costi inviando messaggi senza la tua conferma."</string>
+    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Consente all\'applicazione di inviare messaggi SMS. Ciò potrebbe comportare costi imprevisti. Applicazioni dannose potrebbero generare dei costi inviando messaggi senza la tua conferma."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"lettura messaggi di testo personali (SMS o MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Consente all\'applicazione di leggere i messaggi SMS memorizzati sul tablet o sulla scheda SIM. Ciò consente all\'applicazione di leggere tutti i messaggi SMS, indipendentemente dai contenuti o dal livello di riservatezza."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Consente all\'applicazione di leggere i messaggi SMS memorizzati sul telefono o sulla scheda SIM. Ciò consente all\'applicazione di leggere tutti i messaggi SMS, indipendentemente dai contenuti o dal livello di riservatezza."</string>
@@ -301,8 +301,8 @@
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"invio segnali Linux alle applicazioni"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Consente all\'applicazione di richiedere l\'invio del segnale fornito a tutti i processi persistenti."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"esecuzione permanente delle applicazioni"</string>
-    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Consente all\'applicazione di rendere persistenti in memoria delle sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il tablet."</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Consente all\'applicazione di rendere persistenti in memoria delle sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il telefono."</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Consente all\'applicazione di rendere persistenti in memoria alcune sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il tablet."</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Consente all\'applicazione di rendere persistenti in memoria alcune sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il telefono."</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"eliminazione applicazioni"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Consente all\'applicazione di eliminare pacchetti Android. Le applicazioni dannose potrebbero farne uso per eliminare applicazioni importanti."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"eliminazione dati di altre applicazioni"</string>
@@ -345,14 +345,14 @@
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Consente all\'applicazione di inviare broadcast permanenti, che permangono anche al termine del broadcast. Un uso eccessivo potrebbe rendere il tablet lento o instabile causando un uso eccessivo della memoria."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Consente all\'applicazione di inviare broadcast permanenti, che permangono anche al termine del broadcast. Un uso eccessivo potrebbe rendere il telefono lento o instabile causando un uso eccessivo della memoria."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"lettura contatti personali"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul tablet, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e le applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul telefono, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e le applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul tablet, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul telefono, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modifica dei contatti personali"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul tablet, incluse la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul telefono, incluse la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul tablet, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul telefono, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"lettura del registro chiamate"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Consente all\'applicazione di leggere il registro chiamate del tablet, inclusi i dati sulle chiamate in arrivo e in uscita. Questa autorizzazione consente alle applicazioni di salvare i dati del tuo registro chiamate e le applicazioni dannose potrebbero condividere i dati del registro chiamate a tua insaputa."</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Consente all\'applicazione di leggere il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Questa autorizzazione consente alle applicazioni di salvare i dati del tuo registro chiamate e le applicazioni dannose potrebbero condividere i dati del registro chiamate a tua insaputa."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Consente all\'applicazione di leggere il registro chiamate del tablet, inclusi i dati sulle chiamate in arrivo e in uscita. Questa autorizzazione consente alle applicazioni di salvare i dati del tuo registro chiamate e applicazioni dannose potrebbero condividere i dati del registro chiamate a tua insaputa."</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Consente all\'applicazione di leggere il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Questa autorizzazione consente alle applicazioni di salvare i dati del tuo registro chiamate e applicazioni dannose potrebbero condividere i dati del registro chiamate a tua insaputa."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"scrittura del registro chiamate"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Consente all\'applicazione di modificare il registro chiamate del tablet, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Consente all\'applicazione di modificare il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate."</string>
@@ -426,7 +426,7 @@
     <string name="permlab_hardware_test" msgid="4148290860400659146">"esecuzione test hardware"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"Consente all\'applicazione di controllare varie periferiche per il test dell\'hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"chiamata diretta n. telefono"</string>
-    <string name="permdesc_callPhone" msgid="3740797576113760827">"Consente all\'applicazione di chiamare numeri di telefono senza il tuo intervento. Ciò può comportare chiamate o addebiti imprevisti. Tieni presente che ciò non consente all\'applicazione di chiamare numeri di emergenza. Le applicazioni dannose potrebbero generare dei costi effettuando chiamate senza la tua conferma."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"Consente all\'applicazione di chiamare numeri di telefono senza il tuo intervento. Ciò può comportare chiamate o addebiti imprevisti. Tieni presente che ciò non consente all\'applicazione di chiamare numeri di emergenza. Applicazioni dannose potrebbero generare dei costi effettuando chiamate senza la tua conferma."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"chiamata diretta di tutti i n. telefono"</string>
     <string name="permdesc_callPrivileged" msgid="1689024901509996810">"Consente all\'applicazione di chiamare qualsiasi numero di telefono, inclusi i numeri di emergenza, senza il tuo intervento. Le applicazioni dannose potrebbero effettuare chiamate non necessarie e illegali verso i servizi di emergenza."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"avvio diretto della configurazione del tablet CDMA"</string>
@@ -515,7 +515,7 @@
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"attivazione e disattivazione della sincronizzazione"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Consente a un\'applicazione di modificare le impostazioni di sincronizzazione per un account. Ad esempio, può servire per attivare la sincronizzazione dell\'applicazione Persone con un account."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"lettura statistiche di sincronizz."</string>
-    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Consente a un\'applicazione di leggere le statistiche di sincronizzazione per un account, inclusse la cronologia degli eventi di sincronizzazione e la quantità di dati sincronizzati."</string>
+    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Consente a un\'applicazione di leggere le statistiche di sincronizzazione per un account, incluse la cronologia degli eventi di sincronizzazione e la quantità di dati sincronizzati."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lettura feed sottoscritti"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Consente all\'applicazione di ottenere dettagli sui feed attualmente sincronizzati."</string>
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"scrittura feed sottoscritti"</string>
@@ -934,9 +934,8 @@
     <string name="deleteText" msgid="7070985395199629156">"elimina"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodo inserimento"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Azioni testo"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Spazio in esaurimento"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Spazio di archiviazione del tablet in esaurimento."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Spazio di archiviazione del telefono in esaurimento."</string>
+    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spazio di archiviazione in esaurimento"</string>
+    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Alcune funzioni di sistema potrebbero non funzionare"</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Annulla"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1120,7 +1119,7 @@
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"copia di contenuti"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Consente all\'applicazione di richiamare il servizio container predefinito per la copia di contenuti. Da non usare per normali applicazioni."</string>
     <string name="permlab_route_media_output" msgid="1642024455750414694">"Indirizzamento uscita media"</string>
-    <string name="permdesc_route_media_output" msgid="4932818749547244346">"Consente a un\'applicazione di indirizzare l\'uscita media verso altri dispositivi esterni."</string>
+    <string name="permdesc_route_media_output" msgid="4932818749547244346">"Consente a un\'applicazione di indirizzare l\'uscita di media verso altri dispositivi esterni."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tocca due volte per il comando dello zoom"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Aggiunta del widget non riuscita."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Vai"</string>
@@ -1289,4 +1288,5 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlanti dock"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fine"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a491b86..880cc9d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"מחק"</string>
     <string name="inputMethod" msgid="1653630062304567879">"שיטת קלט"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"פעולות טקסט"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"חסר שטח"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"שטח האחסון בטבלט עומד להיגמר."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"שטח האחסון בטלפון הולך ואוזל."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"אישור"</string>
     <string name="cancel" msgid="6442560571259935130">"ביטול"</string>
     <string name="yes" msgid="5362982303337969312">"אישור"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"רמקולים של מעגן"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"אודיו HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"מערכת"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 553b1dd..eb3d96f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"削除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"入力方法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"テキスト操作"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"空き容量低下"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"タブレットのストレージ空き容量が少なくなっています。"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"携帯電話の空き容量が少なくなっています。"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"キャンセル"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ホルダーのスピーカー"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMIオーディオ"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"システム"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index df84ad8..d345c91 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"삭제"</string>
     <string name="inputMethod" msgid="1653630062304567879">"입력 방법"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"텍스트 작업"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"저장공간 부족"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"태블릿 저장공간이 부족합니다."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"휴대전화 저장공간이 부족합니다."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"확인"</string>
     <string name="cancel" msgid="6442560571259935130">"취소"</string>
     <string name="yes" msgid="5362982303337969312">"확인"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"도크 스피커"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 오디오"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"시스템"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 7095c02..f2df3fa 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <!-- Resources for MultiWaveView in LockScreen -->
+    <!-- Resources for GlowPadView in LockScreen -->
     <array name="lockscreen_targets_when_silent">
         <item>@null</item>"
         <item>@drawable/ic_lockscreen_unlock</item>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0a03730..319aca7 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"ištrinti"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Įvesties būdas"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksto veiksmai"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Mažai vietos"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Mažėja planšetinio kompiuterio atmintinės vietos."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Sparčiai mažėja vietos telefono saugykloje."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Gerai"</string>
     <string name="cancel" msgid="6442560571259935130">"Atšaukti"</string>
     <string name="yes" msgid="5362982303337969312">"Gerai"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doko garsiakalbiai"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI garsas"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b6b0976..8839657 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"dzēst"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Ievades metode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksta darbības"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Maz brīvas vietas"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Planšetdatora krātuve ir gandrīz pilna."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Tālruņa krātuvē kļūst maz vietas."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Labi"</string>
     <string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
     <string name="yes" msgid="5362982303337969312">"Labi"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doka skaļruņi"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistēma"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 2eb296b..41f8521 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -301,8 +301,8 @@
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"hantar isyarat Linux kepada apl"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Membenarkan apl meminta isyarat yang dibekalkan dihantar kepada semua proses yang berterusan."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"buatkan apl sentiasa berjalan"</string>
-    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Membenarkan apl untuk membuat sebahagian dari dirinya berterusan dalam memori. Ini boleh menghadkan memori yang tersedia kepada apl lain menjadikan tablet perlahan."</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Membenarkan apl untuk membuat sebahagian dari dirinya berterusan dalam memori. Ini boleh menghadkan memori yang tersedia kepada apl lain menjadikan telefon perlahan."</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Membenarkan apl untuk membuat sebahagian dirinya berterusan dalam memori. Ini boleh mengehadkan memori yang tersedia kepada apl lain dan menjadikan tablet perlahan."</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Membenarkan apl untuk membuat sebahagian dari dirinya berterusan dalam memori. Ini boleh mengehadkan memori yang tersedia kepada apl lain dan menjadikan telefon perlahan."</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"padam apl"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Membenarkan apl untuk memadam pakej Android. Apl hasad boleh menggunakannya untuk memadam apl penting."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"padamkan data apl lain"</string>
@@ -342,7 +342,7 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Membenarkan apl untuk memulakan dirinya sendiri sebaik sahaja sistem selesai mengebut. Ini boleh membuat masa untuk menghidupkan tablet menjadi lebih lama dan membenarkan apl untuk memperlahankan keseluruhan tablet dengan sentiasa berjalan."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Membenarkan apl bermula sendiri sebaik sahaja sistem telah selesai mengebut. Ini boleh menjadikannya mengambil masa yang lama untuk menghidupkan telefon dan membenarkan apl untuk melambatkan keseluruhan telefon dengan sentiasa berjalan."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"hantar siaran lekit"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Membenarkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Penggunaan berlebihan boleh membuat tablet perlahan atau tidak stabil dengan menyebabkannya menggunakan memori yang terlalu banyak."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Membenarkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Penggunaan berlebihan boleh membuatkan tablet perlahan atau tidak stabil kerana menggunakan terlalu banyak memori."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Membenarkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Penggunaan berlebihan boleh membuat telefon perlahan atau tidak stabil dengan menyebabkannya menggunakan memori yang terlalu banyak."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"baca kenalan anda"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan di tablet anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dalam cara lain dengan individu tertentu. Kebenaran ini membenarkan apl untuk menyimpan data kenalan anda dan apl hasad boleh berkongsi data kenalan anda tanpa pengetahuan anda."</string>
@@ -351,8 +351,8 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada tablet anda, termasuk kekerapan siapa anda panggil, hantar e-mel atau berkomunikasi dalam cara lain dengan kenalan tertentu. Kebenaran ini membenarkan apl untuk memadam data kenalan."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada telefon anda, termasuk kekerapan siapa anda panggil, hantar e-mel atau berkomunikasi dalam cara lain dengan kenalan tertentu. Kebenaran ini membenarkan apl untuk memadam data kenalan."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"baca log panggilan"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Membenarkan apl  membaca log panggilan tablet anda, termasuk data tentang panggilan masuk dan keluar. Kebenaran ini membenarkan apl untuk menyimpan data log panggilan anda dan apl hasad boleh berkongsi data panggilan tanpa pengetahuan anda."</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Membenarkan apl  membaca log panggilan telefon anda, termasuk data tentang panggilan masuk dan keluar. Kebenaran ini membenarkan apl untuk menyimpan data log panggilan anda dan apl hasad boleh berkongsi data panggilan tanpa pengetahuan anda."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Membenarkan apl membaca log panggilan tablet anda, termasuk data tentang panggilan masuk dan keluar. Kebenaran ini membenarkan apl untuk menyimpan data log panggilan anda dan apl hasad boleh berkongsi data panggilan tanpa pengetahuan anda."</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Membenarkan apl membaca log panggilan telefon anda, termasuk data tentang panggilan masuk dan keluar. Kebenaran ini membenarkan apl untuk menyimpan data log panggilan anda dan apl hasad boleh berkongsi data panggilan tanpa pengetahuan anda."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"tulis log panggilan"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Membenarkan apl untuk mengubah suai panggilan tablet anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk memadam atau mengubah suai log panggilan anda."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Membenarkan apl untuk mengubah suai panggilan telefon anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk memadam atau mengubah suai log panggilan anda."</string>
@@ -371,11 +371,11 @@
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Membenarkan apl menambah, mengalih keluar, mengubah acara yang anda boleh ubah suai pada tablet anda, termasuk milik rakan atau rakan sekerja. Ini boleh membenarkan apl menghantar mesej yang kelihatan seperti datang dari pemilik kalendar atau mengubah suai acara tanpa pengetahuan pemilik."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Membenarkan apl menambah, mengalih keluar, mengubah acara yang anda boleh ubah suai pada telefon anda, termasuk milik rakan atau rakan sekerja. Ini boleh membenarkan apl menghantar mesej yang kelihatan seperti datang dari pemilik kalendar atau mengubah suai acara tanpa pengetahuan pemilik."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"gunakan sumber lokasi olok-olok untuk pengujian"</string>
-    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk mengatasi lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
+    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk membatalkan lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"akses perintah tambahan pembekal lokasi"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Membenarkan apl untuk mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"kebenaran untuk memasang pembekal lokasi"</string>
-    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk mengatasi lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
+    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk membatalkan lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"lokasi (GPS) tepat"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Akses sumber lokasi yang tepat seperti Sistem Kedudukan Global pada tablet. Apabila perkhidmatan lokasi tersedia dan dihidupkan, kebenaran ini membenarkan apl menentukan lokasi tepat anda."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Akses sumber lokasi yang tepat seperti Sistem Kedudukan Global pada telefon. Apabila perkhidmatan lokasi tersedia dan dihidupkan, kebenaran ini membenarkan apl menentukan lokasi tepat anda."</string>
@@ -468,8 +468,8 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"bertindak sebagai PerkhidmatanPengurusAkaun"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Membenarkan apl membuat panggilan ke Pengesah Akaun."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"cari akaun pada peranti"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Membenarkan apl mendapatkan senarai akaun yang dikenali oleh tablet. Ini mungkin termasuk sebarang akaun yang dibuat oleh aplikasi yang anda telah pasang."</string>
-    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Membenarkan apl mendapatkan senarai akaun yang dikenali oleh telefon. Ini mungkin termasuk sebarang akaun yang dibuat oleh aplikasi yang anda telah pasang."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Membenarkan apl mendapatkan senarai akaun yang dikenali oleh tablet. Ini mungkin termasuk sebarang akaun yang dibuat oleh aplikasi yang telah anda pasang."</string>
+    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Membenarkan apl mendapatkan senarai akaun yang dikenali oleh telefon. Ini mungkin termasuk sebarang akaun yang dibuat oleh aplikasi yang telah anda pasang."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"buat akaun dan tetapkan kata laluan"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Membenarkan apl menggunakan kebolehan pengesah akaun Pengurus Akaun, termasuk membuat akaun dan mendapatkan serta menetapkan kata laluannya."</string>
     <string name="permlab_manageAccounts" msgid="4983126304757177305">"tambah atau alih keluar akaun"</string>
@@ -493,8 +493,8 @@
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"sambung dan putuskan dari Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Membenarkan apl menyambung ke dan memutuskan sambungan dari titik capaian Wi-Fi dan membuat perubahan kepada konfigurasi peranti untuk rangkaian Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"benarkan penerimaan Wi-Fi Multisiar"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Membenarkan apl menerima paket yang dihantar kepada semua peranti pada rangkaian Wi-Fi menggunakan alamat berbilang acuan, bukan hanya tablet anda. Ia menggunakan lebih kuasa berbanding mod bukan berbilang acuan."</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Membenarkan apl menerima paket yang dihantar kepada semua peranti pada rangkaian Wi-Fi menggunakan alamat berbilang acuan, bukan hanya telefon anda. Ia menggunakan lebih kuasa berbanding mod bukan berbilang acuan."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Membenarkan apl menerima paket yang dihantar kepada semua peranti pada rangkaian Wi-Fi menggunakan alamat multisiar, bukan hanya tablet anda. Apl menggunakan lebih kuasa berbanding mod bukan multisiar."</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Membenarkan apl menerima paket yang dihantar kepada semua peranti pada rangkaian Wi-Fi menggunakan alamat multisiar, bukan hanya telefon anda. Ia menggunakan lebih kuasa berbanding mod bukan multisiar."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"akses tetapan Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Membenarkan apl mengkonfigurasikan tablet Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Membenarkan apl mengkonfigurasikan telefon Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
@@ -504,7 +504,7 @@
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Membenarkan apl untuk menyambungkan tablet ke dan menyahsambungkan tablet dari rangkaian WiMaX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Membenarkan apl untuk menyambungkan telefon ke dan menyahsambung telefon dari rangkaian WiMaX."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"berpasangan dengan peranti Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat dan menerima sambungan dengan peranti yang dipasangkan."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Membenarkan apl melihat konfigurasi Bluetooth pada telefon dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"mengawal Komunikasi Medan Dekat"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Membenarkan apl berkomunikasi dengan teg, kad dan pembaca Komunikasi Medan Dekat (NFC)."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"padam"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Kaedah input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Kekurangan ruang"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang storan tablet semakin rendah."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Ruang simpanan telefon semakin habis."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Batal"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pembesar suara dok"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 37884fd..24d8497 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -204,9 +204,9 @@
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lesing av kringkastede meldinger"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødsituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"sende SMS-meldinger"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"Lar appen sende tekstmeldinger. Dette kan resultere i uventede kostnader. Skadelige apper kan koste deg penger ved å sende meldinger uten bekreftelse fra deg."</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"Lar appen sende tekstmeldinger. Dette kan resultere i uventede kostnader. Merk at skadelige apper kan påføre deg kostnader ved å sende meldinger uten bekreftelse fra deg."</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"send tekstmeldinger uten godkjenning"</string>
-    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Lar appen sende tekstmeldinger. Dette kan resultere i uventede kostnader. Skadelige apper kan koste deg penger ved å sende meldinger uten bekreftelse fra deg."</string>
+    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Lar appen sende tekstmeldinger. Dette kan resultere i uventede kostnader. Merk at skadelige apper kan påføre deg kostnader ved å sende meldinger uten bekreftelse fra deg."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"leser tekstmeldinger (SMS eller MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Lar appen lese tekstmeldinger lagret på nettbrettet eller SIM-kortet ditt. Dette lar appen lese alle tekstmeldingene dine, uavhengig av innhold og konfidensialitet."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Lar appen lese tekstmeldinger lagret på telefonen eller SIM-kortet ditt. Dette lar appen lese alle tekstmeldingene dine, uavhengig av innhold og konfidensialitet."</string>
@@ -342,17 +342,17 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Lar appen starte seg selv så snart systemet har startet opp. Dette kan føre til lengre oppstartstid for nettbrettet, i tillegg til at nettbrettet kan bli generelt tregere av at appen alltid kjører."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Lar appen starte seg selv så snart systemet har startet opp. Dette kan føre til lengre oppstartstid for telefonen, i tillegg til at telefonen kan bli generelt tregere av at appen alltid kjører."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"sende varige kringkastinger"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Lar appen sende hengende kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre nettbrettet tregt eller ustabilt ved å bruke for mye minne."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Lar appen sende faste kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre nettbrettet tregt eller ustabilt ved å bruke for mye minne."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Lar appen sende faste kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre telefonen treg eller ustabil ved å bruke for mye minne."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"leser kontaktene dine"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Lar appen lese informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til, eller på andre måter kommunisert med andre personer. Denne tillatelsen lar apper lagre kontaktdata og skadelige apper kan dele disse dataene uten at du vet om det."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Lar appen lese informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med andre personer. Denne tillatelsen lar apper lagre kontaktdata, og skadelige apper kan dele disse dataene uten at du vet om det."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Lar appen lese informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til, eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Lar appen lese informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"endrer kontaktene dine"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Lar appen endre informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Lar appen endre informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"lar appen lese anropsloggen"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Lar appen lese samtaleloggen på nettbrettet ditt. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din, og skadelige apper kan dele informasjonen uten at du har samtykket."</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Lar appen lese samtaleloggen på telefonen din. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din, og skadelige apper kan dele informasjonen uten at du har samtykket."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Lar appen lese samtaleloggen på nettbrettet ditt. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din. Merk at skadelige apper kan dele informasjonen uten at du har samtykket."</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Lar appen lese samtaleloggen på telefonen din. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din. Merk at skadelige apper kan dele informasjonen uten at du har samtykket."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"lar appen endre samtaleloggen"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Lar appen endre nettbrettets samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Lar appen endre telefonens samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din."</string>
@@ -361,9 +361,9 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"endrer ditt eget kontaktkort"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lar appen endre eller legge til personlig profilinformasjon som er lagret på enheten din, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lese din sosiale strøm"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lar appen lese og synkronisere sosiale oppdateringer fra deg selv og vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lese kommunikasjon mellom deg og vennene dine på sosiale nettverk, uavhengig av konfidensialitet. Vær oppmerksom på at denne tillatelsen kanskje ikke brukes på alle sosiale nettverk."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lar appen lese og synkronisere sosiale oppdateringer fra deg selv og vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lese kommunikasjon mellom deg og vennene dine på sosiale nettverk, uavhengig av konfidensialitet. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder for alle sosiale nettverk."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrive i din sosiale strøm"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Lar appen vise sosiale oppdateringer fra vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lage meldinger som ser ut som om de kommer fra en venn. Vær oppmerksom på at denne tillatelsen kanskje ikke brukes på alle sosiale nettverk."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Lar appen vise sosiale oppdateringer fra vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lage meldinger som ser ut som om de kommer fra en venn. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder på alle sosiale nettverk."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"les kalenderhendelser og konfidensiell informasjon"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Lar appen lese alle kalenderaktivitetene lagret på nettbrettet ditt, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen deler eller lagrer kalenderinformasjonen din uavhengig av konfidensialitet og sensitivitet."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Lar appen lese alle kalenderaktivitetene lagret på telefonen din, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen deler eller lagrer kalenderinformasjonen din uavhengig av konfidensialitet og sensitivitet."</string>
@@ -373,20 +373,20 @@
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"lage simulerte posisjonskilder for testing"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"få tilgang til ekstra posisjonskommandoer"</string>
-    <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lar appen bruke flere kommandoer fra posisjonsangivere. Dette kan gjøre at appen forstyrrer GPS-funksjonen eller andre posisjonskilder."</string>
+    <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lar appen få tilgang til flere kommandoer fra posisjonsangivere. Dette kan gjøre at appen forstyrrer GPS-funksjonen eller andre posisjonskilder."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"installere posisjonskilder"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"nøyaktig (GPS) posisjon"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Bruke kilder for nøyaktig posisjon på nettbrettet ditt, slik som Global Positioning System (GPS). Når posisjonstjenester er er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Bruke kilder for nøyaktig posisjon på telefonen din, slik som Global Positioning System (GPS). Når posisjonstjenester er er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Bruke kilder for nøyaktig posisjon på nettbrettet ditt, slik som Global Positioning System (GPS). Når posisjonstjenester er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Bruke kilder for nøyaktig posisjon på telefonen din, slik som Global Positioning System (GPS). Når posisjonstjenester er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
     <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"omtrentlig (nettverksbasert) posisjon"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Få omtrentlig posisjon fra posisjonsangivere ved bruk av nettverkskilder, slik som telefonmaster og Wi-Fi. Når disse posisjonstjenestene er er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den omtrentlige posisjonen din."</string>
+    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Få omtrentlig posisjon fra posisjonsangivere ved bruk av nettverkskilder, slik som telefonmaster og Wi-Fi. Når disse posisjonstjenestene er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den omtrentlige posisjonen din."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få tilgang til SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Lar appen bruke grunnleggende SurfaceFlinger-funksjoner."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lese skjermbufferet"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Lar appen lese innholdet i rammebufferen."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"endre lydinnstillinger"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydutdata."</string>
+    <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ta opp lyd"</string>
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"Lar appen ta opp lyd med mikrofonen. Dette betyr at appen kan ta opp lyd når som helst uten at du har bedt om det."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ta bilder og videoer"</string>
@@ -426,7 +426,7 @@
     <string name="permlab_hardware_test" msgid="4148290860400659146">"teste maskinvare"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"Lar appen styre ulike eksterne enheter for å teste maskinvare."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"ringe telefonnummer direkte"</string>
-    <string name="permdesc_callPhone" msgid="3740797576113760827">"Lar appen ringe telefonnumre uten at du gjør noe. Dette kan resultere i uventede oppringninger og kostnader. Appen kan ikke ringe nødnumre, men skadelige apper kan koste deg penger ved å ringe uten bekreftelse fra deg."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"Lar appen ringe telefonnumre uten at du gjør noe. Dette kan resultere i uventede oppringninger og kostnader. Appen kan imidlertid ikke ringe nødnumre. Merk at skadelige apper kan påføre deg kostnader ved å ringe uten bekreftelse fra deg."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"ringe vilkårlige telefonnummer direkte"</string>
     <string name="permdesc_callPrivileged" msgid="1689024901509996810">"Lar appen ringe alle slags telefonnumre, deriblant nødnumre, uten din innvirkning. Ondsinnede apper kan foreta unødvendige og ulovlige anrop til nødtjenestene."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"start CDMA-nettbrettoppsett direkte"</string>
@@ -468,7 +468,7 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"fungere som kontoadministrasjonstjenesten"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Lar appen foreta anrop til kontoautentiseringstjenester."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"finner kontoer på enheten"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Lar appen hente listen over kontoene nettbrettet kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert"</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Lar appen hente listen over kontoene nettbrettet kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Lar appen hente listen over kontoene telefonen kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"oppretter kontoer og angir passord"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Lar appen bruke kontoadministratoren sine rettigheter til kontoautentisering, herunder oppretting av kontoer samt innhenting og angivelse av passord."</string>
@@ -479,7 +479,7 @@
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ser nettverkstilkoblinger"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Lar appen se informasjon om nettverkstilkoblinger, slik som hvilke nettverk som finnes og er tilkoblet."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"full nettverkstilgang"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Lar appen opprette nettverkskontakter og bruke tilpassede nettverksprotokoller. Nettleseren og andre apper gjør det mulig å sende data til Internett, så denne tillatelsen er ikke nødvendig for å sende data til Internett."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Lar appen opprette nettverkskontakter og bruke tilpassede nettverksprotokoller. Nettleseren og andre apper gjør det mulig å sende data til Internett, så denne tillatelsen er ikke nødvendig for å kunne sende data til Internett."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"endre eller avskjær nettverksinnstillinger og -trafikk"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Lar appen endre nettverksinnstillinger og avbryte eller undersøke all nettverkstrafikk, for eksempel for å endre mellomtjener og port for alle navn på tilgangspunkt (APN). Ondsinnede apper kan overvåke, viderekoble eller endre nettverkspakker uten at du vet om det."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"endre nettverkskonnektivitet"</string>
@@ -499,9 +499,9 @@
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Lar appen konfigurere det lokale Bluetooth-nettbrettet, samt oppdage og koble sammen med eksterne enheter."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Lar appen konfigurere den lokale Bluetooth-telefonen, samt oppdage og koble sammen med eksterne enheter."</string>
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"ser WiMAX-tilkoblinger"</string>
-    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Lar appen kan avgjøre hvorvidt WiMAX er aktivert og finne informasjon om eventuelle tilkoblede WiMAX-nettverk."</string>
+    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Lar appen avgjøre hvorvidt WiMAX er aktivert og finne informasjon om eventuelle tilkoblede WiMAX-nettverk."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Endre WiMAX-status"</string>
-    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverket."</string>
+    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverk."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lar appen koble telefonen til og fra WiMAX-nettverk."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"kobler til Bluetooth-enheter"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
@@ -509,7 +509,7 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"kontroller overføring av data med NFC-teknologi"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Lar appen kommunisere med etiketter, kort og lesere som benytter NFC-teknologi."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktiverer skjermlåsen"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel på dette er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slår synkronisering av og på"</string>
@@ -784,10 +784,10 @@
     <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"leser nettbokmerkene og nettloggen din"</string>
-    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Lar appen lese loggen for alle nettadressene nettleseren har besøkt, og alle bokmerkene i nettleseren. Vær oppmerksom på at denne tillatelsen kanskje ikke brukes av tredjepartsnettlesere eller andre apper med egenskaper for nettsurfing."</string>
+    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Lar appen lese loggen for alle nettadressene nettleseren har besøkt, og alle bokmerkene i nettleseren. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"skriver nettbokmerker og nettlogg"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Lar appen endre nettleserens logg eller bokmerker lagret på nettbrettet ditt. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke brukes av tredjepartsnettlesere eller andre apper med egenskaper for nettsurfing."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lar appen endre nettleserens logg eller bokmerker lagret på telefonen din. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke brukes av tredjepartsnettlesere eller andre apper med egenskaper for nettsurfing."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Lar appen endre nettleserens logg eller bokmerker lagret på nettbrettet ditt. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lar appen endre nettleserens logg eller bokmerker lagret på telefonen din. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"angir alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"legg til talepost"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"slett"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inndatametode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Lite plass"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Lite lagringsplass igjen på nettbrettet."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Det begynner å bli lite lagringsplass på telefonen."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkhøyttalere"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-lyd"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 566b33e..fb5e365 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -501,8 +501,8 @@
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX-verbindingen weergeven"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-status wijzigen"</string>
-    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Hiermee kan de app verbinding maken met de tablet en de verbinding met WiMAX-netwerken verbreken."</string>
-    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Hiermee kan de app verbinding maken met WiMAX-netwerken en de verbinding met deze netwerken verbreken."</string>
+    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
+    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Hiermee kan de app de telefoon verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"koppelen met Bluetooth-apparaten"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Hiermee kan de app de Bluetooth-configuratie van de tablet bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Hiermee kan de app de Bluetooth-configuratie van de telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"verwijderen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstacties"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Weinig ruimte"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Opslagruimte van tablet raakt op."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Opslagruimte van telefoon raakt op."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuleren"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockluidsprekers"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systeem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a18ca48..8bd9b91 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"usuń"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sposób wprowadzania tekstu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Działania na tekście"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Mało miejsca"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Pamięć tabletu wkrótce zostanie zapełniona."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Maleje ilość dostępnej pamięci telefonu."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Anuluj"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Głośniki stacji dokującej"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Dźwięk przez HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index cfde7d8..1e2687d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -216,7 +216,7 @@
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"receber mensagens de texto (WAP)"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que a aplicação receba e processe mensagens WAP. Esta autorização inclui a capacidade de monitorizar ou eliminar mensagens enviadas para si sem as apresentar."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"obter aplicações em execução"</string>
-    <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que a aplicação recupere informações acerca de tarefas executadas atualmente e recentemente. Pode permitir que a aplicação descubra informações acerca de quais as aplicações utilizadas no dispositivo."</string>
+    <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que a aplicação recupere informações acerca de tarefas executadas atual e recentemente. Isto pode permitir que a aplicação descubra informações acerca de quais as aplicações utilizadas no dispositivo."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"obter detalhes das aplicações em execução"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite à aplicação obter informações detalhadas sobre tarefas atualmente em execução e recentemente executadas. As aplicações maliciosas poderão descobrir informações privadas de outras aplicações."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar as aplicações em execução"</string>
@@ -357,30 +357,30 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite à aplicação modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite à aplicação modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"ler o próprio cartão de contacto"</string>
-    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que a aplicação leia dados de perfil pessoais guardos no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
+    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que a aplicação leia dados de perfil pessoais guardados no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modificar o próprio cartão de contacto"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que a aplicação altere ou adicione dados de perfil pessoais guardados no dispositivo, como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que a aplicação altere ou adicione dados de perfil pessoais guardados no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler o seu fluxo social"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que a aplicação aceda e sincronize atualizações de redes sociais suas e dos seus amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação leia comunicações entre si e os seus amigos nas redes sociais, independentemente do grau de confidencialidade. Nota: esta autorização pode não ser aplicada em todas as redes sociais."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que a aplicação aceda e sincronize atualizações de redes sociais suas e dos seus amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação leia comunicações entre si e os seus amigos nas redes sociais, independentemente do grau de confidencialidade. Nota: esta autorização pode não ser aplicada a todas as redes sociais."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever para o seu fluxo social"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permite que a aplicação apresente atualizações de redes sociais de amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação produza mensagens que podem parecer ser enviadas por um amigo. Nota: esta autorização pode não ser aplicada em todas as redes sociais."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permite que a aplicação apresente atualizações de redes sociais de amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação produza mensagens que podem parecer ser enviadas por um amigo. Nota: esta autorização pode não ser aplicada a todas as redes sociais."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"ler eventos do calendário, para além de informações confidenciais"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite que a aplicação leia todos os eventos do calendário guardados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou sensibilidade."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite que a aplicação leia todos os eventos do calendário guardados no telemóvel, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou sensibilidade."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite que a aplicação leia todos os eventos do calendário guardados no telemóvel, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou da sensibilidade."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"adicionar ou modificar eventos do calendário e enviar e-mail a convidados sem o conhecimento dos proprietários"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite que a aplicação adicione, remova e altere eventos que pode modificar no tablet, incluindo eventos relacionados com amigos ou colegas de trabalho. Pode permitir que a aplicação envie mensagens que parecem ser enviadas pelos proprietários dos calendários ou modifique eventos sem o conhecimento do proprietário."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite que a aplicação adicione, remova e altere eventos que pode modificar no telemóvel, incluindo eventos relacionados com amigos ou colegas de trabalho. Pode permitir que a aplicação envie mensagens que parecem ser enviadas pelos proprietários dos calendários ou modifique eventos sem o conhecimento do proprietário."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"fontes de localização fictícias para teste"</string>
-    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Criar fontes de localização fictícias para fins de teste ou instalar um novo fornecedor de localização. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização, como, por exemplo, GPS ou fornecedores de localização."</string>
+    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Criar fontes de localização fictícias para fins de teste ou instalar um novo fornecedor de localização. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização como, por exemplo, GPS ou fornecedores de localização."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"aceder a comandos adicionais do fornecedor de localização"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Isto pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um fornecedor de localização"</string>
-    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização fictícias para fins de teste ou instalar um fornecedor de localização novo. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização, como, por exemplo, GPS ou fornecedores de localização."</string>
+    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização fictícias para fins de teste ou instalar um fornecedor de localização novo. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização como, por exemplo, GPS ou fornecedores de localização."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"localização exata (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Aceder a fontes de localização precisas, como o Sistema de Posicionamento Global do tablet. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Aceder a fontes de localização precisas, como o Sistema de Posicionamento Global do telemóvel. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Aceder a fontes de localização precisas, tais como o Sistema de Posicionamento Global do tablet. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Aceder a fontes de localização precisas, tais como o Sistema de Posicionamento Global do telemóvel. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
     <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"localização aproximada (baseada na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Aceder à localização aproximada a partir de fornecedores de localização utilizando fontes de rede como antenas de telemóvel e Wi-Fi. Quando estes serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização aproximada do utilizador."</string>
+    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Aceder à localização aproximada a partir de fornecedores de localização utilizando fontes de rede, tais como antenas de telemóvel e Wi-Fi. Quando estes serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização aproximada do utilizador."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"aceder a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite à aplicação utilizar funcionalidades de SurfaceFlinger de nível inferior."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"ler memória intermédia de fotogramas"</string>
@@ -441,7 +441,7 @@
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"modificar estado do telefone"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Permite que a aplicação controle as funcionalidades de telefone do aparelho. Uma aplicação com esta permissão pode alternar entre redes, ligar/desligar o rádio do telefone e outras coisas semelhantes sem sequer o notificar."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"ler o estado e a identidade do telemóvel"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se está uma chamada ativa e qual o número remoto ligado por uma chamada."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se alguma chamada está ativa e qual o número remoto ligado por uma chamada."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que o tablet entre em inactividade"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inactividade do telefone"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Permite que a aplicação impeça o tablet de entrar no modo de suspensão."</string>
@@ -477,9 +477,9 @@
     <string name="permlab_useCredentials" msgid="235481396163877642">"utilizar contas no dispositivo"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Permite que a aplicação solicite tokens de autenticação."</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ver ligações de rede"</string>
-    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite que a aplicação visualize informações acerca das ligações de rede, como, por exemplo, quais as redes que existem e que estão ligadas."</string>
+    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite que a aplicação visualize informações acerca das ligações de rede como, por exemplo, que redes que existem e estão ligadas."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"acesso total à rede"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite que a aplicação crie sockets de rede e utilize protocolos de rede personalizados. O navegador e outras aplicações fornecem meios para enviar dados para a Internet, pelo que esta autorização não é necessária para enviar dados para a Internet."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite que a aplicação crie ligações de rede e utilize protocolos de rede personalizados. O navegador e outras aplicações fornecem meios para enviar dados para a Internet, pelo que esta autorização não é necessária para enviar dados para a Internet."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"alterar/intercetar definições e tráfego de rede"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Permite à aplicação alterar as definições de rede e intercetar e inspecionar todo o tráfego de rede, por exemplo, para mudar o proxy e a porta de qualquer APN. As aplicações maliciosas podem monitorizar, redirecionar ou modificar pacotes de rede sem o seu conhecimento."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"mudar conectividade de rede"</string>
@@ -489,7 +489,7 @@
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"mudar definição de utilização de dados de segundo plano"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permite à aplicação mudar a definição de utilização de dados em segundo plano."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"ver ligações Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite que a aplicação visualize informações acerca de redes Wi-Fi, como, por exemplo, se o Wi-Fi está ativado e o nome dos dispositivos Wi-Fi ligados."</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite que a aplicação visualize informações acerca de redes Wi-Fi como, por exemplo, se o Wi-Fi está ativado e o nome dos dispositivos Wi-Fi ligados."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"ligar e desligar de redes Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite que a aplicação se ligue e desligue de pontos de acesso Wi-Fi e que efetue alterações à configuração do dispositivo para redes Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepção Multicast Wi-Fi"</string>
@@ -509,7 +509,7 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"controlo Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permite que a aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desativar o bloqueio do ecrã"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que a aplicação desative o bloqueio de teclas e qualquer segurança por palavra-passe associada. Por exemplo, o telemóvel desativa o bloqueio de teclas quando recebe uma chamada e volta a ativar o bloqueio de teclas quando a chamada é terminada."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que a aplicação desative o bloqueio de teclas e qualquer segurança por palavra-passe associada. Por exemplo, o telemóvel desativa o bloqueio de teclas quando recebe uma chamada e reativa o bloqueio de teclas ao terminar a chamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que a aplicação leia as definições de sincronização de uma conta. Por exemplo, pode determinar se a aplicação Pessoas está sincronizada com uma conta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ativar e desativar a sincronização"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acções de texto"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Pouco espaço livre"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"O espaço de armazenamento do tablet está a ficar reduzido."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"O espaço de armazenamento do telefone está a ficar reduzido."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altif. estação ancoragem"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Áudio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c4aa883..75840cc 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -234,7 +234,7 @@
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"ativar o modo de carro"</string>
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite que o aplicativo ative o modo Carro."</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"fechar outros aplicativos"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite que o aplicativo encerre processos em segundo plano de outros aplicativos. Pode fazer com que outros aplicativos parem de funcionar."</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite que o aplicativo encerre processos em segundo plano de outros aplicativos. Pode ser que outros aplicativos parem de funcionar."</string>
     <string name="permlab_forceStopPackages" msgid="2329627428832067700">"força o interrompimento de outros aplicativos"</string>
     <string name="permdesc_forceStopPackages" msgid="5253157296183940812">"Permite que o aplicativo force o interrompimento de outros aplicativos."</string>
     <string name="permlab_forceBack" msgid="652935204072584616">"forçar encerramento do aplicativo"</string>
@@ -348,8 +348,8 @@
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite que o aplicativo leia dados dos contatos armazenados no tablet, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o aplicativo a salvar seus dados de contato, e aplicativos maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite que o aplicativo leia dados dos contatos armazenados no telefone, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o aplicativo a salvar seus dados de contato, e aplicativos maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modificar seus contatos"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite que o aplicativo modifique os dados sobre os contatos armazenados no tablet, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o aplicativo a excluir dados de contatos."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite que o aplicativo modifique os dados dos contatos armazenados no telefone, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o aplicativo a excluir dados de contatos."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite que o aplicativo modifique os dados sobre os contatos armazenados no tablet, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o aplicativo a excluir dados de contatos."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite que o aplicativo modifique os dados dos contatos armazenados no telefone, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o aplicativo a excluir dados de contatos."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"ler registro de chamadas"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite que o aplicativo leia o histórico de chamadas do tablet, incluindo dados de chamadas recebidas e realizadas. Esta permissão autoriza o aplicativo a salvar os dados de seu histórico de chamadas, e aplicativos maliciosos podem compartilhar esses dados do histórico de chamadas sem seu conhecimento."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite que o aplicativo leia o histórico de chamadas do telefone, incluindo dados de chamadas recebidas e realizadas. Esta permissão autoriza o aplicativo a salvar os dados de seu histórico de chamadas, e aplicativos maliciosos podem compartilhar os dados de seu histórico de chamadas sem seu conhecimento."</string>
@@ -361,9 +361,9 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"mod. próprio cartão contato"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que o aplicativo altere ou adicione informações pessoais de perfil armazenadas em seu dispositivo, como seu nome e informações de contato. Isso significa que o aplicativo pode identificá-lo e enviar as informações de seus perfil para terceiros."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler suas transmissões sociais"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que o aplicativo acesse e sincronize suas atualizações sociais e as de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o aplicativo leia as mensagens trocadas por você e seus amigos em redes sociais, independentemente de sua confidencialidade. Obs.: pode não ser aplicável a todas as redes sociais."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que o aplicativo acesse e sincronize suas atualizações sociais e as de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o aplicativo leia as mensagens trocadas por você e seus amigos em redes sociais, independentemente de sua confidencialidade. Obsservaç: pode não ser aplicável a todas as redes sociais."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever p/ suas transm. soc."</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permite que o aplicativo exiba atualizações sociais de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o aplicativo produza mensagens aparentemente enviadas por amigos. Obs.: pode não ser aplicável a todas as redes sociais."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Permite que o aplicativo exiba atualizações sociais de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o aplicativo produza mensagens aparentemente enviadas por amigos. Observação: pode não ser aplicável a todas as redes sociais."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"ler compromissos e informações confidenciais"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite que o aplicativo leia todos os eventos do calendário armazenados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que o aplicativo compartilhe ou salve os dados do calendário, independentemente de sua confidencialidade."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite que o aplicativo leia todos os eventos do calendário armazenados no telefone, incluindo os de amigos ou colegas de trabalho. Pode permitir que o aplicativo compartilhe ou salve os dados do calendário, independentemente de sua confidencialidade."</string>
@@ -377,10 +377,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um provedor de localização"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização simuladas para testar ou instalar um novo provedor de localização. Isso permite que o aplicativo substitua a localização e/ou o status retornado por outras fontes de localização, como o GPS ou provedores de localização."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"loalização precisa (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Acessar fontes de localização precisa, como o GPS do tablet. Quando esses serviços de localização estão disponíveis e ligados, esta permissão permite que o aplicativo determine sua localização precisa."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Acessar fontes de localização precisa, como o GPS do telefone. Quando esses serviços de localização estão disponíveis e ligados, esta permissão permite que o aplicativo determine sua localização precisa."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Acessar fontes de localização precisa, como o GPS do tablet. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização precisa."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Acessar fontes de localização precisa, como o GPS do telefone. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização precisa."</string>
     <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"localização aproximada (com base na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Acessar a localização aproximada a partir de fornecedores de localização que utilizam fontes de rede como torres de celular e Wi-Fi. Quando esses serviços de localização estão disponíveis e ligados, esta permissão permite que o aplicativo determine sua localização aproximada."</string>
+    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Acessar a localização aproximada a partir de fornecedores de localização que utilizam fontes de rede como torres de celular e Wi-Fi. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização aproximada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acessar SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite que o aplicativo use recursos com baixos níveis de SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"ler o buffer do frame"</string>
@@ -479,7 +479,7 @@
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ver conexões de rede"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite que o aplicativo acesse informações sobre conexões de rede, como as redes existentes e conectadas."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"acesso total à rede"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite que o aplicativo crie soquetes de rede e utilize protocolos de rede personalizados. O navegador e outros aplicativos fornecem meios de enviar dados para a Internet, e por isso esta permissão não é necessária para enviar dados para a Internet."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite que o aplicativo crie soquetes de rede e utilize protocolos de rede personalizados. O navegador e outros aplicativos fornecem meios de enviar dados para a Internet, e por isso esta permissão não é necessária para enviar os dados."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"alterar/interceptar as configurações de rede e tráfego"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Permite que o aplicativo altere configurações de rede e intercepte e inspecione todo o tráfego de rede, por exemplo, para alterar o proxy e a porta de qualquer APN. Aplicativos maliciosos podem monitorar, redirecionar ou modificar os pacotes de rede sem seu conhecimento."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"alterar conectividade da rede"</string>
@@ -509,7 +509,7 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar a comunicação a curta distância"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permite que o aplicativo se comunique com leitores, cartões e etiqueta NFC (Comunicação a curta distância)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desativar o bloqueio de tela"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que o aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Por exemplo, o telefone desativa o bloqueio de telas ao receber uma chamada e a reativa o bloqueio quando a chamada é finalizada."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que o aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Por exemplo, o telefone desativa o bloqueio de telas ao receber uma chamada e o reativa quando a chamada é finalizada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que o aplicativo leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o aplicativo People está sincronizado com uma conta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ativar e desativar sincronização"</string>
@@ -784,10 +784,10 @@
     <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Emirado"</string>
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"ler seu histórico e seus favoritos da web"</string>
-    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Permite que o aplicativo leia o histórico de todos os URLs acessados no navegador e todos os favoritos do navegador. Obs.: pode não ser aplicável a navegadors de terceiros e outros aplicativos com capacidade de navegação na web."</string>
+    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Permite que o aplicativo leia o histórico de todos os URLs acessados no navegador e todos os favoritos do navegador. Observação: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"gravar seu histórico e seus favoritos da web"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite que o aplicativo modifique o histórico ou os favoritos do navegador armazenados no tablet. Pode permitir que o aplicativo apague ou modifique os dados do navegador. Obs.: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que o aplicativo modifique o histórico ou os favoritos do navegador armazenados no telefone. Pode permitir que o aplicativo apague ou modifique os dados do navegador. Obs.: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite que o aplicativo modifique o histórico ou os favoritos do navegador armazenados no tablet. Pode permitir que o aplicativo apague ou modifique os dados do navegador. Observação: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que o aplicativo modifique o histórico ou os favoritos do navegador armazenados no telefone. Pode permitir que o aplicativo apague ou modifique os dados do navegador. Observação: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"definir um alarme"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que o aplicativo defina um alarme em um aplicativo despertador instalado. Alguns aplicativos despertador podem não implementar este recurso."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"excluir"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ações de texto"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Pouco espaço"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"O espaço de armazenamento do tablet está ficando baixo."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"O espaço de armazenamento do telefone está ficando baixo."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes do dock"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Áudio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index b0d007c..d5a4250 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1420,10 +1420,10 @@
     <skip />
     <string name="inputMethod" msgid="1653630062304567879">"Metoda d\'endataziun"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acziuns da text"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Pauca capacitad da memorisar"</string>
-    <!-- no translation found for low_internal_storage_view_text (4231085657068852042) -->
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
     <skip />
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Mo pli pauca capacitad da memorisar."</string>
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Interrumper"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -2024,4 +2024,6 @@
     <skip />
     <!-- no translation found for default_audio_route_category_name (3722811174003886946) -->
     <skip />
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 53fe99f..ef732f8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"ştergeţi"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Spaţiu de stocare redus"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Spaţiul de stocare de pe tabletă este scăzut."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Spaţiul de stocare a telefonului se reduce."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Anulaţi"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Difuz. dispozit. andocare"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Ieşire audio HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 4ba5b2a..8c280cc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"удалить"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Способ ввода"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Операции с текстом"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Недостаточно места"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Заканчивается место в памяти планшетного ПК."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Заканчивается место в памяти телефона."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"ОК"</string>
     <string name="cancel" msgid="6442560571259935130">"Отмена"</string>
     <string name="yes" msgid="5362982303337969312">"ОК"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динамики док-станции"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-аудио"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f026a5b..0ddf9ef 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -351,8 +351,8 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v tablete vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v telefóne vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"čítať denník hovorov"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Umožňuje aplikácii čítať hovory vášho tabletu vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Toto povolenie umožňuje aplikáciám ukladať údaje o hovoroch. Škodlivé aplikácie môžu zdieľať údaje o hovoroch bez vášho vedomia."</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Umožňuje aplikácii čítať hovory vášho telefónu vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Toto povolenie umožňuje aplikáciám ukladať údaje o hovoroch. Škodlivé aplikácie môžu zdieľať údaje o hovoroch bez vášho vedomia."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Umožňuje aplikácii čítať denník hovorov vášho tabletu vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Toto povolenie umožňuje aplikáciám ukladať údaje o hovoroch. Škodlivé aplikácie môžu zdieľať údaje o hovoroch bez vášho vedomia."</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Umožňuje aplikácii čítať denník hovorov vášho telefónu vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Toto povolenie umožňuje aplikáciám ukladať údaje o hovoroch. Škodlivé aplikácie môžu zdieľať údaje o hovoroch bez vášho vedomia."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"zapisovať do denníka hovorov"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Umožňuje aplikácii upravovať denník hovorov vo vašom tablete vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Umožňuje aplikácii upravovať denník hovorov vo vašom telefóne vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov."</string>
@@ -361,12 +361,12 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"upraviť vlastnú kartu kontaktu"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikácii zmeniť alebo pridať do osobného profilu informácie uložené vo vašom zariadení, ako je vaše meno a kontaktné informácie. Znamená to, že vás aplikácia môže identifikovať a odoslať informácie o vašom profile ostatným aplikáciám."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čítať váš sociálny stream"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikácii pristupovať k sociálnym aktualizáciám od vás a vašich priateľov a synchronizovať ich. Pri zdieľaní informácií buďte opatrní – toto povolenie umožňuje aplikácii čítať komunikáciu medzi vami a vašimi priateľmi v sociálnych sieťach, a to bez ohľadu na jej dôvernosť. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikácii pristupovať k sociálnym aktualizáciám od vás a vašich priateľov a synchronizovať ich. Pri zdieľaní informácií dávajte pozor – toto povolenie umožňuje aplikácii čítať komunikáciu medzi vami a vašimi priateľmi v sociálnych sieťach, a to bez ohľadu na jej dôvernosť. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"písať do vášho sociálneho streamu"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Umožňuje aplikácii zobraziť sociálne aktualizácie od vašich priateľov. Pri zdieľaní informácií buďte opatrní – toto povolenie umožňuje aplikácii vytvárať správy, ktoré zdanlivo pochádzajú od vašich priateľov. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Umožňuje aplikácii zobraziť sociálne aktualizácie od vašich priateľov. Pri zdieľaní informácií dávajte pozor – toto povolenie umožňuje aplikácii vytvárať správy, ktoré zdanlivo pochádzajú od vašich priateľov. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"čítať udalosti v kalendári a dôverné informácie"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Umožňuje aplikácii čítať všetky udalosti kalendára uložené v tablete vrátane udalostí priateľov alebo spolupracovníkov. Aplikácii to môže umožniť zdieľať alebo ukladať údaje kalendára bez ohľadu na dôvernosť či citlivosť týchto údajov."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Umožňuje aplikácii čítať všetky udalosti kalendára uložené v telefóne vrátane udalostí priateľov alebo spolupracovníkov. Aplikácii to môže umožniť zdieľať alebo ukladať údaje kalendára bez ohľadu na dôvernosť či citlivosť týchto údajov."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Umožňuje aplikácii čítať všetky udalosti kalendára uložené v tablete vrátane udalostí priateľov alebo spolupracovníkov. Aplikácii to umožní zdieľať alebo ukladať údaje kalendára bez ohľadu na dôvernosť či citlivosť týchto údajov."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Umožňuje aplikácii čítať všetky udalosti kalendára uložené v telefóne vrátane udalostí priateľov alebo spolupracovníkov. Aplikácii to umožní zdieľať alebo ukladať údaje kalendára bez ohľadu na dôvernosť či citlivosť týchto údajov."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"pridať alebo upraviť udalosti v kalendári a odoslať e-mail hosťom bez vedomia vlastníka"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Umožňuje aplikácii pridávať, odstraňovať alebo meniť udalosti, ktoré môžete v tablete upravovať, a to vrátane udalostí priateľov a spolupracovníkov. Toto povolenie umožňuje aplikácii odosielať správy, ktoré budú zdanlivo prichádzať od vlastníkov kalendára, alebo upravovať udalosti bez vedomia vlastníkov."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Umožňuje aplikácii pridávať, odstraňovať alebo meniť udalosti, ktoré môžete v telefóne upravovať, a to vrátane udalostí priateľov a spolupracovníkov. Toto povolenie umožňuje aplikácii odosielať správy, ktoré budú zdanlivo prichádzať od vlastníkov kalendára, alebo upravovať udalosti bez vedomia vlastníkov."</string>
@@ -489,12 +489,12 @@
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"zmeniť nastavenie použitia údajov na pozadí"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Umožňuje aplikácii zmeniť nastavenie používania údajov na pozadí."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"zobraziť pripojenia siete Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Umožňuje aplikácii zobraziť informácie o sieťach Wi-Fi. Napríklad o tom, či je sieť Wi-Fi povolená, alebo názov pripojených zariadení Wi-Fi."</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Umožňuje aplikácii zobraziť informácie o sieťach Wi-Fi. Napríklad o tom, či je sieť Wi-Fi povolená alebo názvy pripojených zariadení Wi-Fi."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"pripojiť a odpojiť od siete Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Umožňuje aplikácii pripojiť sa na prístupové body siete Wi-Fi, odpojiť sa od nich a meniť konfiguráciu zariadení pre siete Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Povoliť príjem viacsmerového vysielania Wi-Fi"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Umožňuje aplikácii prijímať pakety odoslané na všetky zariadenia v sieti Wi-Fi pomocou viacsmerových adries, nie len pomocou vášho tabletu. Spotrebuje viac energie ako režim bez viacsmerového vysielania."</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Umožňuje aplikácii prijímať pakety odoslané na všetky zariadenia v sieti Wi-Fi pomocou viacsmerových adries, nie len pomocou vášho telefónu. Spotrebuje viac energie ako režim bez viacsmerového vysielania."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Umožňuje aplikácii prijímať pakety odoslané na všetky zariadenia v sieti Wi-Fi pomocou viacsmerových adries, nielen pomocou vášho tabletu. Spotrebuje viac energie ako režim bez viacsmerového vysielania."</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Umožňuje aplikácii prijímať pakety odoslané na všetky zariadenia v sieti Wi-Fi pomocou viacsmerových adries, nielen pomocou vášho telefónu. Spotrebuje viac energie ako režim bez viacsmerového vysielania."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"pristupovať k nastaveniam Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Umožňuje aplikácii konfigurovať miestny tablet s rozhraním Bluetooth a vyhľadávať a spárovať vzdialené zariadenia."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Umožňuje aplikácii konfigurovať miestny telefón s rozhraním Bluetooth, vyhľadávať a spárovať vzdialené zariadenia."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"odstrániť"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metóda vstupu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operácie s textom"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Nedostatok pamäte"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"V ukladacom priestore tabletu je málo miesta."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"V telefóne je málo miesta na ukladanie údajov."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvuk HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 4f82bbb..102e6f2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način vnosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Besedilna dejanja"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Zmanjkuje pomnilnika"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Pomanjkanje prostora v shrambi tabličnega računalnika."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Primanjkuje pomnilnika telefona."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"V redu"</string>
     <string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
     <string name="yes" msgid="5362982303337969312">"V redu"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvočniki stojala"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvok HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index ca35957..7dd17fc 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"избриши"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Мало простора"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Меморијски простор таблета је скоро попуњен."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Понестаје простора за складиштење на телефону."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Потврди"</string>
     <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
     <string name="yes" msgid="5362982303337969312">"Потврди"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Звучници базне станице"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI аудио"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2e88f0a..c673628 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -204,9 +204,9 @@
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"läsa SMS-meddelanden"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"skicka SMS"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"Tillåter att appen skickar SMS. Detta kan leda till ovänta avgifter. Skadliga appar kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar."</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"Tillåter att appen skickar SMS. Detta kan leda till oväntade avgifter. Skadliga appar kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar."</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"skicka SMS utan bekräftelse"</string>
-    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Tillåter att appen skickar SMS. Detta kan leda till ovänta avgifter. Skadliga appar kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar."</string>
+    <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Tillåter att appen skickar SMS. Detta kan leda till oväntade avgifter. Skadliga appar kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"läsa dina textmeddelanden (SMS eller MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Tillåter att appen läser SMS som sparats på pekdatorn eller på SIM-kortet. Med den här behörigheten tillåts appen att läsa alla SMS oavsett innehåll eller sekretess."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Tillåter att appen läser SMS som sparats på mobilen eller på SIM-kortet. Med den här behörigheten tillåts appen att läsa alla SMS oavsett innehåll eller sekretess."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"ta bort"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indatametod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textåtgärder"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Dåligt med utrymme"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Pekdatorns lagringsutrymme håller på att ta slut."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Telefonens lagringsutrymme håller på att ta slut."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockningsstationens högtalare"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-ljud"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3136766..ef9d19d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -280,7 +280,7 @@
     <string name="permdesc_readInputState" msgid="8387754901688728043">"Inaruhusu programu kuangalia vibonye unavyo bonyeza hata wakati unapo shirikiana na programu nyingine (kama vile kuweka neno). Kamwe isihitajike na programu za kawaida."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"funganisha kwa mbinu ya uingizaji"</string>
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Inaruhusu mmiliki kushurutisha kwenye kusano ya kiwango cha juu ya mbinu ya ingizo. Haipaswi kuhitajika kwa programu za kawaida."</string>
-    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"funga kwa huduma ya afikiaji"</string>
+    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"funga kwa huduma ya ufikiaji"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Inamuruhusu mmiliki kufunga kipengee kinachojitokeza katika nyanja mbalimbali za kiwango cha juu cha huduma ya afikiaji. Hapaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindTextService" msgid="7358378401915287938">"Imefungwa kwa huduma ya maandishi"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu ya huduma ya matini(k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"futa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mbinu ya uingizaji"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Vitendo vya maandishi"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Nafasi ni ndogo"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">" Nafasi ya hifadhi ya kompyuta ndogo inaisha."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Nafasi ya hifadhi ya simu inaisha."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Sawa"</string>
     <string name="cancel" msgid="6442560571259935130">"Ghairi"</string>
     <string name="yes" msgid="5362982303337969312">"Sawa"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Vipasa sauti vya gati"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Sauti ya HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Mfumo"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw600dp-land/arrays.xml b/core/res/res/values-sw600dp-land/arrays.xml
index 6a09cf8..2b5fd99 100644
--- a/core/res/res/values-sw600dp-land/arrays.xml
+++ b/core/res/res/values-sw600dp-land/arrays.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <!-- Resources for MultiWaveView in LockScreen -->
+    <!-- Resources for GlowPadView in LockScreen -->
     <array name="lockscreen_targets_when_silent">
         <item>@drawable/ic_lockscreen_unlock</item>
         <item>@null</item>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index d26666e..8937c2a 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,8 +45,8 @@
     <!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
 
-    <!-- target placement radius for MultiWaveView -->
-    <dimen name="multiwaveview_target_placement_radius">182dip</dimen>
+    <!-- target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
+    <dimen name="glowpadview_target_placement_radius">182dip</dimen>
 
     <!-- Size of status line font in LockScreen. -->
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ba0ee66..c4b31d5 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -361,7 +361,7 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"แก้ไขบัตรผู้ติดต่อของคุณเอง"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงหรือเพิ่มข้อมูลโปรไฟล์ส่วนตัวที่จัดเก็บไว้บนอุปกรณ์ของคุณ เช่น ชื่อและข้อมูลติดต่อ ซึ่งหมายความว่าแอปพลิเคชันจะสามารถระบุตัวตนของคุณและส่งข้อมูลโปรไฟล์ของคุณให้แก่ผู้อื่นได้"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"อ่านสตรีมเครือข่ายสังคม"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"อนุญาตให้แอปพลิเคชันเข้าถึงและซิงค์การอัปเดตทางสังคมจากคุณและเพื่อน โปรดแบ่งปันข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถอ่านการติดต่อระหว่างคุณและเพื่อนในเครือข่ายสังคมได้ ไ่ม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับแบบใดก็ตาม หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับทุกเครือข่ายสังคม"</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"อนุญาตให้แอปพลิเคชันเข้าถึงและซิงค์การอัปเดตทางสังคมจากคุณและเพื่อน โปรดแบ่งปันข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถอ่านการติดต่อระหว่างคุณและเพื่อนในเครือข่ายสังคมได้ ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับแบบใดก็ตาม หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับทุกเครือข่ายสังคม"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"เขียนในสตรีมเครือข่ายสังคม"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"อนุญาตให้แอปพลิเคชันแสดงการอัปเดตทางสังคมจากเพื่อนของคุณ โปรดแบ่งปันข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถสร้างข้อความที่ดูเหมือนมาจากเพื่อนได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้ได้กับทุกเครือข่ายสังคม"</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"อ่านกิจกรรมบนปฏิทินรวมถึงข้อมูลที่เป็นความลับ"</string>
@@ -499,7 +499,7 @@
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"อนุญาตให้แอปพลิเคชันกำหนดค่าแท็บเล็ตบลูทูธในตัวเครื่อง รวมทั้งค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"อนุญาตให้แอปพลิเคชันกำหนดค่าโทรศัพท์บลูทูธในตัวเครื่อง ตลอดจนค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"ดูการเชื่อมต่อ WiMAX"</string>
-    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"อนุญาตใ้ห้แอปพลิเคชันตรวจสอบว่า WiMAX เปิดใช้งานอยู่หรือไม่และข้อมูลเกี่ยวกับเครือข่าย WiMAX ใดๆ ที่เชื่อมต่ออยู่"</string>
+    <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"อนุญาตให้แอปพลิเคชันตรวจสอบว่า WiMAX เปิดใช้งานอยู่หรือไม่และข้อมูลเกี่ยวกับเครือข่าย WiMAX ใดๆ ที่เชื่อมต่ออยู่"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"เปลี่ยนสถานะของ WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อแท็บเล็ตกับเครือข่าย WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อโทรศัพท์กับเครือข่าย WiMAX"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"ลบ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"เหลือที่ว่างน้อย"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"ที่เก็บข้อมูลแท็บเล็ตมีพื้นที่เหลือน้อย"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"พื้นที่เก็บข้อมูลบนโทรศัพท์เหลือน้อย"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"ตกลง"</string>
     <string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
     <string name="yes" msgid="5362982303337969312">"ตกลง"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ลำโพงแท่นชาร์จ"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"เสียง HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"ระบบ"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8cd4b7a..4ea1dbc 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"tanggalin"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Pamamaraan ng pag-input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Pagkilos ng teksto"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Mababa sa espasyo"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Bumababa na ang puwang ng imbakan ng Tablet."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Lumiliit ang espasyo ng imbakan ng telepono."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Mga speaker ng dock"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index b83cb7f..182e2cd 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -459,7 +459,7 @@
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Uygulamaya, sistem duvar kağıdı için boyut ipuçlarını ayarlama izni verir."</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"sistemi fabrika değerlerine sıfırla"</string>
     <string name="permdesc_masterClear" msgid="3665380492633910226">"Uygulamaya, tüm verileri, yapılandırmayı ve yüklü uygulamaları silerek sistemi tamamen fabrika ayarlarına sıfırlama izni verir."</string>
-    <string name="permlab_setTime" msgid="2021614829591775646">"saati ayarla"</string>
+    <string name="permlab_setTime" msgid="2021614829591775646">"saati ayarlayın"</string>
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"Uygulamaya, tablet saatini değiştirme izni verir."</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"Uygulamaya, telefon saatini değiştirme izni verir."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"saat dilimini ayarla"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"sil"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Giriş yöntemi"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Metin eylemleri"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Yer az"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tabletin depolama alanındaki boş yer azalıyor."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Telefonun depolama alanı azalıyor."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"Tamam"</string>
     <string name="cancel" msgid="6442560571259935130">"İptal"</string>
     <string name="yes" msgid="5362982303337969312">"Tamam"</string>
@@ -1040,8 +1041,8 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kart eklendi"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Mobil ağa erişmek için cihazınızı yeniden başlatın."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Yeniden başlat"</string>
-    <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarla"</string>
-    <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarla"</string>
+    <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarlayın"</string>
+    <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarlayın"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Tamamlandı"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Varsayılan"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Yuva hoparlörleri"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ses"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 2370815..d861415 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"видалити"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод введення"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дії з текстом"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Недост. місця"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Пам\'яті пристрою стає недостатньо."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Пам\'яті телефону стає недостатньо."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Скасувати"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динаміки док-станції"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Аудіовихід HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 76027d3..e80ac6a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -220,7 +220,7 @@
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"truy xuất chi tiết về các ứng dụng đang chạy"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Cho phép ứng dụng truy xuất thông tin chi tiết về các tác vụ đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string>
-    <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng có thể thực hiện việc này mà không cần thiết bị vào của bạn."</string>
+    <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng có thể thực hiện việc này mà không cần bạn nhập."</string>
     <string name="permlab_removeTasks" msgid="6821513401870377403">"dừng các ứng dụng đang chạy"</string>
     <string name="permdesc_removeTasks" msgid="1394714352062635493">"Cho phép ứng dụng xóa công việc và loại bỏ các ứng dụng của chúng. Ứng dụng độc hại có thể làm gián đoạn hoạt động của các ứng dụng khác."</string>
     <string name="permlab_startAnyActivity" msgid="2918768238045206456">"bắt đầu mọi hoạt động"</string>
@@ -301,8 +301,8 @@
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"gửi tín hiệu Linux đến ứng dụng"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"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="8841113627955563938">"đặt ứng dụng luôn chạy"</string>
-    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình trong bộ nhớ. Việc này có thể hạn chế bộ nhớ có đối với các ứng dụng khác đang làm chậm máy tính bảng."</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình trong bộ nhớ. Việc này có thể hạn chế bộ nhớ có đối với các ứng dụng khác đang làm chậm điện thoại."</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình trong bộ nhớ. Việc này có thể hạn chế bộ nhớ đối với các ứng dụng khác đang làm chậm máy tính bảng."</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình trong bộ nhớ. Việc này có thể hạn chế bộ nhớ đối với các ứng dụng khác đang làm chậm điện thoại."</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"xóa ứng dụng"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Cho phép ứng dụng xóa các gói Android. Ứ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="274109191845842756">"xóa dữ liệu của ứng dụng khác"</string>
@@ -342,8 +342,8 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến máy tính bảng mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ máy tính bảng do ứng dụng luôn chạy."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến điện thoại mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ điện thoại do ứng dụng luôn chạy."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"gửi truyền phát hấp dẫn người xem"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho máy tính bảng bị chậm hoặc không ổn định bằng cách khiến máy tính bảng sử dụng quá nhiều bộ nhớ."</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho điện thoại bị chậm hoặc không ổn định bằng cách khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho máy tính bảng bị chậm hoặc không ổn định do khiến máy tính bảng sử dụng quá nhiều bộ nhớ."</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho điện thoại bị chậm hoặc không ổn định do khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"đọc danh sách liên hệ của bạn"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Cho phép ứng dụng đọc dữ liệu về các liên hệ được lưu trữ trên máy tính bảng của bạn, bao gồm tần suất bạn đã gọi điện, gửi email hoặc liên lạc theo các cách khác với những người cụ thể. Quyền này cho phép ứng dụng lưu dữ liệu liên lạc của bạn và các ứng dụng độc hại có thể chia sẻ dữ liệu liên lạc mà bạn không biết."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Cho phép ứng dụng đọc dữ liệu về các liên hệ được lưu trữ trên điện thoại của bạn, bao gồm tần suất bạn đã gọi điện, gửi email hoặc liên lạc theo các cách khác với những người cụ thể. Quyền này cho phép ứng dụng lưu dữ liệu liên lạc của bạn và các ứng dụng độc hại có thể chia sẻ dữ liệu liên lạc mà bạn không biết."</string>
@@ -426,7 +426,7 @@
     <string name="permlab_hardware_test" msgid="4148290860400659146">"kiểm tra phần cứng"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"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="3740797576113760827">"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. Việc này có thể dẫn đến các khoản phí hoặc cuộc gọi không mong muố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. Các ứng dụng độc hại có thể khiến bạn tốn tiền bằng cách thực hiện cuộc gọi mà không cần sự xác nhận của bạn."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"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. Việc này có thể dẫn đến các khoản phí hoặc cuộc gọi không mong muố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. Các ứng dụng độc hại có thể khiến bạn tốn tiền do thực hiện cuộc gọi mà không cần sự xác nhận của bạn."</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="1689024901509996810">"Cho phép ứng dụng gọi bất kỳ số điện thoại nào, bao gồm cả số khẩn cấp mà không có sự can thiệp của bạn. Ứng dụng độc hại có thể thực hiện những cuộc gọi không cần thiết và bất hợp pháp đến các 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>
@@ -505,7 +505,7 @@
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Cho phép ứng dụng kết nối điện thoại và ngắt kết nối điện thoại khỏi mạng WiMAX."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ghép nối với thiết bị Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Cho phép ứng dụng xem cấu hình của Bluetooth trên máy tính bảng và 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="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại và 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="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại, 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="7120611819401789907">"Cho phép ứng dụng giao tiếp với thẻ Giao tiếp trường gần (NFC), thẻ và trình đọc."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"vô hiệu hóa khóa màn hình của bạn"</string>
@@ -521,13 +521,13 @@
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"ghi nguồn cấp dữ liệu đã đăng ký"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hóa của bạn. Ứng dụng độc hại có thể thay đổi nguồn cấp dữ liệu đã đồng bộ hóa của bạn."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"đọc cụm từ bạn đã thêm vào từ điển"</string>
-    <string name="permdesc_readDictionary" msgid="659614600338904243">"Cho phép ứng dụng đọc các từ, tên và cụm từ mà người dùng có thể đã lưu trữ trong từ điển của người dùng."</string>
+    <string name="permdesc_readDictionary" msgid="659614600338904243">"Cho phép ứng dụng đọc tất cả các từ, tên và cụm từ 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="2296383164914812772">"ghi vào từ điển do người dùng xác định"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"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_sdcardRead" product="nosdcard" msgid="8235341515605559677">"kiểm tra quyền truy cập vào bộ nhớ được bảo vệ"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"kiểm tra quyền truy cập vào bộ nhớ được bảo vệ"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Cho phép ứng dụng kiểm tra quyền cho bộ lưu trữ USB sẽ có trên các thiết bị trong tương lai."</string>
-    <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Cho phép ứng dụng kiểm tra quyền cho thẻ SD sẽ có trên các thiết bị trong tương lai."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Cho phép ứng dụng kiểm tra quyền cho bộ lưu trữ USB trên các thiết bị trong tương lai."</string>
+    <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Cho phép ứng dụng kiểm tra quyền cho thẻ SD sẽ các thiết bị trong tương lai."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"sửa đổi hoặc xóa nội dung của bộ lưu trữ USB của bạn"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"sửa đổi hoặc xóa nội dung của thẻ SD của bạn"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Cho phép ứng dụng ghi vào bộ lưu trữ USB."</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"xóa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Phương thức nhập"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tác vụ văn bản"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Còn ít dung lượng"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Dung lượng lưu trữ của máy tính bảng thấp."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Dung lượng lưu trữ của điện thoại thấp."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Hủy"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Loa đế"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Âm thanh HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Hệ thống"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e38b098..6b1bfa6 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"删除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"输入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字操作"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"存储空间不足"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"平板电脑存储空间所剩不多了。"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"手机内存空间所剩不多了。"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"确定"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="yes" msgid="5362982303337969312">"确定"</string>
@@ -1011,7 +1012,7 @@
     <item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
     <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
   </plurals>
-    <string name="wifi_available_sign_in" msgid="4029489716605255386">"连接到 Wi-Fi 网络"</string>
+    <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 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>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"基座扬声器"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 音频"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"系统"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9519007..9decfa9 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -196,9 +196,9 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"重設撥號路徑"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"允許應用程式處理撥出電話及更改撥打的號碼。這項權限可讓應用程式監控、轉接或阻止撥出的電話。"</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"接收簡訊 (SMS)"</string>
-    <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理簡訊。這樣可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
+    <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理簡訊。這項設定可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收簡訊 (MMS)"</string>
-    <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理 MMS 訊息。這樣可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
+    <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理 MMS 訊息。這項設定可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"接收緊急廣播"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"允許應用程式接收及處理緊急廣播訊息,只有系統應用程式可以具備這項權限。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
@@ -216,7 +216,7 @@
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"接收簡訊 (WAP)"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string>
-    <string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取最近執行工作的資訊。這樣可能會讓應用程式找出裝置上所使用應用程式的相關資訊。"</string>
+    <string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取最近執行工作的資訊。這項設定可讓應用程式找出裝置所用程式的相關資訊。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"擷取執行中應用程式的詳細資訊"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允許應用程式擷取目前及最近所執行任務的詳細資訊。請注意,惡意應用程式可能會找出其他應用程式的不公開資訊。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string>
@@ -234,7 +234,7 @@
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"啟用行車模式"</string>
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"允許應用程式啟用車用模式。"</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"關閉其他應用程式"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"允許應用程式終止其他應用程式的背景處理程序。這樣可能會導致其他應用程式停止執行。"</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"允許應用程式終止其他應用程式的背景處理程序。這項設定可能會導致其他應用程式停止執行。"</string>
     <string name="permlab_forceStopPackages" msgid="2329627428832067700">"強制停止其他應用程式"</string>
     <string name="permdesc_forceStopPackages" msgid="5253157296183940812">"允許應用程式強制停止其他應用程式。"</string>
     <string name="permlab_forceBack" msgid="652935204072584616">"強制關閉應用程式"</string>
@@ -301,8 +301,8 @@
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"將 Linux 訊號傳送給應用程式"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允許應用程式要求將提供的訊號傳送給所有持續運作中的處理程序。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"一律執行應用程式"</string>
-    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允許應用程式讓部分內容佔用記憶體,持續執行。這樣可能會限制其他應用程式可用的記憶體,並拖慢平板電腦運作速度。"</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"允許應用程式讓部分內容佔用記憶體,持續執行。這樣可能會限制其他應用程式可用的記憶體,並拖慢手機運作速度。"</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允許應用程式的部分內容常駐在記憶體中。這項設定可能會限制其他應用程式可用的記憶體,並拖慢平板電腦運作速度。"</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"允許應用程式讓部分內容佔用記憶體,持續執行。這項設定可能會限制其他應用程式可用的記憶體,並拖慢手機運作速度。"</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"刪除應用程式"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"允許應用程式刪除 Android 套件。請注意,惡意應用程式可能利用此功能刪除重要應用程式。"</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"刪除其他應用程式資料"</string>
@@ -359,23 +359,23 @@
     <string name="permlab_readProfile" msgid="4701889852612716678">"讀取自己的聯絡資訊"</string>
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"允許應用程式讀取裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這表示應用程式可以識別您的身分,並將您的個人資料傳送給他人。"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"修改自己的聯絡資訊"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或變更裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這樣可讓應用程式識別您的身分,並可能將您的個人資料傳送給他人。"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或變更裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這項設定可讓應用程式識別您的身分,並可能將您的個人資料傳送給他人。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"讀取您的社交串流"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允許應用程式存取並同步處理您和好友的最新動態。因此,當您分享資訊時請小心,因為這項權限可讓應用程式讀取您和好友在社交網路上的私人通訊,包括機密通訊。注意:並非所有社交網路皆適用於這項權限。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"寫入您的社交串流"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"允許應用程式顯示好友的最新動態。因此,當您分享資訊時請小心,因為這項權限可讓應用程式偽裝好友產生訊息。注意:並非所有社交網路皆適用於這項權限。"</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"讀取日曆活動與機密資訊"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"允許應用程式讀取平板電腦上儲存的所有日曆活動,包括好友或同事的活動。這樣可能會讓應用程式共用或儲存您的日曆資料,甚至包括機密或敏感的資料。"</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"允許應用程式讀取手機上儲存的所有日曆活動,包括好友或同事的活動。這樣可能會讓應用程式共用或儲存您的日曆資料,甚至包括機密或敏感的資料。"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"允許應用程式讀取平板電腦上儲存的所有日曆活動,包括好友或同事的活動。這項設定會讓應用程式共用或儲存您的日曆資料,甚至包括機密或敏感的資料。"</string>
+    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"允許應用程式讀取手機上儲存的所有日曆活動,包括好友或同事的活動。這項設定可能會讓應用程式共用或儲存您的日曆資料,甚至包括機密或敏感的資料。"</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"在未經擁有者同意的情況下新增或修改日曆活動,以及傳送電子郵件給邀請對象"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"允許應用程式新增、移除、變更您可以在平板電腦上修改的活動,包括好友或同事的活動。這樣可能會讓應用程式偽裝日曆擁有者傳送訊息,或私自修改活動。"</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"允許應用程式新增、移除、變更您可以在手機上修改的活動,包括好友或同事的活動。這樣可能會讓應用程式偽裝日曆擁有者傳送訊息,或私自修改活動。"</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"允許應用程式新增、移除、變更您可以在平板電腦上修改的活動,包括好友或同事的活動。這項設定可能會讓應用程式偽裝日曆擁有者傳送訊息,或私自修改活動。"</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"允許應用程式新增、移除、變更您可以在手機上修改的活動,包括好友或同事的活動。這項設定可能會讓應用程式偽裝日曆擁有者傳送訊息,或私自修改活動。"</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"模擬位置來源以供測試"</string>
-    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這樣可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
+    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這項設定可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"接收額外的位置提供者指令"</string>
-    <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允許應用程式存取額外位置資訊提供者指令。這樣可能會讓應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
+    <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"准許安裝位置提供者"</string>
-    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這樣可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
+    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這項設定可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"精確位置 (GPS)"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"存取平板電腦 GPS 等精確位置資訊來源。當位置資訊服務可以使用且已開啟時,這項權限即可讓應用程式判斷您的精確位置。"</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"存取手機 GPS 等精確位置資訊來源。當位置資訊服務可以使用且已開啟時,這項權限即可讓應用程式判斷您的精確位置。"</string>
@@ -493,8 +493,8 @@
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"建立及中斷 WiFi 連線"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"允許應用程式與 Wi-Fi 存取點連線或中斷連線,並可變更 Wi-Fi 網路的裝置設定。"</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"允許接收 Wi-Fi 多點傳播封包"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"允許應用程式接收透過多點傳播位址傳送給 Wi-Fi 網路上所有裝置 (而不只是傳送給您的平板電腦) 的封包。這樣會比非多點傳播模式使用更多電力。"</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"允許應用程式接收透過多點傳播位址傳送給 Wi-Fi 網路上所有裝置 (而不只是傳送給您的手機) 的封包。這樣會比非多點傳播模式使用更多電力。"</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"允許應用程式接收透過多點傳播位址傳送給 Wi-Fi 網路上所有裝置 (而不只是傳送給您的平板電腦) 的封包。這項設定會比非多點傳播模式耗用更多電力。"</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"允許應用程式接收透過多點傳播位址傳送給 Wi-Fi 網路上所有裝置 (而不只是傳送給您的手機) 的封包。這項設定會比非多點傳播模式耗用更多電力。"</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"存取藍牙設定"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允許應用程式設定本機藍牙平板電腦,以及搜尋遠端裝置並配對連線。"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允許應用程式設定本機藍牙手機,以及搜尋遠端裝置並配對連線。"</string>
@@ -786,8 +786,8 @@
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"讀取您的網路書籤和紀錄"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"允許應用程式讀取瀏覽器造訪過的所有網址紀錄,以及瀏覽器的所有書籤。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"寫入網路書籤和紀錄"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"允許應用程式修改平板電腦上儲存的瀏覽紀錄或書籤。這樣可能會讓應用程式清除或修改瀏覽資料。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽紀錄或書籤。這樣可能會讓應用程式清除或修改瀏覽資料。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"允許應用程式修改平板電腦上儲存的瀏覽紀錄或書籤。這項設定會讓應用程式具有清除或修改瀏覽資料的權限。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽紀錄或書籤。這項設定會讓應用程式具有清除或修改瀏覽資料的權限。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增語音留言"</string>
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"刪除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"輸入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字動作"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"儲存空間即將不足"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"平板電腦的儲存空間即將不足。"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"手機儲存空間即將不足。"</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"確定"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="yes" msgid="5362982303337969312">"確定"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"座架喇叭"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 音訊"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c4808a2..48a7a8a 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -934,9 +934,10 @@
     <string name="deleteText" msgid="7070985395199629156">"susa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indlela yokufakwayo"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
-    <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Isikhala sincane"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Isitoreji sethebhulethi siya ngokuphela."</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Isikhala sokugcina sefoni siya ngokuphela."</string>
+    <!-- no translation found for low_internal_storage_view_title (5576272496365684834) -->
+    <skip />
+    <!-- no translation found for low_internal_storage_view_text (6640505817617414371) -->
+    <skip />
     <string name="ok" msgid="5970060430562524910">"KULUNGILE"</string>
     <string name="cancel" msgid="6442560571259935130">"Khansela"</string>
     <string name="yes" msgid="5362982303337969312">"KULUNGILE"</string>
@@ -1289,4 +1290,6 @@
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Izipika ze-Dock"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Umsindo we-HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Isistimu"</string>
+    <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 1eeca59..aeb6b4f 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -350,7 +350,7 @@
         <item>中文 (繁體)</item>
     </string-array>
 
-    <!-- Resources for MultiWaveView in LockScreen -->
+    <!-- Resources for GlowPadView in LockScreen -->
     <array name="lockscreen_targets_when_silent">
         <item>@drawable/ic_lockscreen_unlock</item>
         <item>@drawable/ic_lockscreen_search</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a68011d..3a7253b 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5377,6 +5377,51 @@
     </declare-styleable>
 
     <!-- =============================== -->
+    <!-- GlowPadView class attributes -->
+    <!-- =============================== -->
+    <eat-comment />
+    <declare-styleable name="GlowPadView">
+        <!-- Reference to an array resource that be shown as targets around a circle. -->
+        <attr name="targetDrawables"/>
+
+        <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+        <attr name="targetDescriptions"/>
+
+        <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+        <attr name="directionDescriptions"/>
+
+        <!-- Sets a drawable as the center. -->
+        <attr name="handleDrawable"/>
+
+        <!-- Drawable to use for wave ripple animation. -->
+        <attr name="outerRingDrawable" format="reference"/>
+
+        <!-- Drawble used for drawing points -->
+        <attr name="pointDrawable" format="reference" />
+
+        <!-- Inner radius of glow area. -->
+        <attr name="innerRadius"/>
+
+        <!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
+        <attr name="outerRadius"/>
+
+        <!-- Radius of glow under finger. -->
+        <attr name="glowRadius" format="dimension" />
+
+        <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
+        <attr name="vibrationDuration"/>
+
+        <!-- How close we need to be before snapping to a target. -->
+        <attr name="snapMargin"/>
+
+        <!-- Number of waves/chevrons to show in animation. -->
+        <attr name="feedbackCount"/>
+
+        <!-- Used when the handle shouldn't wait to be hit before following the finger -->
+        <attr name="alwaysTrackFinger"/>
+    </declare-styleable>
+
+    <!-- =============================== -->
     <!-- MultiWaveView class attributes -->
     <!-- =============================== -->
     <eat-comment />
@@ -5393,22 +5438,6 @@
         <!-- Sets a drawable as the drag center. -->
         <attr name="handleDrawable" format="reference" />
 
-        <!-- Drawable to use for chevron animation on the left. May be null.
-            @deprecated use chevronDrawables instead -->
-        <attr name="leftChevronDrawable" format="reference" />
-
-        <!-- Drawable to use for chevron animation on the right. May be null.
-            @deprecated use chevronDrawables instead -->
-        <attr name="rightChevronDrawable" format="reference" />
-
-        <!-- Drawable to use for chevron animation on the top. May be null.
-            @deprecated use chevronDrawables instead -->
-        <attr name="topChevronDrawable" format="reference" />
-
-        <!-- Drawable to use for chevron animation on the bottom. May be null.
-            @deprecated use chevronDrawables instead -->
-        <attr name="bottomChevronDrawable" format="reference" />
-
         <!-- Drawables to use for chevron animations. May be null. -->
         <attr name="chevronDrawables" format="reference"/>
 
@@ -5418,9 +5447,6 @@
         <!-- Outer radius of target circle. Icons will be drawn on this circle. -->
         <attr name="outerRadius" format="dimension" />
 
-        <!-- Size of target radius. Points within this distance of target center is a "hit". -->
-        <attr name="hitRadius" format="dimension" />
-
         <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
         <attr name="vibrationDuration" format="integer"/>
 
@@ -5430,17 +5456,6 @@
         <!-- Number of waves/chevrons to show in animation. -->
         <attr name="feedbackCount" format="integer" />
 
-        <!-- {@deprecated Not used by the framework. Use android:gravity instead}
-            Used to shift center of pattern vertically. -->
-        <attr name="verticalOffset" format="dimension" />
-
-        <!-- {@deprecated Not used by the framework. Use android:gravity instead}
-            Used to shift center of pattern horizontally. -->
-        <attr name="horizontalOffset" format="dimension" />
-
-        <!-- How the items in this layout should be positioned -->
-        <attr name="gravity" />
-
         <!-- Used when the handle shouldn't wait to be hit before following the finger -->
         <attr name="alwaysTrackFinger" format="boolean" />
     </declare-styleable>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d549644..f30943a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -73,14 +73,17 @@
     <!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_outerring_diameter">270dp</dimen>
 
-    <!-- Default target placement radius for MultiWaveView -->
-    <dimen name="multiwaveview_target_placement_radius">135dip</dimen>
+    <!-- Default target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
+    <dimen name="glowpadview_target_placement_radius">135dip</dimen>
 
-    <!-- Default distance beyond which MultiWaveView snaps to the target radius -->
-    <dimen name="multiwaveview_snap_margin">20dip</dimen>
+    <!-- Default glow radius for GlowPadView -->
+    <dimen name="glowpadview_glow_radius">75dip</dimen>
 
-    <!-- Default distance from each snap target that MultiWaveView considers a "hit" -->
-    <dimen name="multiwaveview_hit_radius">60dip</dimen>
+    <!-- Default distance beyond which GlowPadView snaps to the matching target -->
+    <dimen name="glowpadview_snap_margin">40dip</dimen>
+
+    <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
+    <dimen name="glowpadview_inner_radius">15dip</dimen>
 
     <!-- Preference activity side margins -->
     <dimen name="preference_screen_side_margin">0dp</dimen>
@@ -228,10 +231,10 @@
          a few are present. -->
     <dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
 
-	<!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
+    <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
     <dimen name="notification_text_size">14dp</dimen>
-	<!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
+    <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
     <dimen name="notification_title_text_size">18dp</dimen>
-	<!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
+    <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
     <dimen name="notification_subtext_size">12dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e1f15cf..a6f2f49 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1166,6 +1166,15 @@
 
   <java-symbol type="attr" name="mediaRouteButtonStyle" />
   <java-symbol type="attr" name="externalRouteEnabledDrawable" />
+  <java-symbol type="id" name="extended_settings" />
+  <java-symbol type="id" name="check" />
+  <java-symbol type="layout" name="media_route_chooser_layout" />
+  <java-symbol type="layout" name="media_route_list_item_top_header" />
+  <java-symbol type="layout" name="media_route_list_item_section_header" />
+  <java-symbol type="layout" name="media_route_list_item" />
+  <java-symbol type="layout" name="media_route_list_item_checkable" />
+  <java-symbol type="layout" name="media_route_list_item_collapse_group" />
+  <java-symbol type="string" name="bluetooth_a2dp_audio_route_name" />
 
   <!-- From android.policy -->
   <java-symbol type="anim" name="app_starting_exit" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9861bae..da4d37a 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2705,11 +2705,9 @@
     <string name="editTextMenuTitle">Text actions</string>
 
     <!-- If the device is getting low on internal storage, a notification is shown to the user.  This is the title of that notification. -->
-    <string name="low_internal_storage_view_title">Low on space</string>
+    <string name="low_internal_storage_view_title">Storage space running out</string>
     <!-- If the device is getting low on internal storage, a notification is shown to the user.  This is the message of that notification. -->
-    <string name="low_internal_storage_view_text" product="tablet">Tablet storage space is getting low.</string>
-    <!-- If the device is getting low on internal storage, a notification is shown to the user.  This is the message of that notification. -->
-    <string name="low_internal_storage_view_text" product="default">Phone storage space is getting low.</string>
+    <string name="low_internal_storage_view_text">Some system functions may not work</string>
 
     <!-- Preference framework strings. -->
     <string name="ok">OK</string>
@@ -3553,24 +3551,29 @@
     <string name="activity_resolver_use_once">Just once</string>
 
     <!-- Name of the default audio route for tablets when nothing
-         is connected to a headphone or other wired audio output jack. [CHAR LIMIT=25] -->
+         is connected to a headphone or other wired audio output jack. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name" product="tablet">Tablet speakers</string>
 
     <!-- Name of the default audio route when nothing is connected to
-         a headphone or other wired audio output jack. [CHAR LIMIT=25] -->
+         a headphone or other wired audio output jack. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name" product="default">Phone speaker</string>
 
     <!-- Name of the default audio route when wired headphones are
-         connected. [CHAR LIMIT=25] -->
+         connected. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name_headphones">Headphones</string>
 
-    <!-- Name of the default audio route when an audio dock is connected. [CHAR LIMIT=25] -->
+    <!-- Name of the default audio route when an audio dock is connected. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name_dock_speakers">Dock speakers</string>
 
-    <!-- Name of the default audio route when HDMI is connected. [CHAR LIMIT=25] -->
+    <!-- Name of the default audio route when HDMI is connected. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name_hdmi">HDMI audio</string>
 
-    <!-- Name of the default audio route category. [CHAR LIMIT=25] -->
+    <!-- Name of the default audio route category. [CHAR LIMIT=50] -->
     <string name="default_audio_route_category_name">System</string>
 
+    <!-- Default name of the bluetooth a2dp audio route. [CHAR LIMIT=50] -->
+    <string name="bluetooth_a2dp_audio_route_name">Bluetooth audio</string>
+
+    <!-- "Done" button for MediaRouter chooser dialog when grouping routes. [CHAR LIMIT=NONE] -->
+    <string name="media_route_chooser_grouping_done">Done</string>
 </resources>
diff --git a/data/sounds/ringtones/ogg/Themos.ogg b/data/sounds/ringtones/ogg/Themos.ogg
index bc850b8..4ddc71c 100644
--- a/data/sounds/ringtones/ogg/Themos.ogg
+++ b/data/sounds/ringtones/ogg/Themos.ogg
Binary files differ
diff --git a/data/sounds/ringtones/wav/Themos.wav b/data/sounds/ringtones/wav/Themos.wav
index d4d5c6e..fa3178f 100644
--- a/data/sounds/ringtones/wav/Themos.wav
+++ b/data/sounds/ringtones/wav/Themos.wav
Binary files differ
diff --git a/data/videos/VideoPackage1.mk b/data/videos/VideoPackage1.mk
index 407a76e..0089657 100644
--- a/data/videos/VideoPackage1.mk
+++ b/data/videos/VideoPackage1.mk
@@ -23,6 +23,4 @@
         $(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \
         $(LOCAL_PATH)/AndroidInSpace.480p.lq.mp4:$(TARGET_PATH)/AndroidInSpace.480p.mp4 \
         $(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4 \
-        $(LOCAL_PATH)/Sunset.480p.lq.mp4:$(TARGET_PATH)/Sunset.480p.mp4 \
-        $(LOCAL_PATH)/Disco.240p.mp4:$(TARGET_PATH)/Disco.240p.mp4 \
-        $(LOCAL_PATH)/Disco.480p.lq.mp4:$(TARGET_PATH)/Disco.480p.mp4
+        $(LOCAL_PATH)/Sunset.480p.lq.mp4:$(TARGET_PATH)/Sunset.480p.mp4
diff --git a/data/videos/VideoPackage2.mk b/data/videos/VideoPackage2.mk
index c256a2d..b53fd9f 100644
--- a/data/videos/VideoPackage2.mk
+++ b/data/videos/VideoPackage2.mk
@@ -23,6 +23,4 @@
         $(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \
         $(LOCAL_PATH)/AndroidInSpace.480p.mq.mp4:$(TARGET_PATH)/AndroidInSpace.480p.mp4 \
         $(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4 \
-        $(LOCAL_PATH)/Sunset.480p.mq.mp4:$(TARGET_PATH)/Sunset.480p.mp4 \
-        $(LOCAL_PATH)/Disco.240p.mp4:$(TARGET_PATH)/Disco.240p.mp4 \
-        $(LOCAL_PATH)/Disco.480p.mq.mp4:$(TARGET_PATH)/Disco.480p.mp4
+        $(LOCAL_PATH)/Sunset.480p.mq.mp4:$(TARGET_PATH)/Sunset.480p.mp4
diff --git a/include/androidfw/KeycodeLabels.h b/include/androidfw/KeycodeLabels.h
index 1828062..538949d 100755
--- a/include/androidfw/KeycodeLabels.h
+++ b/include/androidfw/KeycodeLabels.h
@@ -243,6 +243,7 @@
     { "YEN", 216 },
     { "RO", 217 },
     { "KANA", 218 },
+    { "ASSIST", 219 },
 
     // 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/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index a0bf8e3..0d6e62a 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -598,6 +598,7 @@
         glGenTextures(1, &cacheTexture->mTextureId);
     }
 
+    Caches::getInstance().activeTexture(0);
     glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     // Initialize texture dimensions
@@ -826,6 +827,7 @@
         }
     }
 
+    caches.activeTexture(0);
     glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
     if (mLinearFiltering != mCurrentCacheTexture->mLinearFiltering) {
         const GLenum filtering = mLinearFiltering ? GL_LINEAR : GL_NEAREST;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0d857bf..c92bead 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2422,6 +2422,7 @@
         linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
     }
 
+    // The font renderer will always use texture unit 0
     mCaches.activeTexture(0);
     setupDraw();
     setupDrawDirtyRegionsDisabled();
@@ -2432,6 +2433,8 @@
     setupDrawBlending(true, mode);
     setupDrawProgram();
     setupDrawModelView(x, y, x, y, pureTranslate, true);
+    // See comment above; the font renderer must use texture unit 0
+    // assert(mTextureUnit == 0)
     setupDrawTexture(fontRenderer.getTexture(linearFilter));
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 133f30b..70fc623 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -97,7 +97,7 @@
 
     boolean isBluetoothScoOn();
 
-    oneway void setBluetoothA2dpOn(boolean on);
+    void setBluetoothA2dpOn(boolean on);
 
     boolean isBluetoothA2dpOn();
 
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 7e4ca6a..9e70b7f 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -21,37 +21,75 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * MediaRouter allows applications to control the routing of media channels
  * and streams from the current device to external speakers and destination devices.
  *
- * <p>Media routes should only be modified on your application's main thread.</p>
+ * <p>A MediaRouter is retrieved through {@link Context#getSystemService(String)
+ * Context.getSystemService()} of a {@link Context#MEDIA_ROUTER_SERVICE
+ * Context.MEDIA_ROUTER_SERVICE}.
+ *
+ * <p>The media router API is not thread-safe; all interactions with it must be
+ * done from the main thread of the process.</p>
  */
 public class MediaRouter {
     private static final String TAG = "MediaRouter";
 
-    private Context mAppContext;
-    private AudioManager mAudioManager;
-    private Handler mHandler;
-    private final ArrayList<CallbackInfo> mCallbacks = new ArrayList<CallbackInfo>();
+    static class Static {
+        final Resources mResources;
+        final AudioManager mAudioManager;
+        final Handler mHandler;
+        final ArrayList<CallbackInfo> mCallbacks = new ArrayList<CallbackInfo>();
 
-    private final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
-    private final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
+        final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
+        final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
 
-    private final RouteCategory mSystemCategory;
-    private RouteInfo mDefaultAudio;
-    private RouteInfo mBluetoothA2dpRoute;
+        final RouteCategory mSystemCategory;
+        final HeadphoneChangedBroadcastReceiver mHeadphoneChangedReceiver;
 
-    private RouteInfo mSelectedRoute;
+        RouteInfo mDefaultAudio;
+        RouteInfo mBluetoothA2dpRoute;
 
-    // These get removed when an activity dies
-    final ArrayList<BroadcastReceiver> mRegisteredReceivers = new ArrayList<BroadcastReceiver>();
+        RouteInfo mSelectedRoute;
+
+        Static(Context appContext) {
+            mResources = Resources.getSystem();
+            mHandler = new Handler(appContext.getMainLooper());
+
+            mAudioManager = (AudioManager)appContext.getSystemService(Context.AUDIO_SERVICE);
+
+            // XXX this doesn't deal with locale changes!
+            mSystemCategory = new RouteCategory(mResources.getText(
+                    com.android.internal.R.string.default_audio_route_category_name),
+                    ROUTE_TYPE_LIVE_AUDIO, false);
+
+            final IntentFilter speakerFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+            speakerFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
+            speakerFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
+            speakerFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
+            mHeadphoneChangedReceiver = new HeadphoneChangedBroadcastReceiver();
+            appContext.registerReceiver(mHeadphoneChangedReceiver, speakerFilter);
+        }
+
+        // Called after sStatic is initialized
+        void initDefaultRoutes() {
+            mDefaultAudio = new RouteInfo(mSystemCategory);
+            mDefaultAudio.mNameResId = com.android.internal.R.string.default_audio_route_name;
+            mDefaultAudio.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
+            addRoute(mDefaultAudio);
+        }
+    }
+
+    static Static sStatic;
 
     /**
      * Route type flag for live audio.
@@ -78,25 +116,6 @@
     // Maps application contexts
     static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>();
 
-    /**
-     * Return a MediaRouter for the application that the specified Context belongs to.
-     * The behavior or availability of media routing may depend on
-     * various parameters of the context.
-     *
-     * @param context Context for the desired router
-     * @return Router for the supplied Context
-     */
-    public static MediaRouter forApplication(Context context) {
-        final Context appContext = context.getApplicationContext();
-        if (!sRouters.containsKey(appContext)) {
-            final MediaRouter r = new MediaRouter(appContext);
-            sRouters.put(appContext, r);
-            return r;
-        } else {
-            return sRouters.get(appContext);
-        }
-    }
-
     static String typesToString(int types) {
         final StringBuilder result = new StringBuilder();
         if ((types & ROUTE_TYPE_LIVE_AUDIO) != 0) {
@@ -108,63 +127,21 @@
         return result.toString();
     }
 
-    private MediaRouter(Context context) {
-        mAppContext = context;
-        mHandler = new Handler(mAppContext.getMainLooper());
-
-        mAudioManager = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE);
-
-        mSystemCategory = new RouteCategory(mAppContext.getText(
-                com.android.internal.R.string.default_audio_route_category_name),
-                ROUTE_TYPE_LIVE_AUDIO, false);
-
-        registerReceivers();
-
-        createDefaultRoutes();
-    }
-
-    private void registerReceivers() {
-        final BroadcastReceiver volumeReceiver = new VolumeChangedBroadcastReceiver();
-        mAppContext.registerReceiver(volumeReceiver,
-                new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
-        mRegisteredReceivers.add(volumeReceiver);
-
-        final IntentFilter speakerFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
-        speakerFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
-        speakerFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
-        speakerFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
-        final BroadcastReceiver plugReceiver = new HeadphoneChangedBroadcastReceiver();
-        mAppContext.registerReceiver(plugReceiver, speakerFilter);
-        mRegisteredReceivers.add(plugReceiver);
-    }
-
-    void unregisterReceivers() {
-        final int count = mRegisteredReceivers.size();
-        for (int i = 0; i < count; i++) {
-            final BroadcastReceiver r = mRegisteredReceivers.get(i);
-            mAppContext.unregisterReceiver(r);
+    /** @hide */
+    public MediaRouter(Context context) {
+        synchronized (Static.class) {
+            if (sStatic == null) {
+                sStatic = new Static(context.getApplicationContext());
+                sStatic.initDefaultRoutes();
+            }
         }
-        mRegisteredReceivers.clear();
-    }
-
-    private void createDefaultRoutes() {
-        mDefaultAudio = new RouteInfo(mSystemCategory);
-        mDefaultAudio.mName = mAppContext.getText(
-                com.android.internal.R.string.default_audio_route_name);
-        mDefaultAudio.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
-        final int maxMusicVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
-        if (maxMusicVolume > 0) {
-            mDefaultAudio.mVolume =
-                    mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) / maxMusicVolume;
-        }
-        addRoute(mDefaultAudio);
     }
 
     /**
      * @hide for use by framework routing UI
      */
     public RouteInfo getSystemAudioRoute() {
-        return mDefaultAudio;
+        return sStatic.mDefaultAudio;
     }
 
     /**
@@ -174,30 +151,20 @@
      * @return the selected route
      */
     public RouteInfo getSelectedRoute(int type) {
-        return mSelectedRoute;
+        return sStatic.mSelectedRoute;
     }
 
-    void onHeadphonesPlugged(boolean headphonesPresent, String headphonesName) {
-        mDefaultAudio.mName = headphonesPresent ? headphonesName : mAppContext.getText(
-                com.android.internal.R.string.default_audio_route_name);
-        dispatchRouteChanged(mDefaultAudio);
-    }
+    static void onHeadphonesPlugged(boolean headphonesPresent, String headphonesName) {
+        if (headphonesPresent) {
+            sStatic.mDefaultAudio.mName = headphonesName;
+            sStatic.mDefaultAudio.mNameResId = 0;
+        } else {
+            sStatic.mDefaultAudio.mName = null;
+            sStatic.mDefaultAudio.mNameResId =
+                    com.android.internal.R.string.default_audio_route_name;
+        }
 
-    /**
-     * Set volume for the specified selected route types.
-     *
-     * @param types Volume will be set for these route types
-     * @param volume Volume to set in the range 0.f (inaudible) to 1.f (full volume).
-     */
-    public void setSelectedRouteVolume(int types, float volume) {
-        if ((types & ROUTE_TYPE_LIVE_AUDIO) != 0 && mSelectedRoute == mDefaultAudio) {
-            final int index = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
-            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
-        }
-        if ((types & ROUTE_TYPE_USER) != 0 && mSelectedRoute instanceof UserRouteInfo) {
-            mSelectedRoute.mVolume = volume;
-            dispatchVolumeChanged(ROUTE_TYPE_USER, volume);
-        }
+        dispatchRouteChanged(sStatic.mDefaultAudio);
     }
 
     /**
@@ -209,15 +176,15 @@
      * @param cb Callback to add
      */
     public void addCallback(int types, Callback cb) {
-        final int count = mCallbacks.size();
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo info = mCallbacks.get(i);
+            final CallbackInfo info = sStatic.mCallbacks.get(i);
             if (info.cb == cb) {
                 info.type &= types;
                 return;
             }
         }
-        mCallbacks.add(new CallbackInfo(cb, types));
+        sStatic.mCallbacks.add(new CallbackInfo(cb, types, this));
     }
 
     /**
@@ -226,24 +193,50 @@
      * @param cb Callback to remove
      */
     public void removeCallback(Callback cb) {
-        final int count = mCallbacks.size();
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            if (mCallbacks.get(i).cb == cb) {
-                mCallbacks.remove(i);
+            if (sStatic.mCallbacks.get(i).cb == cb) {
+                sStatic.mCallbacks.remove(i);
                 return;
             }
         }
         Log.w(TAG, "removeCallback(" + cb + "): callback not registered");
     }
 
+    /**
+     * Select the specified route to use for output of the given media types.
+     *
+     * @param types type flags indicating which types this route should be used for.
+     *              The route must support at least a subset.
+     * @param route Route to select
+     */
     public void selectRoute(int types, RouteInfo route) {
-        if (mSelectedRoute == route) return;
+        // Applications shouldn't programmatically change anything but user routes.
+        types &= ROUTE_TYPE_USER;
+        selectRouteStatic(types, route);
+    }
+    
+    /**
+     * @hide internal use
+     */
+    public void selectRouteInt(int types, RouteInfo route) {
+        selectRouteStatic(types, route);
+    }
 
-        if (mSelectedRoute != null) {
-            // TODO filter types properly
-            dispatchRouteUnselected(types & mSelectedRoute.getSupportedTypes(), mSelectedRoute);
+    static void selectRouteStatic(int types, RouteInfo route) {
+        if (sStatic.mSelectedRoute == route) return;
+        if ((route.getSupportedTypes() & types) == 0) {
+            Log.w(TAG, "selectRoute ignored; cannot select route with supported types " +
+                    typesToString(route.getSupportedTypes()) + " into route types " +
+                    typesToString(types));
         }
-        mSelectedRoute = route;
+
+        if (sStatic.mSelectedRoute != null) {
+            // TODO filter types properly
+            dispatchRouteUnselected(types & sStatic.mSelectedRoute.getSupportedTypes(),
+                    sStatic.mSelectedRoute);
+        }
+        sStatic.mSelectedRoute = route;
         if (route != null) {
             // TODO filter types properly
             dispatchRouteSelected(types & route.getSupportedTypes(), route);
@@ -262,22 +255,34 @@
         addRoute(info);
     }
 
-    void addRoute(RouteInfo info) {
+    /**
+     * @hide Framework use only
+     */
+    public void addRouteInt(RouteInfo info) {
+        addRoute(info);
+    }
+
+    static void addRoute(RouteInfo info) {
         final RouteCategory cat = info.getCategory();
-        if (!mCategories.contains(cat)) {
-            mCategories.add(cat);
+        if (!sStatic.mCategories.contains(cat)) {
+            sStatic.mCategories.add(cat);
         }
-        if (info.getCategory().isGroupable() && !(info instanceof RouteGroup)) {
+        final boolean onlyRoute = sStatic.mRoutes.isEmpty();
+        if (cat.isGroupable() && !(info instanceof RouteGroup)) {
             // Enforce that any added route in a groupable category must be in a group.
             final RouteGroup group = new RouteGroup(info.getCategory());
+            sStatic.mRoutes.add(group);
+            dispatchRouteAdded(group);
             group.addRoute(info);
+
             info = group;
+        } else {
+            sStatic.mRoutes.add(info);
+            dispatchRouteAdded(info);
         }
-        final boolean onlyRoute = mRoutes.isEmpty();
-        mRoutes.add(info);
-        dispatchRouteAdded(info);
+
         if (onlyRoute) {
-            selectRoute(info.getSupportedTypes(), info);
+            selectRouteStatic(info.getSupportedTypes(), info);
         }
     }
 
@@ -297,49 +302,68 @@
      * @see #removeUserRoute(UserRouteInfo)
      */
     public void clearUserRoutes() {
-        for (int i = 0; i < mRoutes.size(); i++) {
-            final RouteInfo info = mRoutes.get(i);
-            if (info instanceof UserRouteInfo) {
+        for (int i = 0; i < sStatic.mRoutes.size(); i++) {
+            final RouteInfo info = sStatic.mRoutes.get(i);
+            // TODO Right now, RouteGroups only ever contain user routes.
+            // The code below will need to change if this assumption does.
+            if (info instanceof UserRouteInfo || info instanceof RouteGroup) {
                 removeRouteAt(i);
                 i--;
             }
         }
     }
 
-    void removeRoute(RouteInfo info) {
-        if (mRoutes.remove(info)) {
+    /**
+     * @hide internal use only
+     */
+    public void removeRouteInt(RouteInfo info) {
+        removeRoute(info);
+    }
+
+    static void removeRoute(RouteInfo info) {
+        if (sStatic.mRoutes.remove(info)) {
             final RouteCategory removingCat = info.getCategory();
-            final int count = mRoutes.size();
+            final int count = sStatic.mRoutes.size();
             boolean found = false;
             for (int i = 0; i < count; i++) {
-                final RouteCategory cat = mRoutes.get(i).getCategory();
+                final RouteCategory cat = sStatic.mRoutes.get(i).getCategory();
                 if (removingCat == cat) {
                     found = true;
                     break;
                 }
             }
+            if (info == sStatic.mSelectedRoute) {
+                // Removing the currently selected route? Select the default before we remove it.
+                // TODO: Be smarter about the route types here; this selects for all valid.
+                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+            }
             if (!found) {
-                mCategories.remove(removingCat);
+                sStatic.mCategories.remove(removingCat);
             }
             dispatchRouteRemoved(info);
         }
     }
 
     void removeRouteAt(int routeIndex) {
-        if (routeIndex >= 0 && routeIndex < mRoutes.size()) {
-            final RouteInfo info = mRoutes.remove(routeIndex);
+        if (routeIndex >= 0 && routeIndex < sStatic.mRoutes.size()) {
+            final RouteInfo info = sStatic.mRoutes.remove(routeIndex);
             final RouteCategory removingCat = info.getCategory();
-            final int count = mRoutes.size();
+            final int count = sStatic.mRoutes.size();
             boolean found = false;
             for (int i = 0; i < count; i++) {
-                final RouteCategory cat = mRoutes.get(i).getCategory();
+                final RouteCategory cat = sStatic.mRoutes.get(i).getCategory();
                 if (removingCat == cat) {
                     found = true;
                     break;
                 }
             }
+            if (info == sStatic.mSelectedRoute) {
+                // Removing the currently selected route? Select the default before we remove it.
+                // TODO: Be smarter about the route types here; this selects for all valid.
+                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+            }
             if (!found) {
-                mCategories.remove(removingCat);
+                sStatic.mCategories.remove(removingCat);
             }
             dispatchRouteRemoved(info);
         }
@@ -352,7 +376,7 @@
      * @return the number of unique categories represented by this MediaRouter's known routes
      */
     public int getCategoryCount() {
-        return mCategories.size();
+        return sStatic.mCategories.size();
     }
 
     /**
@@ -363,7 +387,7 @@
      * @return the category at index
      */
     public RouteCategory getCategoryAt(int index) {
-        return mCategories.get(index);
+        return sStatic.mCategories.get(index);
     }
 
     /**
@@ -373,7 +397,7 @@
      * @return the number of routes tracked by this router
      */
     public int getRouteCount() {
-        return mRoutes.size();
+        return sStatic.mRoutes.size();
     }
 
     /**
@@ -383,7 +407,15 @@
      * @return the route at index
      */
     public RouteInfo getRouteAt(int index) {
-        return mRoutes.get(index);
+        return sStatic.mRoutes.get(index);
+    }
+
+    static int getRouteCountStatic() {
+        return sStatic.mRoutes.size();
+    }
+
+    static RouteInfo getRouteAtStatic(int index) {
+        return sStatic.mRoutes.get(index);
     }
 
     /**
@@ -410,97 +442,120 @@
     public RouteCategory createRouteCategory(CharSequence name, boolean isGroupable) {
         return new RouteCategory(name, ROUTE_TYPE_USER, isGroupable);
     }
+    
+    /**
+     * Create a new route category. Each route must belong to a category.
+     *
+     * @param nameResId Resource ID of the name of the new category
+     * @param isGroupable true if routes in this category may be grouped with one another
+     * @return the new RouteCategory
+     */
+    public RouteCategory createRouteCategory(int nameResId, boolean isGroupable) {
+        return new RouteCategory(nameResId, ROUTE_TYPE_USER, isGroupable);
+    }
 
-    void updateRoute(final RouteInfo info) {
+    static void updateRoute(final RouteInfo info) {
         dispatchRouteChanged(info);
     }
 
-    void dispatchRouteSelected(int type, RouteInfo info) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteSelected(int type, RouteInfo info) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
             if ((cbi.type & type) != 0) {
-                cbi.cb.onRouteSelected(type, info);
+                cbi.cb.onRouteSelected(cbi.router, type, info);
             }
         }
     }
 
-    void dispatchRouteUnselected(int type, RouteInfo info) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteUnselected(int type, RouteInfo info) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
             if ((cbi.type & type) != 0) {
-                cbi.cb.onRouteUnselected(type, info);
+                cbi.cb.onRouteUnselected(cbi.router, type, info);
             }
         }
     }
 
-    void dispatchRouteChanged(RouteInfo info) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteChanged(RouteInfo info) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
             if ((cbi.type & info.mSupportedTypes) != 0) {
-                cbi.cb.onRouteChanged(info);
+                cbi.cb.onRouteChanged(cbi.router, info);
             }
         }
     }
 
-    void dispatchRouteAdded(RouteInfo info) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteAdded(RouteInfo info) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
             if ((cbi.type & info.mSupportedTypes) != 0) {
-                cbi.cb.onRouteAdded(info.mSupportedTypes, info);
+                cbi.cb.onRouteAdded(cbi.router, info);
             }
         }
     }
 
-    void dispatchRouteRemoved(RouteInfo info) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteRemoved(RouteInfo info) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
             if ((cbi.type & info.mSupportedTypes) != 0) {
-                cbi.cb.onRouteRemoved(info.mSupportedTypes, info);
+                cbi.cb.onRouteRemoved(cbi.router, info);
             }
         }
     }
 
-    void dispatchVolumeChanged(int type, float volume) {
-        final int count = mCallbacks.size();
+    static void dispatchRouteGrouped(RouteInfo info, RouteGroup group, int index) {
+        final int count = sStatic.mCallbacks.size();
         for (int i = 0; i < count; i++) {
-            final CallbackInfo cbi = mCallbacks.get(i);
-            if ((cbi.type & type) != 0) {
-                cbi.cb.onVolumeChanged(type, volume);
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
+            if ((cbi.type & group.mSupportedTypes) != 0) {
+                cbi.cb.onRouteGrouped(cbi.router, info, group, index);
             }
         }
     }
 
-    void onA2dpDeviceConnected() {
-        final RouteInfo info = new RouteInfo(mSystemCategory);
-        info.mName = "Bluetooth"; // TODO Fetch the real name of the device
-        mBluetoothA2dpRoute = info;
-        addRoute(mBluetoothA2dpRoute);
+    static void dispatchRouteUngrouped(RouteInfo info, RouteGroup group) {
+        final int count = sStatic.mCallbacks.size();
+        for (int i = 0; i < count; i++) {
+            final CallbackInfo cbi = sStatic.mCallbacks.get(i);
+            if ((cbi.type & group.mSupportedTypes) != 0) {
+                cbi.cb.onRouteUngrouped(cbi.router, info, group);
+            }
+        }
     }
 
-    void onA2dpDeviceDisconnected() {
-        removeRoute(mBluetoothA2dpRoute);
-        mBluetoothA2dpRoute = null;
+    static void onA2dpDeviceConnected() {
+        final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
+        info.mNameResId = com.android.internal.R.string.bluetooth_a2dp_audio_route_name;
+        sStatic.mBluetoothA2dpRoute = info;
+        addRoute(sStatic.mBluetoothA2dpRoute);
+    }
+
+    static void onA2dpDeviceDisconnected() {
+        removeRoute(sStatic.mBluetoothA2dpRoute);
+        sStatic.mBluetoothA2dpRoute = null;
     }
 
     /**
      * Information about a media route.
      */
-    public class RouteInfo {
+    public static class RouteInfo {
         CharSequence mName;
+        int mNameResId;
         private CharSequence mStatus;
         int mSupportedTypes;
         RouteGroup mGroup;
         final RouteCategory mCategory;
-        float mVolume;
+        Drawable mIcon;
+
+        private Object mTag;
 
         RouteInfo(RouteCategory category) {
             mCategory = category;
-            category.mRoutes.add(this);
         }
 
         /**
@@ -508,6 +563,24 @@
          * to users who may select this as the active route.
          */
         public CharSequence getName() {
+            return getName(sStatic.mResources);
+        }
+        
+        /**
+         * Return the properly localized/resource selected name of this route.
+         * 
+         * @param context Context used to resolve the correct configuration to load
+         * @return The user-friendly name of the media route. This is the string presented
+         * to users who may select this as the active route.
+         */
+        public CharSequence getName(Context context) {
+            return getName(context.getResources());
+        }
+        
+        CharSequence getName(Resources res) {
+            if (mNameResId != 0) {
+                return mName = res.getText(mNameResId);
+            }
             return mName;
         }
 
@@ -541,10 +614,36 @@
         }
 
         /**
-         * @return This route's current volume setting.
+         * Get the icon representing this route.
+         * This icon will be used in picker UIs if available.
+         *
+         * @return the icon representing this route or null if no icon is available
          */
-        public float getVolume() {
-            return mVolume;
+        public Drawable getIconDrawable() {
+            return mIcon;
+        }
+
+        /**
+         * Set an application-specific tag object for this route.
+         * The application may use this to store arbitrary data associated with the
+         * route for internal tracking.
+         *
+         * <p>Note that the lifespan of a route may be well past the lifespan of
+         * an Activity or other Context; take care that objects you store here
+         * will not keep more data in memory alive than you intend.</p>
+         *
+         * @param tag Arbitrary, app-specific data for this route to hold for later use
+         */
+        public void setTag(Object tag) {
+            mTag = tag;
+        }
+
+        /**
+         * @return The tag object previously set by the application
+         * @see #setTag(Object)
+         */
+        public Object getTag() {
+            return mTag;
         }
 
         void setStatusInt(CharSequence status) {
@@ -564,9 +663,9 @@
 
         @Override
         public String toString() {
-            String supportedTypes = typesToString(mSupportedTypes);
-            return "RouteInfo{ name=" + mName + ", status=" + mStatus +
-                    " category=" + mCategory +
+            String supportedTypes = typesToString(getSupportedTypes());
+            return getClass().getSimpleName() + "{ name=" + getName() + ", status=" + getStatus() +
+                    " category=" + getCategory() +
                     " supportedTypes=" + supportedTypes + "}";
         }
     }
@@ -576,7 +675,8 @@
      *
      * @see MediaRouter.RouteInfo
      */
-    public class UserRouteInfo extends RouteInfo {
+    public static class UserRouteInfo extends RouteInfo {
+        RemoteControlClient mRcc;
 
         UserRouteInfo(RouteCategory category) {
             super(category);
@@ -591,6 +691,16 @@
             mName = name;
             routeUpdated();
         }
+        
+        /**
+         * Set the user-visible name of this route.
+         * @param resId Resource ID of the name to display to the user to describe this route
+         */
+        public void setName(int resId) {
+            mNameResId = resId;
+            mName = null;
+            routeUpdated();
+        }
 
         /**
          * Set the current user-visible status for this route.
@@ -600,12 +710,46 @@
         public void setStatus(CharSequence status) {
             setStatusInt(status);
         }
+
+        /**
+         * Set the RemoteControlClient responsible for reporting playback info for this
+         * user route.
+         *
+         * <p>If this route manages remote playback, the data exposed by this
+         * RemoteControlClient will be used to reflect and update information
+         * such as route volume info in related UIs.</p>
+         *
+         * @param rcc RemoteControlClient associated with this route
+         */
+        public void setRemoteControlClient(RemoteControlClient rcc) {
+            mRcc = rcc;
+        }
+
+        /**
+         * Set an icon that will be used to represent this route.
+         * The system may use this icon in picker UIs or similar.
+         *
+         * @param icon icon drawable to use to represent this route
+         */
+        public void setIconDrawable(Drawable icon) {
+            mIcon = icon;
+        }
+
+        /**
+         * Set an icon that will be used to represent this route.
+         * The system may use this icon in picker UIs or similar.
+         *
+         * @param resId Resource ID of an icon drawable to use to represent this route
+         */
+        public void setIconResource(int resId) {
+            setIconDrawable(sStatic.mResources.getDrawable(resId));
+        }
     }
 
     /**
      * Information about a route that consists of multiple other routes in a group.
      */
-    public class RouteGroup extends RouteInfo {
+    public static class RouteGroup extends RouteInfo {
         final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
         private boolean mUpdateName;
 
@@ -614,9 +758,9 @@
             mGroup = this;
         }
 
-        public CharSequence getName() {
+        CharSequence getName(Resources res) {
             if (mUpdateName) updateName();
-            return super.getName();
+            return super.getName(res);
         }
 
         /**
@@ -634,8 +778,11 @@
                             "(Route category=" + route.getCategory() +
                             " group category=" + mCategory + ")");
             }
+            final int at = mRoutes.size();
             mRoutes.add(route);
+            route.mGroup = this;
             mUpdateName = true;
+            dispatchRouteGrouped(route, this, at);
             routeUpdated();
         }
 
@@ -656,7 +803,9 @@
                             " group category=" + mCategory + ")");
             }
             mRoutes.add(insertAt, route);
+            route.mGroup = this;
             mUpdateName = true;
+            dispatchRouteGrouped(route, this, insertAt);
             routeUpdated();
         }
 
@@ -671,7 +820,9 @@
                         " is not a member of this group.");
             }
             mRoutes.remove(route);
+            route.mGroup = null;
             mUpdateName = true;
+            dispatchRouteUngrouped(route, this);
             routeUpdated();
         }
 
@@ -681,11 +832,50 @@
          * @param index index of the route to remove
          */
         public void removeRoute(int index) {
-            mRoutes.remove(index);
+            RouteInfo route = mRoutes.remove(index);
+            route.mGroup = null;
             mUpdateName = true;
+            dispatchRouteUngrouped(route, this);
             routeUpdated();
         }
 
+        /**
+         * @return The number of routes in this group
+         */
+        public int getRouteCount() {
+            return mRoutes.size();
+        }
+
+        /**
+         * Return the route in this group at the specified index
+         *
+         * @param index Index to fetch
+         * @return The route at index
+         */
+        public RouteInfo getRouteAt(int index) {
+            return mRoutes.get(index);
+        }
+
+        /**
+         * Set an icon that will be used to represent this group.
+         * The system may use this icon in picker UIs or similar.
+         *
+         * @param icon icon drawable to use to represent this group
+         */
+        public void setIconDrawable(Drawable icon) {
+            mIcon = icon;
+        }
+
+        /**
+         * Set an icon that will be used to represent this group.
+         * The system may use this icon in picker UIs or similar.
+         *
+         * @param resId Resource ID of an icon drawable to use to represent this group
+         */
+        public void setIconResource(int resId) {
+            setIconDrawable(sStatic.mResources.getDrawable(resId));
+        }
+
         void memberNameChanged(RouteInfo info, CharSequence name) {
             mUpdateName = true;
             routeUpdated();
@@ -695,25 +885,57 @@
             setStatusInt(status);
         }
 
+        @Override
+        void routeUpdated() {
+            int types = 0;
+            final int count = mRoutes.size();
+            if (count == 0) {
+                // Don't keep empty groups in the router.
+                MediaRouter.removeRoute(this);
+                return;
+            }
+
+            for (int i = 0; i < count; i++) {
+                types |= mRoutes.get(i).mSupportedTypes;
+            }
+            mSupportedTypes = types;
+            mIcon = count == 1 ? mRoutes.get(0).getIconDrawable() : null;
+            super.routeUpdated();
+        }
+
         void updateName() {
             final StringBuilder sb = new StringBuilder();
             final int count = mRoutes.size();
             for (int i = 0; i < count; i++) {
                 final RouteInfo info = mRoutes.get(i);
+                // TODO: There's probably a much more correct way to localize this.
                 if (i > 0) sb.append(", ");
                 sb.append(info.mName);
             }
             mName = sb.toString();
             mUpdateName = false;
         }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(super.toString());
+            sb.append('[');
+            final int count = mRoutes.size();
+            for (int i = 0; i < count; i++) {
+                if (i > 0) sb.append(", ");
+                sb.append(mRoutes.get(i));
+            }
+            sb.append(']');
+            return sb.toString();
+        }
     }
 
     /**
      * Definition of a category of routes. All routes belong to a category.
      */
-    public class RouteCategory {
-        final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
+    public static class RouteCategory {
         CharSequence mName;
+        int mNameResId;
         int mTypes;
         final boolean mGroupable;
 
@@ -723,28 +945,64 @@
             mGroupable = groupable;
         }
 
+        RouteCategory(int nameResId, int types, boolean groupable) {
+            mNameResId = nameResId;
+            mTypes = types;
+            mGroupable = groupable;
+        }
+
         /**
          * @return the name of this route category
          */
         public CharSequence getName() {
+            return getName(sStatic.mResources);
+        }
+        
+        /**
+         * Return the properly localized/configuration dependent name of this RouteCategory.
+         * 
+         * @param context Context to resolve name resources
+         * @return the name of this route category
+         */
+        public CharSequence getName(Context context) {
+            return getName(context.getResources());
+        }
+        
+        CharSequence getName(Resources res) {
+            if (mNameResId != 0) {
+                return res.getText(mNameResId);
+            }
             return mName;
         }
 
         /**
-         * @return the number of routes in this category
-         */
-        public int getRouteCount() {
-            return mRoutes.size();
-        }
-
-        /**
-         * Return a route from this category
+         * Return the current list of routes in this category that have been added
+         * to the MediaRouter.
          *
-         * @param index Index from [0-getRouteCount)
-         * @return the route at the given index
+         * <p>This list will not include routes that are nested within RouteGroups.
+         * A RouteGroup is treated as a single route within its category.</p>
+         *
+         * @param out a List to fill with the routes in this category. If this parameter is
+         *            non-null, it will be cleared, filled with the current routes with this
+         *            category, and returned. If this parameter is null, a new List will be
+         *            allocated to report the category's current routes.
+         * @return A list with the routes in this category that have been added to the MediaRouter.
          */
-        public RouteInfo getRouteAt(int index) {
-            return mRoutes.get(index);
+        public List<RouteInfo> getRoutes(List<RouteInfo> out) {
+            if (out == null) {
+                out = new ArrayList<RouteInfo>();
+            } else {
+                out.clear();
+            }
+
+            final int count = getRouteCountStatic();
+            for (int i = 0; i < count; i++) {
+                final RouteInfo route = getRouteAtStatic(i);
+                if (route.mCategory == this) {
+                    out.add(route);
+                }
+            }
+            return out;
         }
 
         /**
@@ -758,7 +1016,7 @@
          * Return whether or not this category supports grouping.
          *
          * <p>If this method returns true, all routes obtained from this category
-         * via calls to {@link #getRouteAt(int)} will be {@link MediaRouter.RouteGroup}s.
+         * via calls to {@link #getRouteAt(int)} will be {@link MediaRouter.RouteGroup}s.</p>
          *
          * @return true if this category supports
          */
@@ -768,17 +1026,19 @@
 
         public String toString() {
             return "RouteCategory{ name=" + mName + " types=" + typesToString(mTypes) +
-                    " groupable=" + mGroupable + " routes=" + mRoutes.size() + " }";
+                    " groupable=" + mGroupable + " }";
         }
     }
 
     static class CallbackInfo {
         public int type;
-        public Callback cb;
+        public final Callback cb;
+        public final MediaRouter router;
 
-        public CallbackInfo(Callback cb, int type) {
+        public CallbackInfo(Callback cb, int type, MediaRouter router) {
             this.cb = cb;
             this.type = type;
+            this.router = router;
         }
     }
 
@@ -792,48 +1052,42 @@
      * @see MediaRouter#addCallback(int, Callback)
      * @see MediaRouter#removeCallback(Callback)
      */
-    public interface Callback {
+    public static abstract class Callback {
         /**
          * Called when the supplied route becomes selected as the active route
          * for the given route type.
          *
+         * @param router the MediaRouter reporting the event
          * @param type Type flag set indicating the routes that have been selected
          * @param info Route that has been selected for the given route types
          */
-        public void onRouteSelected(int type, RouteInfo info);
+        public abstract void onRouteSelected(MediaRouter router, int type, RouteInfo info);
 
         /**
          * Called when the supplied route becomes unselected as the active route
          * for the given route type.
          *
+         * @param router the MediaRouter reporting the event
          * @param type Type flag set indicating the routes that have been unselected
          * @param info Route that has been unselected for the given route types
          */
-        public void onRouteUnselected(int type, RouteInfo info);
-
-        /**
-         * Called when the volume is changed for the specified route types.
-         *
-         * @param type Type flags indicating which volume type was changed
-         * @param volume New volume value in the range 0 (inaudible) to 1 (full)
-         */
-        public void onVolumeChanged(int type, float volume);
+        public abstract void onRouteUnselected(MediaRouter router, int type, RouteInfo info);
 
         /**
          * Called when a route for the specified type was added.
          *
-         * @param type Type flags indicating which types the added route supports
+         * @param router the MediaRouter reporting the event
          * @param info Route that has become available for use
          */
-        public void onRouteAdded(int type, RouteInfo info);
+        public abstract void onRouteAdded(MediaRouter router, RouteInfo info);
 
         /**
          * Called when a route for the specified type was removed.
          *
-         * @param type Type flags indicating which types the removed route supported
+         * @param router the MediaRouter reporting the event
          * @param info Route that has been removed from availability
          */
-        public void onRouteRemoved(int type, RouteInfo info);
+        public abstract void onRouteRemoved(MediaRouter router, RouteInfo info);
 
         /**
          * Called when an aspect of the indicated route has changed.
@@ -841,64 +1095,68 @@
          * <p>This will not indicate that the types supported by this route have
          * changed, only that cosmetic info such as name or status have been updated.</p>
          *
+         * @param router the MediaRouter reporting the event
          * @param info The route that was changed
          */
-        public void onRouteChanged(RouteInfo info);
+        public abstract void onRouteChanged(MediaRouter router, RouteInfo info);
+
+        /**
+         * Called when a route is added to a group.
+         *
+         * @param router the MediaRouter reporting the event
+         * @param info The route that was added
+         * @param group The group the route was added to
+         * @param index The route index within group that info was added at
+         */
+        public abstract void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
+                int index);
+
+        /**
+         * Called when a route is removed from a group.
+         *
+         * @param router the MediaRouter reporting the event
+         * @param info The route that was removed
+         * @param group The group the route was removed from
+         */
+        public abstract void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group);
     }
 
     /**
-     * Stub implementation of the {@link MediaRouter.Callback} interface.
-     * Each interface method is defined as a no-op. Override just the ones
+     * Stub implementation of {@link MediaRouter.Callback}.
+     * Each abstract method is defined as a no-op. Override just the ones
      * you need.
      */
-    public static class SimpleCallback implements Callback {
+    public static class SimpleCallback extends Callback {
 
         @Override
-        public void onRouteSelected(int type, RouteInfo info) {
-
+        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
         }
 
         @Override
-        public void onRouteUnselected(int type, RouteInfo info) {
-
+        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
         }
 
         @Override
-        public void onVolumeChanged(int type, float volume) {
-
+        public void onRouteAdded(MediaRouter router, RouteInfo info) {
         }
 
         @Override
-        public void onRouteAdded(int type, RouteInfo info) {
-
+        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
         }
 
         @Override
-        public void onRouteRemoved(int type, RouteInfo info) {
-
+        public void onRouteChanged(MediaRouter router, RouteInfo info) {
         }
 
         @Override
-        public void onRouteChanged(RouteInfo info) {
-
+        public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
+                int index) {
         }
 
-    }
-
-    class VolumeChangedBroadcastReceiver extends BroadcastReceiver {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (AudioManager.VOLUME_CHANGED_ACTION.equals(action) &&
-                    AudioManager.STREAM_MUSIC == intent.getIntExtra(
-                            AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1)) {
-                final int maxVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
-                final int volExtra = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
-                final float volume = (float) volExtra / maxVol;
-                mDefaultAudio.mVolume = volume;
-                dispatchVolumeChanged(ROUTE_TYPE_LIVE_AUDIO, volume);
-            }
+        public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
         }
+
     }
 
     class BtChangedBroadcastReceiver extends BroadcastReceiver {
@@ -917,24 +1175,24 @@
         }
     }
 
-    class HeadphoneChangedBroadcastReceiver extends BroadcastReceiver {
+    static class HeadphoneChangedBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
             if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
                 final boolean plugged = intent.getIntExtra("state", 0) != 0;
-                final String name = mAppContext.getString(
+                final String name = sStatic.mResources.getString(
                         com.android.internal.R.string.default_audio_route_name_headphones);
                 onHeadphonesPlugged(plugged, name);
             } else if (Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG.equals(action) ||
                     Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG.equals(action)) {
                 final boolean plugged = intent.getIntExtra("state", 0) != 0;
-                final String name = mAppContext.getString(
+                final String name = sStatic.mResources.getString(
                         com.android.internal.R.string.default_audio_route_name_dock_speakers);
                 onHeadphonesPlugged(plugged, name);
             } else if (Intent.ACTION_HDMI_AUDIO_PLUG.equals(action)) {
                 final boolean plugged = intent.getIntExtra("state", 0) != 0;
-                final String name = mAppContext.getString(
+                final String name = sStatic.mResources.getString(
                         com.android.internal.R.string.default_audio_route_name_hdmi);
                 onHeadphonesPlugged(plugged, name);
             }
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
diff --git a/media/jni/mediaeditor/NOTICE b/media/jni/mediaeditor/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/media/jni/mediaeditor/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/media/mca/filterpacks/java/android/filterpacks/videoproc/BackDropperFilter.java b/media/mca/filterpacks/java/android/filterpacks/videoproc/BackDropperFilter.java
index 52c9fda..78f7f3e 100644
--- a/media/mca/filterpacks/java/android/filterpacks/videoproc/BackDropperFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/videoproc/BackDropperFilter.java
@@ -29,6 +29,7 @@
 import android.filterfw.format.ImageFormat;
 import android.opengl.GLES20;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import java.lang.ArrayIndexOutOfBoundsException;
@@ -510,6 +511,20 @@
         super(name);
 
         mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
+
+        String adjStr = SystemProperties.get("ro.media.effect.bgdropper.adj");
+        if (adjStr.length() > 0) {
+            try {
+                mAcceptStddev += Float.parseFloat(adjStr);
+                if (mLogVerbose) {
+                    Log.v(TAG, "Adjusting accept threshold by " + adjStr +
+                            ", now " + mAcceptStddev);
+                }
+            } catch (NumberFormatException e) {
+                Log.e(TAG,
+                        "Badly formatted property ro.media.effect.bgdropper.adj: " + adjStr);
+            }
+        }
     }
 
     @Override
@@ -695,7 +710,6 @@
             mBgUpdateVarianceProgram.setHostValue("bg_adapt_rate", mAdaptRateLearning);
             mBgUpdateVarianceProgram.setHostValue("fg_adapt_rate", mAdaptRateLearning);
             mFrameCount = 0;
-            mStartLearning = false;
         }
 
         // Select correct pingpong buffers
@@ -720,6 +734,11 @@
         mBgInput.setTextureParameter(GLES20.GL_TEXTURE_MIN_FILTER,
                                      GLES20.GL_LINEAR_MIPMAP_NEAREST);
 
+        if (mStartLearning) {
+            copyShaderProgram.process(mVideoInput, mBgMean[inputIndex]);
+            mStartLearning = false;
+        }
+
         // Process shaders
         Frame[] distInputs = { mVideoInput, mBgMean[inputIndex], mBgVariance[inputIndex] };
         mBgDistProgram.process(distInputs, mDistance);
@@ -765,7 +784,12 @@
                 ByteBuffer mMaskAverageByteBuffer = mMaskAverage.getData();
                 byte[] mask_average = mMaskAverageByteBuffer.array();
                 int bi = (int)(mask_average[3] & 0xFF);
-                if (mLogVerbose) Log.v(TAG, String.format("Mask_average is %d", bi));
+
+                if (mLogVerbose) {
+                    Log.v(TAG,
+                            String.format("Mask_average is %d, threshold is %d",
+                                    bi, DEFAULT_LEARNING_DONE_THRESHOLD));
+                }
 
                 if (bi >= DEFAULT_LEARNING_DONE_THRESHOLD) {
                     mStartLearning = true;                                      // Restart learning
diff --git a/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 4c163a2..0000000
--- a/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 21c5abd..0000000
--- a/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 7874c63..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/system_bar_notification_header_bg.xml b/packages/SystemUI/res/drawable/system_bar_notification_header_bg.xml
new file mode 100644
index 0000000..85f1ea2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/system_bar_notification_header_bg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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_pressed="true"  android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
+    <item                               android:drawable="@*android:drawable/list_selector_disabled_holo_dark" />
+</selector>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 8a21117..00e3e27 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -26,7 +26,11 @@
     android:layout_width="match_parent"
     systemui:recentItemLayout="@layout/status_bar_recent_item"
     >
-
+    <View
+        android:id="@+id/recents_transition_background"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="invisible" />
     <FrameLayout
         android:id="@+id/recents_bg_protect"
         android:background="@drawable/status_bar_recents_background"
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index ae81167..c8a120d 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -38,25 +38,28 @@
             android:layout_height="match_parent"
             android:layout_alignParentRight="true">
 
-            <com.android.internal.widget.multiwaveview.MultiWaveView
-                android:id="@+id/multi_wave_view"
+            <com.android.internal.widget.multiwaveview.GlowPadView
+                android:id="@+id/glow_pad_view"
                 android:orientation="vertical"
                 android:layout_width="@dimen/navbar_search_panel_height"
                 android:layout_height="match_parent"
                 android:layout_alignParentBottom="true"
-                android:background="@drawable/navbar_search_bg_scrim"
                 android:gravity="left"
 
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
                 prvandroid:handleDrawable="@drawable/navbar_search_handle"
-                prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+                prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+                prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+                prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
                 prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-                prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
                 prvandroid:feedbackCount="0"
                 prvandroid:vibrationDuration="@integer/config_vibration_duration"
-                prvandroid:alwaysTrackFinger="true"/>
+                prvandroid:alwaysTrackFinger="true"
+                prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+                prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+                />
 
         </RelativeLayout>
 
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index 1d29c5a..a7e5db1 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -26,7 +26,11 @@
     android:layout_width="match_parent"
     systemui:recentItemLayout="@layout/status_bar_recent_item"
     >
-
+    <View
+        android:id="@+id/recents_transition_background"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="invisible" />
     <FrameLayout
         android:id="@+id/recents_bg_protect"
         android:background="@drawable/status_bar_recents_background"
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
index 785d5dd..1e4bb57 100644
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
@@ -38,25 +38,28 @@
             android:layout_height="wrap_content"
             android:layout_alignParentBottom="true">
 
-            <com.android.internal.widget.multiwaveview.MultiWaveView
-                android:id="@+id/multi_wave_view"
+            <com.android.internal.widget.multiwaveview.GlowPadView
+                android:id="@+id/glow_pad_view"
                 android:orientation="horizontal"
                 android:layout_width="match_parent"
                 android:layout_height="@dimen/navbar_search_panel_height"
                 android:layout_alignParentBottom="true"
-                android:background="@drawable/navbar_search_bg_scrim"
                 android:gravity="top"
 
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
                 prvandroid:handleDrawable="@drawable/navbar_search_handle"
-                prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+                prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+                prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+                prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
                 prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-                prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
                 prvandroid:feedbackCount="0"
                 prvandroid:vibrationDuration="@integer/config_vibration_duration"
-                prvandroid:alwaysTrackFinger="true"/>
+                prvandroid:alwaysTrackFinger="true"
+                prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+                prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+               />
 
         </RelativeLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
index 74a15f2..3b6c52e 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
@@ -25,23 +25,25 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
-    <com.android.internal.widget.multiwaveview.MultiWaveView
-        android:id="@+id/multi_wave_view"
+    <com.android.internal.widget.multiwaveview.GlowPadView
+        android:id="@+id/glow_pad_view"
         android:layout_width="wrap_content"
         android:layout_height="@dimen/navbar_search_panel_height"
         android:layout_gravity="center_horizontal|bottom"
         android:gravity="center_horizontal|top"
-        android:background="@drawable/navbar_search_bg_scrim"
 
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
         prvandroid:handleDrawable="@drawable/navbar_search_handle"
-        prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+        prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+        prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+        prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
         prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-        prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
         prvandroid:feedbackCount="0"
         prvandroid:vibrationDuration="@integer/config_vibration_duration"
-        prvandroid:alwaysTrackFinger="true"/>
+        prvandroid:alwaysTrackFinger="true"
+        prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+        prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
 
 </com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
index 2a97307..8c2360e 100644
--- a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
@@ -25,24 +25,26 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
-    <com.android.internal.widget.multiwaveview.MultiWaveView
-        android:id="@+id/multi_wave_view"
+    <com.android.internal.widget.multiwaveview.GlowPadView
+        android:id="@+id/glow_pad_view"
         android:layout_width="wrap_content"
         android:layout_height="@dimen/navbar_search_panel_height"
         android:layout_gravity="left|bottom"
         android:gravity="top|right"
         android:layout_marginLeft="-150dip"
-        android:background="@drawable/navbar_search_bg_scrim"
 
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
         prvandroid:handleDrawable="@drawable/navbar_search_handle"
-        prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+        prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+        prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+        prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
         prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-        prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
         prvandroid:feedbackCount="0"
         prvandroid:vibrationDuration="@integer/config_vibration_duration"
-        prvandroid:alwaysTrackFinger="true"/>
+        prvandroid:alwaysTrackFinger="true"
+        prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+        prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
 
 </com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
index afe3b49..480d979 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
@@ -18,7 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/title_area"
-    android:background="@color/notification_panel_solid_background"
+    android:background="@drawable/system_bar_notification_header_bg"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:clickable="true"
diff --git a/packages/SystemUI/res/layout/system_bar_recent_panel.xml b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
index d5745c8..127551d 100644
--- a/packages/SystemUI/res/layout/system_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
@@ -28,7 +28,11 @@
     android:clipChildren="false"
     systemui:recentItemLayout="@layout/system_bar_recent_item"
     >
-
+    <View
+        android:id="@+id/recents_transition_background"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="invisible" />
     <FrameLayout
         android:id="@+id/recents_bg_protect"
         android:background="@drawable/recents_bg_protect_tile"
@@ -38,7 +42,6 @@
         android:layout_marginBottom="@*android:dimen/system_bar_height"
         android:clipToPadding="false"
         android:clipChildren="false">
-
         <ImageView
             android:id="@+id/recents_transition_placeholder_icon"
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 1bf59b0..2b5248f 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -30,6 +30,9 @@
     <!-- Diameter of outer shape drawable shown in navbar search-->
     <dimen name="navbar_search_outerring_diameter">430dip</dimen>
 
+    <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value. -->
+    <dimen name="navbar_search_outerring_radius">215dip</dimen>
+
     <!-- Height of search panel including navigation bar height -->
     <dimen name="navbar_search_panel_height">280dip</dimen>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3ed63ed..6a96c6b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -87,6 +87,8 @@
     <dimen name="fling_collapse_min_velocity">200dp</dimen>
     <!-- Cap on contribution of x dimension of gesture to overall velocity -->
     <dimen name="fling_gesture_max_x_velocity">200dp</dimen>
+    <!-- Cap on overall resulting fling speed (s^-1) -->
+    <dimen name="fling_gesture_max_output_velocity">3000dp</dimen>
 
     <!-- Minimum fraction of the display a gesture must travel, at any velocity, to qualify as a
          collapse request -->
@@ -108,15 +110,15 @@
     <!-- The width of the view containing the menu status bar icon -->
     <dimen name="navigation_menu_key_width">40dip</dimen>
 
-    <!-- Default distance beyond which snaps to the target radius -->
-    <dimen name="navbar_search_snap_margin">20dip</dimen>
-
-    <!-- Default distance from each snap target considers a "hit" -->
-    <dimen name="navbar_search_hit_radius">60dip</dimen>
+    <!-- Default distance beyond which snaps to the matching target -->
+    <dimen name="navbar_search_snap_margin">40dip</dimen>
 
     <!-- Diameter of outer shape drawable shown in navbar search-->
     <dimen name="navbar_search_outerring_diameter">340dp</dimen>
 
+    <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value -->
+    <dimen name="navbar_search_outerring_radius">170dp</dimen>
+
     <!-- Threshold for swipe-up gesture to activate search dialog -->
     <dimen name="navbar_search_up_threshhold">40dip</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1eb353f..f18e33e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -117,7 +117,7 @@
     </string>
 
     <!-- Separator for PLMN and SPN in network name. -->
-    <string name="status_bar_network_name_separator" translatable="false">"\n"</string>
+    <string name="status_bar_network_name_separator" translatable="false">|</string>
 
     <!-- Network connection string for Bluetooth Reverse Tethering -->
     <string name="bluetooth_tethered">Bluetooth tethered</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index df41d25..48efbc7 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -23,11 +23,14 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
+import android.widget.ScrollView;
+import android.widget.FrameLayout;
 
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
@@ -38,7 +41,7 @@
     }
 
     private static final String TAG = "ExpandHelper";
-    protected static final boolean DEBUG = false;
+    protected static final boolean DEBUG = true;
     private static final long EXPAND_DURATION = 250;
     private static final long GLOW_DURATION = 150;
 
@@ -82,8 +85,11 @@
     private int mLargeSize;
     private float mMaximumStretch;
 
+    private int mGravity;
+
     private class ViewScaler {
         View mView;
+
         public ViewScaler() {}
         public void setView(View v) {
             mView = v;
@@ -119,6 +125,15 @@
         }
     }
 
+    /**
+     * Handle expansion gestures to expand and contract children of the callback.
+     *
+     * @param context application context
+     * @param callback the container that holds the items to be manipulated
+     * @param small the smallest allowable size for the manuipulated items.
+     * @param large the largest allowable size for the manuipulated items.
+     * @param scoller if non-null also manipulate the scroll position to obey the gravity.
+     */
     public ExpandHelper(Context context, Callback callback, int small, int large) {
         mSmallSize = small;
         mMaximumStretch = mSmallSize * STRETCH_INTERVAL;
@@ -126,7 +141,7 @@
         mContext = context;
         mCallback = callback;
         mScaler = new ViewScaler();
-
+        mGravity = Gravity.TOP;
         mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
         mScaleAnimation.setDuration(EXPAND_DURATION);
 
@@ -194,6 +209,7 @@
                 span *= USE_SPAN ? 1f : 0f;
                 float drag = detector.getFocusY() - mInitialTouchFocusY;
                 drag *= USE_DRAG ? 1f : 0f;
+                drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
                 float pull = Math.abs(drag) + Math.abs(span) + 1f;
                 float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
                 if (DEBUG) Log.d(TAG, "current span handle is: " + hand);
@@ -227,6 +243,10 @@
         mEventSource = eventSource;
     }
 
+    public void setGravity(int gravity) {
+        mGravity = gravity;
+    }
+
     public void setGlow(float glow) {
         if (!mGlowAnimationSet.isRunning() || glow == 0f) {
             if (mGlowAnimationSet.isRunning()) {
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 8b8a814..c082c97 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -23,7 +23,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.Vibrator;
 import android.provider.Settings;
@@ -35,8 +34,9 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnPreDrawListener;
 import android.widget.FrameLayout;
-import com.android.internal.widget.multiwaveview.MultiWaveView;
-import com.android.internal.widget.multiwaveview.MultiWaveView.OnTriggerListener;
+
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
 import com.android.systemui.R;
 import com.android.systemui.recent.StatusBarTouchProxy;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -53,12 +53,13 @@
     private static final String ASSIST_ICON_METADATA_NAME =
             "com.android.systemui.action_assist_icon";
     private final Context mContext;
+    private final SearchManager mSearchManager;
     private BaseStatusBar mBar;
     private StatusBarTouchProxy mStatusBarTouchProxy;
 
     private boolean mShowing;
     private View mSearchTargetsContainer;
-    private MultiWaveView mMultiWaveView;
+    private GlowPadView mGlowPadView;
 
     public SearchPanelView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -73,38 +74,12 @@
         }
     }
 
-    private SearchManager mSearchManager;
-
-    // This code should be the same as that used in LockScreen.java
     public boolean isAssistantAvailable() {
-        Intent intent = getAssistIntent();
-        return intent == null ? false
-                : mContext.getPackageManager().queryIntentActivities(intent,
-                PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
+        return mSearchManager != null && mSearchManager.isAssistantAvailable();
     }
 
     private Intent getAssistIntent() {
-        Intent intent = null;
-        SearchManager searchManager = getSearchManager();
-        if (searchManager != null) {
-            ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
-            if (globalSearchActivity != null) {
-                intent = new Intent(Intent.ACTION_ASSIST);
-                intent.setPackage(globalSearchActivity.getPackageName());
-            } else {
-                Slog.w(TAG, "No global search activity");
-            }
-        } else {
-            Slog.w(TAG, "No SearchManager");
-        }
-        return intent;
-    }
-
-    private SearchManager getSearchManager() {
-        if (mSearchManager == null) {
-            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
-        }
-        return mSearchManager;
+        return mSearchManager != null ? mSearchManager.getAssistIntent() : null;
     }
 
     private void startAssistActivity() {
@@ -125,7 +100,7 @@
         }
     }
 
-    class MultiWaveTriggerListener implements MultiWaveView.OnTriggerListener {
+    class GlowPadTriggerListener implements GlowPadView.OnTriggerListener {
         boolean mWaitingForLaunch;
 
         public void onGrabbed(View v, int handle) {
@@ -141,7 +116,7 @@
         }
 
         public void onTrigger(View v, final int target) {
-            final int resId = mMultiWaveView.getResourceIdForTarget(target);
+            final int resId = mGlowPadView.getResourceIdForTarget(target);
             switch (resId) {
                 case com.android.internal.R.drawable.ic_lockscreen_search:
                     mWaitingForLaunch = true;
@@ -154,13 +129,13 @@
         public void onFinishFinalAnimation() {
         }
     }
-    final MultiWaveTriggerListener mMultiWaveViewListener = new MultiWaveTriggerListener();
+    final GlowPadTriggerListener mGlowPadViewListener = new GlowPadTriggerListener();
 
     @Override
     public void onAnimationStarted() {
         postDelayed(new Runnable() {
             public void run() {
-                mMultiWaveViewListener.mWaitingForLaunch = false;
+                mGlowPadViewListener.mWaitingForLaunch = false;
                 mBar.hideSearchPanel();
             }
         }, SEARCH_PANEL_HOLD_DURATION);
@@ -173,13 +148,12 @@
         mSearchTargetsContainer = findViewById(R.id.search_panel_container);
         mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
         // TODO: fetch views
-        mMultiWaveView = (MultiWaveView) findViewById(R.id.multi_wave_view);
-        mMultiWaveView.setOnTriggerListener(mMultiWaveViewListener);
-        SearchManager searchManager = getSearchManager();
-        if (searchManager != null) {
-            ComponentName component = searchManager.getGlobalSearchActivity();
+        mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
+        mGlowPadView.setOnTriggerListener(mGlowPadViewListener);
+        if (mSearchManager != null) {
+            ComponentName component = mSearchManager.getGlobalSearchActivity();
             if (component != null) {
-                if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
+                if (!mGlowPadView.replaceTargetDrawablesIfPresent(component,
                         ASSIST_ICON_METADATA_NAME,
                         com.android.internal.R.drawable.ic_lockscreen_search)) {
                     Slog.w(TAG, "Couldn't grab icon from component " + component);
@@ -214,7 +188,7 @@
     private final OnPreDrawListener mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
         public boolean onPreDraw() {
             getViewTreeObserver().removeOnPreDrawListener(this);
-            mMultiWaveView.resumeAnimations();
+            mGlowPadView.resumeAnimations();
             return false;
         }
     };
@@ -240,7 +214,8 @@
                 setVisibility(View.VISIBLE);
                 // Don't start the animation until we've created the layer, which is done
                 // right before we are drawn
-                mMultiWaveView.suspendAnimations();
+                mGlowPadView.suspendAnimations();
+                mGlowPadView.ping();
                 getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
                 vibrate();
             }
@@ -299,7 +274,7 @@
     public void setStatusBarView(final View statusBarView) {
         if (mStatusBarTouchProxy != null) {
             mStatusBarTouchProxy.setStatusBar(statusBarView);
-//            mMultiWaveView.setOnTouchListener(new OnTouchListener() {
+//            mGlowPadView.setOnTouchListener(new OnTouchListener() {
 //                public boolean onTouch(View v, MotionEvent event) {
 //                    return statusBarView.onTouchEvent(event);
 //                }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index ccdf038..296b640 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -20,15 +20,19 @@
 import android.animation.AnimatorSet;
 import android.animation.AnimatorSet.Builder;
 import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.Slog;
 import android.view.View;
 import android.view.ViewRootImpl;
 
+import com.android.systemui.R;
+
 /* package */ class Choreographer implements Animator.AnimatorListener {
     // should group this into a multi-property animation
     private static final int OPEN_DURATION = 136;
-    private static final int CLOSE_DURATION = 130;
+    private static final int CLOSE_DURATION = 230;
     private static final int SCRIM_DURATION = 400;
     private static final String TAG = RecentsPanelView.TAG;
     private static final boolean DEBUG = RecentsPanelView.DEBUG;
@@ -81,7 +85,7 @@
                 mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
         fadeAnim.setInterpolator(appearing
                 ? new android.view.animation.AccelerateInterpolator(1.0f)
-                : new android.view.animation.DecelerateInterpolator(1.0f));
+                : new android.view.animation.AccelerateInterpolator(2.5f));
         fadeAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
 
         Animator noRecentAppsFadeAnim = null;
@@ -110,6 +114,20 @@
                 bgAnim.setDuration(appearing ? SCRIM_DURATION : CLOSE_DURATION);
                 builder.with(bgAnim);
             }
+        } else {
+            final Resources res = mRootView.getResources();
+            boolean isTablet = res.getBoolean(R.bool.config_recents_interface_for_tablets);
+            if (!isTablet) {
+                View recentsTransitionBackground =
+                        mRootView.findViewById(R.id.recents_transition_background);
+                recentsTransitionBackground.setVisibility(View.VISIBLE);
+                Drawable bgDrawable = new ColorDrawable(0xFF000000);
+                recentsTransitionBackground.setBackground(bgDrawable);
+                Animator bgAnim = ObjectAnimator.ofInt(bgDrawable, "alpha", 0, 255);
+                bgAnim.setDuration(CLOSE_DURATION);
+                bgAnim.setInterpolator(new android.view.animation.AccelerateInterpolator(1f));
+                builder.with(bgAnim);
+            }
         }
         mContentAnim.addListener(this);
         if (mListener != null) {
@@ -139,6 +157,10 @@
         if (mScrimView.getBackground() != null) {
             mScrimView.getBackground().setAlpha(appearing ? 255 : 0);
         }
+        View recentsTransitionBackground =
+                mRootView.findViewById(R.id.recents_transition_background);
+        recentsTransitionBackground.setVisibility(View.INVISIBLE);
+        mRootView.requestLayout();
     }
 
     public void setPanelHeight(int h) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 34cd397..0bdf84a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -34,11 +34,13 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
 import android.view.KeyEvent;
+import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
@@ -86,7 +88,8 @@
     OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
 
     ImageView mPlaceholderThumbnail;
-    boolean mHideWindowAfterPlaceholderThumbnailIsHidden;
+    View mTransitionBg;
+    boolean mHideRecentsAfterThumbnailScaleUpStarted;
 
     private RecentTasksLoader mRecentTasksLoader;
     private ArrayList<TaskDescription> mRecentTaskDescriptions;
@@ -97,6 +100,7 @@
     private boolean mFitThumbnailToXY;
     private int mRecentItemLayoutId;
     private boolean mFirstScreenful = true;
+    private boolean mHighEndGfx;
 
     public static interface OnRecentsPanelVisibilityChangedListener {
         public void onRecentsPanelVisibilityChanged(boolean visible);
@@ -248,7 +252,7 @@
     @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
-            show(false, true);
+            show(false, false);
             return true;
         }
         return super.onKeyUp(keyCode, event);
@@ -305,10 +309,6 @@
             ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
         sendCloseSystemWindows(mContext, BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
 
-        // For now, disable animations. We may want to re-enable in the future
-        if (show) {
-            animate = false;
-        }
         if (show) {
             // Need to update list of recent apps before we set visibility so this view's
             // content description is updated before it gets focus for TalkBack mode
@@ -318,6 +318,7 @@
             // quit early
             boolean noApps = !mFirstScreenful && (mRecentTaskDescriptions.size() == 0);
             if (mRecentsNoApps != null) {
+                mRecentsNoApps.setAlpha(1f);
                 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
             } else {
                 if (noApps) {
@@ -339,7 +340,6 @@
             mRecentTasksDirty = true;
             mWaitingToShow = false;
             mReadyToShow = false;
-            mRecentsNoApps.setVisibility(View.INVISIBLE);
         }
         if (animate) {
             if (mShowing != show) {
@@ -488,7 +488,8 @@
         if (mRecentsScrim != null) {
             Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay();
-            if (!ActivityManager.isHighEndGfx(d)) {
+            mHighEndGfx = ActivityManager.isHighEndGfx(d);
+            if (!mHighEndGfx) {
                 mRecentsScrim.setBackground(null);
             } else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
                 // In order to save space, we make the background texture repeat in the Y direction
@@ -704,22 +705,57 @@
         setContentDescription(recentAppsAccessibilityDescription);
     }
 
+
+    boolean mThumbnailScaleUpStarted;
     public void handleOnClick(View view) {
         ViewHolder holder = (ViewHolder)view.getTag();
         TaskDescription ad = holder.taskDescription;
         final Context context = view.getContext();
         final ActivityManager am = (ActivityManager)
                 context.getSystemService(Context.ACTIVITY_SERVICE);
-        holder.thumbnailViewImage.setDrawingCacheEnabled(true);
-        Bitmap bm = holder.thumbnailViewImage.getDrawingCache();
-        mPlaceholderThumbnail = (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
+        Bitmap bm = holder.thumbnailViewImageBitmap;
+        boolean usingDrawingCache;
+        if (bm.getWidth() == holder.thumbnailViewImage.getWidth() &&
+                bm.getHeight() == holder.thumbnailViewImage.getHeight()) {
+            usingDrawingCache = false;
+        } else {
+            holder.thumbnailViewImage.setDrawingCacheEnabled(true);
+            bm = holder.thumbnailViewImage.getDrawingCache();
+            usingDrawingCache = true;
+        }
+
+        if (mPlaceholderThumbnail == null) {
+            mPlaceholderThumbnail =
+                    (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
+        }
+        if (mTransitionBg == null) {
+            mTransitionBg = (View) findViewById(R.id.recents_transition_background);
+
+            IWindowManager wm = IWindowManager.Stub.asInterface(
+                    ServiceManager.getService(Context.WINDOW_SERVICE));
+            try {
+                if (!wm.hasSystemNavBar()) {
+                    FrameLayout.LayoutParams lp =
+                            (FrameLayout.LayoutParams) mTransitionBg.getLayoutParams();
+                    int statusBarHeight = getResources().
+                            getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+                    lp.setMargins(0, statusBarHeight, 0, 0);
+                    mTransitionBg.setLayoutParams(lp);
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failing checking whether status bar is visible", e);
+            }
+        }
 
         final ImageView placeholderThumbnail = mPlaceholderThumbnail;
-        mHideWindowAfterPlaceholderThumbnailIsHidden = false;
+        mHideRecentsAfterThumbnailScaleUpStarted = false;
         placeholderThumbnail.setVisibility(VISIBLE);
-        Bitmap b2 = bm.copy(bm.getConfig(), true);
-        placeholderThumbnail.setImageBitmap(b2);
-
+        if (!usingDrawingCache) {
+            placeholderThumbnail.setImageBitmap(bm);
+        } else {
+            Bitmap b2 = bm.copy(bm.getConfig(), true);
+            placeholderThumbnail.setImageBitmap(b2);
+        }
         Rect r = new Rect();
         holder.thumbnailViewImage.getGlobalVisibleRect(r);
 
@@ -728,13 +764,16 @@
 
         show(false, true);
 
+        mThumbnailScaleUpStarted = false;
         ActivityOptions opts = ActivityOptions.makeDelayedThumbnailScaleUpAnimation(
                 holder.thumbnailViewImage, bm, 0, 0,
                 new ActivityOptions.OnAnimationStartedListener() {
                     @Override public void onAnimationStarted() {
-                        mPlaceholderThumbnail = null;
-                        placeholderThumbnail.setVisibility(INVISIBLE);
-                        if (mHideWindowAfterPlaceholderThumbnailIsHidden) {
+                        mThumbnailScaleUpStarted = true;
+                        if (!mHighEndGfx) {
+                            mPlaceholderThumbnail.setVisibility(INVISIBLE);
+                        }
+                        if (mHideRecentsAfterThumbnailScaleUpStarted) {
                             hideWindow();
                         }
                     }
@@ -751,15 +790,19 @@
             if (DEBUG) Log.v(TAG, "Starting activity " + intent);
             context.startActivity(intent, opts.toBundle());
         }
-        holder.thumbnailViewImage.setDrawingCacheEnabled(false);
+        if (usingDrawingCache) {
+            holder.thumbnailViewImage.setDrawingCacheEnabled(false);
+        }
     }
 
     public void hideWindow() {
-        if (mPlaceholderThumbnail != null) {
-            mHideWindowAfterPlaceholderThumbnailIsHidden = true;
+        if (!mThumbnailScaleUpStarted) {
+            mHideRecentsAfterThumbnailScaleUpStarted = true;
         } else {
             setVisibility(GONE);
-            mHideWindowAfterPlaceholderThumbnailIsHidden = false;
+            mTransitionBg.setVisibility(INVISIBLE);
+            mPlaceholderThumbnail.setVisibility(INVISIBLE);
+            mHideRecentsAfterThumbnailScaleUpStarted = false;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index d387515..e802985 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -76,9 +76,6 @@
     }
 
     private void addToRecycledViews(View v) {
-        if (mRecycledViews.contains(v)) {
-            throw new RuntimeException("Child was already recycled");
-        }
         if (mRecycledViews.size() < mNumItemsInOneScreenful) {
             mRecycledViews.add(v);
         }
@@ -105,9 +102,6 @@
                 old = recycledViews.next();
                 recycledViews.remove();
                 old.setVisibility(VISIBLE);
-                if (old.getParent() != null) {
-                    throw new RuntimeException("Recycled child has parent (i: " + i + ", recycled i: " + mRecycledViews.size());
-                }
             }
             final View view = mAdapter.getView(i, old, mLinearLayout);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index cf2690b..750c6dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -440,13 +440,13 @@
              case MSG_OPEN_RECENTS_PANEL:
                   if (DEBUG) Slog.d(TAG, "opening recents panel");
                   if (mRecentsPanel != null) {
-                      mRecentsPanel.show(true, true);
+                      mRecentsPanel.show(true, false);
                   }
                   break;
              case MSG_CLOSE_RECENTS_PANEL:
                   if (DEBUG) Slog.d(TAG, "closing recents panel");
                   if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
-                      mRecentsPanel.show(false, true);
+                      mRecentsPanel.show(false, false);
                   }
                   break;
              case MSG_PRELOAD_RECENT_APPS:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
index d8441f2..491fad1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.provider.Telephony;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Slog;
 import android.view.View;
@@ -91,24 +92,20 @@
             Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
                     + " showPlmn=" + showPlmn + " plmn=" + plmn);
         }
-        StringBuilder str = new StringBuilder();
-        boolean something = false;
-        if (showPlmn && plmn != null) {
-            str.append(plmn);
-            something = true;
-        }
-        if (showSpn && spn != null) {
-            if (something) {
-                str.append('\n');
-            }
-            str.append(spn);
-            something = true;
-        }
-        if (something) {
-            setText(str.toString());
+        final String str;
+        // match logic in KeyguardStatusViewManager
+        final boolean plmnValid = showPlmn && !TextUtils.isEmpty(plmn);
+        final boolean spnValid = showSpn && !TextUtils.isEmpty(spn);
+        if (plmnValid && spnValid) {
+            str = plmn + "|" + spn;
+        } else if (plmnValid) {
+            str = plmn;
+        } else if (spnValid) {
+            str = spn;
         } else {
-            setText(com.android.internal.R.string.lockscreen_carrier_default);
+            str = "";
         }
+        setText(str);
     }
 
     
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 9c773a5..00d6d6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -225,11 +225,28 @@
         final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
         final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
 
+        setSlippery(disableHome && disableRecent && disableBack);
+
         getBackButton()   .setVisibility(disableBack       ? View.INVISIBLE : View.VISIBLE);
         getHomeButton()   .setVisibility(disableHome       ? View.INVISIBLE : View.VISIBLE);
         getRecentsButton().setVisibility(disableRecent     ? View.INVISIBLE : View.VISIBLE);
     }
 
+    public void setSlippery(boolean newSlippery) {
+        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
+        if (lp != null) {
+            boolean oldSlippery = (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0;
+            if (!oldSlippery && newSlippery) {
+                lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
+            } else if (oldSlippery && !newSlippery) {
+                lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
+            } else {
+                return;
+            }
+            WindowManagerImpl.getDefault().updateViewLayout(this, lp);
+        }
+    }
+
     public void setMenuVisibility(final boolean show) {
         setMenuVisibility(show, false);
     }
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 87e95da..3c19ad2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -134,6 +134,9 @@
     private float mExpandAccelPx; // classic value: 2000px/s/s
     private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
 
+    private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little 
+                                                    // faster than mSelfCollapseVelocityPx)
+
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -165,8 +168,10 @@
     ScrollView mScrollView;
     View mExpandedContents;
     int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
+    final Rect mNotificationPanelBackgroundPadding = new Rect();
     int mNotificationPanelGravity;
     int mNotificationPanelMinHeight;
+    boolean mNotificationPanelIsFullScreenWidth;
 
     // top bar
     View mClearButton;
@@ -267,6 +272,13 @@
         }
     };
 
+    private final Runnable mPerformSelfExpandFling = new Runnable() {
+        @Override
+        public void run() {
+            performFling(0, mSelfExpandVelocityPx, true);
+        }
+    };
+
     private final Runnable mPerformFling = new Runnable() {
         @Override
         public void run() {
@@ -350,9 +362,11 @@
                 return true;
             }
         });
+        mNotificationPanelIsFullScreenWidth =
+            (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
         mNotificationPanel.setSystemUiVisibility(
                   View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
-                | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
+                | (mNotificationPanelIsFullScreenWidth ? 0 : View.STATUS_BAR_DISABLE_SYSTEM_INFO));
 
         if (!ActivityManager.isHighEndGfx(mDisplay)) {
             mStatusBarWindow.setBackground(null);
@@ -365,6 +379,8 @@
             mIntruderAlertView.setBar(this);
         }
 
+        updateShowSearchHoldoff();
+
         mStatusBarView.mService = this;
 
         mChoreographer = Choreographer.getInstance();
@@ -392,12 +408,13 @@
         mTickerView = mStatusBarView.findViewById(R.id.ticker);
 
         mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);
+        mPile.setLayoutTransitionsEnabled(false);
         mPile.setLongPressListener(getNotificationLongClicker());
         if (SHOW_CARRIER_LABEL) {
             mPile.setOnSizeChangedListener(new OnSizeChangedListener() {
                 @Override
                 public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
-                    updateCarrierLabelVisibility();
+                    updateCarrierLabelVisibility(false);
                 }
             });
         }
@@ -443,12 +460,15 @@
 
         mNetworkController.addSignalCluster(signalCluster);
         signalCluster.setNetworkController(mNetworkController);
-        
-        // for wifi-only devices, we show SSID; otherwise, we show PLMN
-        if (mNetworkController.hasMobileDataFeature()) {
-            mNetworkController.addMobileLabelView(mCarrierLabel);
-        } else {
-            mNetworkController.addWifiLabelView(mCarrierLabel);
+
+        if (SHOW_CARRIER_LABEL) {
+            // for mobile devices, we always show mobile connection info here (SPN/PLMN)
+            // for other devices, we show whatever network is connected
+            if (mNetworkController.hasMobileDataFeature()) {
+                mNetworkController.addMobileLabelView(mCarrierLabel);
+            } else {
+                mNetworkController.addCombinedLabelView(mCarrierLabel);
+            }
         }
 
 //        final ImageView wimaxRSSI =
@@ -649,7 +669,6 @@
 
         lp.setTitle("NavigationBar");
         lp.windowAnimations = 0;
-
         return lp;
     }
 
@@ -794,8 +813,29 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         updateRecentsPanel();
-        mShowSearchHoldoff  = mContext.getResources().getInteger(
-                R.integer.config_show_search_delay);
+        updateShowSearchHoldoff();
+    }
+
+    private void updateShowSearchHoldoff() {
+        mShowSearchHoldoff = mContext.getResources().getInteger(
+            R.integer.config_show_search_delay);
+    }
+
+    // Q: What kinds of notifications should show during setup?
+    // A: Almost none! Only things coming from the system (package is "android") that also 
+    // have special "kind" tags marking them as relevant for setup (see below).
+    private boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
+        if ("android".equals(sbn.pkg)) {
+            if (sbn.notification.kind != null) {
+                for (String aKind : sbn.notification.kind) {
+                    // IME switcher, created by InputMethodManagerService
+                    if ("android.system.imeswitcher".equals(aKind)) return true;
+                    // OTA availability & errors, created by SystemUpdateService
+                    if ("android.system.update".equals(aKind)) return true;
+                }
+            }
+        }
+        return false;
     }
 
     private void loadNotificationShade() {
@@ -809,7 +849,7 @@
         // If the device hasn't been through Setup, we only show system notifications
         for (int i=0; i<N; i++) {
             Entry ent = mNotificationData.get(N-i-1);
-            if (provisioned || "android".equals(ent.notification.pkg)) {
+            if (provisioned || showNotificationEvenIfUnprovisioned(ent.notification)) {
                 toShow.add(ent.row);
             }
         }
@@ -864,7 +904,7 @@
         for (int i=0; i<N; i++) {
             Entry ent = mNotificationData.get(N-i-1);
             if ((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE)
-                    || "android".equals(ent.notification.pkg)) {
+                    || showNotificationEvenIfUnprovisioned(ent.notification)) {
                 toShow.add(ent.icon);
             }
         }
@@ -889,7 +929,7 @@
         }
     }
 
-    protected void updateCarrierLabelVisibility() {
+    protected void updateCarrierLabelVisibility(boolean force) {
         if (!SHOW_CARRIER_LABEL) return;
         // The idea here is to only show the carrier label when there is enough room to see it, 
         // i.e. when there aren't enough notifications to fill the panel.
@@ -901,7 +941,7 @@
         final boolean makeVisible = 
             mPile.getHeight() < (mScrollView.getHeight() - mCarrierLabelHeight);
         
-        if (mCarrierLabelVisible != makeVisible) {
+        if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
             if (DEBUG) {
                 Slog.d(TAG, "making carrier label " + (makeVisible?"visible":"invisible"));
@@ -986,7 +1026,7 @@
                 .start();
         }
 
-        updateCarrierLabelVisibility();
+        updateCarrierLabelVisibility(false);
     }
 
     public void showClock(boolean show) {
@@ -1159,9 +1199,11 @@
         }
 
         mExpandedVisible = true;
-        makeSlippery(mNavigationBarView, true);
+        mPile.setLayoutTransitionsEnabled(true);
+        if (mNavigationBarView != null)
+            mNavigationBarView.setSlippery(true);
 
-        updateCarrierLabelVisibility();
+        updateCarrierLabelVisibility(true);
 
         updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
 
@@ -1183,19 +1225,6 @@
         visibilityChanged(true);
     }
 
-    private static void makeSlippery(View view, boolean slippery) {
-        if (view == null) {
-            return;
-        }
-        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams();
-        if (slippery) {
-            lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
-        } else {
-            lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
-        }
-        WindowManagerImpl.getDefault().updateViewLayout(view, lp);
-    }
-
     public void animateExpand() {
         if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
@@ -1206,7 +1235,7 @@
         }
 
         prepareTracking(0, true);
-        performFling(0, mSelfExpandVelocityPx, true);
+        mHandler.post(mPerformSelfExpandFling);
     }
 
     public void animateCollapse() {
@@ -1279,8 +1308,10 @@
             return;
         }
         mExpandedVisible = false;
+        mPile.setLayoutTransitionsEnabled(false);
+        if (mNavigationBarView != null)
+            mNavigationBarView.setSlippery(false);
         visibilityChanged(false);
-        makeSlippery(mNavigationBarView, false);
 
         // Shrink the window to the size of the status bar only
         WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
@@ -1363,12 +1394,59 @@
         if (!mTracking)
             return;
         mTracking = false;
-        mPile.setLayerType(View.LAYER_TYPE_NONE, null);
+        setPileLayers(View.LAYER_TYPE_NONE);
         mVelocityTracker.recycle();
         mVelocityTracker = null;
         mCloseView.setPressed(false);
     }
 
+    /**
+     * Enables or disables layers on the children of the notifications pile.
+     * 
+     * When layers are enabled, this method attempts to enable layers for the minimal
+     * number of children. Only children visible when the notification area is fully
+     * expanded will receive a layer. The technique used in this method might cause
+     * more children than necessary to get a layer (at most one extra child with the
+     * current UI.)
+     * 
+     * @param layerType {@link View#LAYER_TYPE_NONE} or {@link View#LAYER_TYPE_HARDWARE}
+     */
+    private void setPileLayers(int layerType) {
+        final int count = mPile.getChildCount();
+
+        switch (layerType) {
+            case View.LAYER_TYPE_NONE:
+                for (int i = 0; i < count; i++) {
+                    mPile.getChildAt(i).setLayerType(layerType, null);
+                }
+                break;
+            case View.LAYER_TYPE_HARDWARE:
+                final int[] location = new int[2]; 
+                mNotificationPanel.getLocationInWindow(location);
+
+                final int left = location[0];
+                final int top = location[1];
+                final int right = left + mNotificationPanel.getWidth();
+                final int bottom = top + getExpandedViewMaxHeight();
+
+                final Rect childBounds = new Rect();
+
+                for (int i = 0; i < count; i++) {
+                    final View view = mPile.getChildAt(i);
+                    view.getLocationInWindow(location);
+
+                    childBounds.set(location[0], location[1],
+                            location[0] + view.getWidth(), location[1] + view.getHeight());
+
+                    if (childBounds.intersects(left, top, right, bottom)) {
+                        view.setLayerType(layerType, null);
+                    }
+                }
+
+                break;
+        }
+    }
+
     void incrementAnim(long frameTimeNanos) {
         final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
         final float t = deltaNanos * 0.000000001f;                  // ns -> s
@@ -1408,7 +1486,7 @@
         mCloseView.setPressed(true);
 
         mTracking = true;
-        mPile.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        setPileLayers(View.LAYER_TYPE_HARDWARE);
         mVelocityTracker = VelocityTracker.obtain();
         if (opening) {
             makeExpandedVisible(true);
@@ -1521,12 +1599,15 @@
                 mViewDelta = statusBarSize - y;
             } else {
                 mCloseView.getLocationOnScreen(mAbsPos);
-                mViewDelta = mAbsPos[1] + statusBarSize + getCloseViewHeight() - y; // XXX: not closeViewHeight, but paddingBottom from the 9patch
+                mViewDelta = mAbsPos[1]
+                           + getCloseViewHeight() // XXX: not closeViewHeight, but paddingBottom from the 9patch
+                           + mNotificationPanelBackgroundPadding.top
+                           + mNotificationPanelBackgroundPadding.bottom
+                           - y;
             }
             if ((!mExpanded && y < hitSize) ||
                     // @@ add taps outside the panel if it's not full-screen
                     (mExpanded && y > (getExpandedViewMaxHeight()-hitSize))) {
-
                 // We drop events at the edge of the screen to make the windowshade come
                 // down by accident less, especially when pushing open a device with a keyboard
                 // that rotates (like g1 and droid)
@@ -1562,6 +1643,9 @@
                 }
 
                 float vel = (float)Math.hypot(yVel, xVel);
+                if (vel > mFlingGestureMaxOutputVelocityPx) {
+                    vel = mFlingGestureMaxOutputVelocityPx;
+                }
                 if (negative) {
                     vel = -vel;
                 }
@@ -1943,9 +2027,7 @@
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
 
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
-            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        }
+        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
 
         lp.gravity = getStatusBarGravity();
         lp.setTitle("StatusBar");
@@ -2041,7 +2123,7 @@
             mStatusBarWindow.setBackgroundColor(color);
         }
         
-        updateCarrierLabelVisibility();
+        updateCarrierLabelVisibility(false);
     }
 
     void updateDisplaySize() {
@@ -2268,6 +2350,8 @@
 
         mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
 
+        mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
+
         mNotificationPanelMarginBottomPx
             = (int) res.getDimension(R.dimen.notification_panel_margin_bottom);
         mNotificationPanelMarginLeftPx
@@ -2276,10 +2360,12 @@
         if (mNotificationPanelGravity <= 0) {
             mNotificationPanelGravity = Gravity.CENTER_VERTICAL | Gravity.TOP;
         }
+        getNinePatchPadding(res.getDrawable(R.drawable.notification_panel_bg), mNotificationPanelBackgroundPadding);
         final int notificationPanelDecorationHeight =
               res.getDimensionPixelSize(R.dimen.notification_panel_padding_top)
             + res.getDimensionPixelSize(R.dimen.notification_panel_header_height)
-            + getNinePatchPadding(res.getDrawable(R.drawable.notification_panel_bg)).bottom;
+            + mNotificationPanelBackgroundPadding.top
+            + mNotificationPanelBackgroundPadding.bottom;
         mNotificationPanelMinHeight = 
               notificationPanelDecorationHeight 
             + res.getDimensionPixelSize(R.dimen.close_handle_underlap);
@@ -2289,13 +2375,11 @@
         if (false) Slog.v(TAG, "updateResources");
     }
 
-    private static Rect getNinePatchPadding(Drawable d) {
-        Rect padding = new Rect();
+    private static void getNinePatchPadding(Drawable d, Rect outPadding) {
         if (d instanceof NinePatchDrawable) {
             NinePatchDrawable ninePatch = (NinePatchDrawable) d;
-            ninePatch.getPadding(padding);
+            ninePatch.getPadding(outPadding);
         }
-        return padding;
     }
 
     //
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index ed1b2f5..9317561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -22,6 +22,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.widget.FrameLayout;
+import android.widget.ScrollView;
 import android.widget.TextSwitcher;
 
 import com.android.systemui.ExpandHelper;
@@ -47,6 +48,7 @@
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
         latestItems = (NotificationRowLayout) findViewById(R.id.latestItems);
+        ScrollView scroller = (ScrollView) findViewById(R.id.scroll);
         int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
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 b8f6054..1068267 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -121,8 +121,12 @@
     private int mWimaxSignal = 0;
     private int mWimaxState = 0;
     private int mWimaxExtraState = 0;
+
     // data connectivity (regardless of state, can we access the internet?)
     // state of inet connection - 0 not connected, 100 connected
+    private boolean mConnected = false;
+    private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+    private String mConnectedNetworkTypeName;
     private int mInetCondition = 0;
     private static final int INET_CONDITION_THRESHOLD = 50;
 
@@ -868,6 +872,16 @@
                 .getSystemService(Context.CONNECTIVITY_SERVICE);
         final NetworkInfo info = connManager.getActiveNetworkInfo();
 
+        // Are we connected at all, by any interface?
+        mConnected = info != null && info.isConnected();
+        if (mConnected) {
+            mConnectedNetworkType = info.getType();
+            mConnectedNetworkTypeName = info.getTypeName();
+        } else {
+            mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+            mConnectedNetworkTypeName = null;
+        }
+
         int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
 
         if (CHATTY) {
@@ -912,12 +926,13 @@
             //   - We are connected to mobile data, or
             //   - We are not connected to mobile data, as long as the *reason* packets are not
             //     being routed over that link is that we have better connectivity via wifi.
-            // If data is disconnected for some other reason but wifi is connected, we show nothing.
+            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) 
+            // is connected, we show nothing.
             // Otherwise (nothing connected) we show "No internet connection".
 
             if (mDataConnected) {
                 mobileLabel = mNetworkName;
-            } else if (mWifiConnected) {
+            } else if (mConnected) {
                 if (hasService()) {
                     mobileLabel = mNetworkName;
                 } else {
@@ -997,6 +1012,12 @@
                     R.string.accessibility_bluetooth_tether);
         }
 
+        final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
+        if (ethernetConnected) {
+            // TODO: icons and strings for Ethernet connectivity
+            combinedLabel = mConnectedNetworkTypeName;
+        }
+
         if (mAirplaneMode &&
                 (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
             // Only display the flight-mode icon if not in "emergency calls only" mode.
@@ -1023,7 +1044,7 @@
                 combinedSignalIconId = mDataSignalIconId;
             }
         }
-        else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected) {
+        else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected && !ethernetConnected) {
             // pretty much totally disconnected
 
             combinedLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
@@ -1224,6 +1245,9 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NetworkController state:");
+        pw.println(String.format("  %s network type %d (%s)", 
+                mConnected?"CONNECTED":"DISCONNECTED",
+                mConnectedNetworkType, mConnectedNetworkTypeName));
         pw.println("  - telephony ------");
         pw.print("  hasService()=");
         pw.println(hasService());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 42db8cf..61e5ab6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -68,6 +68,8 @@
     // animation is done
     boolean mRemoveViews = true;
 
+    private LayoutTransition mRealLayoutTransition;
+
     public NotificationRowLayout(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -75,7 +77,8 @@
     public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        setLayoutTransition(new LayoutTransition());
+        mRealLayoutTransition = new LayoutTransition();
+        setLayoutTransitionsEnabled(true);
         
         setOrientation(LinearLayout.VERTICAL);
 
@@ -121,9 +124,9 @@
 
     private void logLayoutTransition() {
         Log.v(TAG, "layout " +
-              (getLayoutTransition().isChangingLayout() ? "is " : "is not ") +
+              (mRealLayoutTransition.isChangingLayout() ? "is " : "is not ") +
               "in transition and animations " +
-              (getLayoutTransition().isRunning() ? "are " : "are not ") +
+              (mRealLayoutTransition.isRunning() ? "are " : "are not ") +
               "running.");
     }
 
@@ -225,6 +228,18 @@
         mRemoveViews = removeViews;
     }
 
+    // Suppress layout transitions for a little while.
+    public void setLayoutTransitionsEnabled(boolean b) {
+        if (b) {
+            setLayoutTransition(mRealLayoutTransition);
+        } else {
+            if (mRealLayoutTransition.isRunning()) {
+                mRealLayoutTransition.cancel();
+            }
+            setLayoutTransition(null);
+        }
+    }
+
     public void dismissRowAnimated(View child) {
         dismissRowAnimated(child, 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 71657f5..af0f9d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Slog;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -33,6 +34,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.RelativeLayout;
+import android.widget.ScrollView;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
@@ -104,8 +106,6 @@
         mClearButton.setOnClickListener(mClearButtonListener);
 
         mShowing = false;
-
-        setContentFrameVisible(mNotificationCount > 0, false);
     }
 
     @Override
@@ -116,6 +116,7 @@
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
+        mExpandHelper.setGravity(Gravity.BOTTOM);
     }
 
     private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
@@ -129,10 +130,6 @@
     }
 
     public void show(boolean show, boolean animate) {
-        if (show && !mShowing) {
-            setContentFrameVisible(mSettingsView != null || mNotificationCount > 0, false);
-        }
-
         if (animate) {
             if (mShowing != show) {
                 mShowing = show;
@@ -226,53 +223,10 @@
     }
 
     public void setNotificationCount(int n) {
-//        Slog.d(TAG, "notificationCount=" + n);
-        if (!mShowing) {
-            // just do it, already
-            setContentFrameVisible(n > 0, false);
-        } else if (mSettingsView == null) {
-            // we're looking at the notifications; time to maybe make some changes
-            if ((mNotificationCount > 0) != (n > 0)) {
-                setContentFrameVisible(n > 0, true);
-            }
-        }
         mNotificationCount = n;
     }
 
     public void setContentFrameVisible(final boolean showing, boolean animate) {
-        if (!animate) {
-            mContentFrame.setVisibility(showing ? View.VISIBLE : View.GONE);
-            mContentFrame.setAlpha(1f);
-            // the translation will be patched up when the window is slid into place
-            return;
-        }
-
-        if (showing) {
-            mContentFrame.setVisibility(View.VISIBLE);
-        }
-        AnimatorSet set = new AnimatorSet();
-        set.play(ObjectAnimator.ofFloat(
-                mContentFrame, "alpha",
-                showing ? 0f : 1f,
-                showing ? 1f : 0f))
-            .with(ObjectAnimator.ofFloat(
-                mContentParent, "translationY",
-                showing ? mContentFrameMissingTranslation : 0f,
-                showing ? 0f : mContentFrameMissingTranslation))
-              ;
-
-        set.setDuration(200);
-        set.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator _a) {
-                if (!showing) {
-                    mContentFrame.setVisibility(View.GONE);
-                    mContentFrame.setAlpha(1f);
-                }
-                updateClearButton();
-            }
-        });
-        set.start();
     }
 
     public void swapPanels() {
@@ -292,11 +246,6 @@
             public void onAnimationEnd(Animator _a) {
                 toHide.setVisibility(View.GONE);
                 if (toShow != null) {
-                    if (mNotificationCount == 0) {
-                        // show the frame for settings, hide for notifications
-                        setContentFrameVisible(toShow == mSettingsView, true);
-                    }
-
                     toShow.setVisibility(View.VISIBLE);
                     if (toShow == mSettingsView || mNotificationCount > 0) {
                         ObjectAnimator.ofFloat(toShow, "alpha", 0f, 1f)
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 8df9b85..9b46af8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -404,6 +404,7 @@
         mRecentsPanel.updateValuesFromResources();
         mShowSearchHoldoff = mContext.getResources().getInteger(
                 R.integer.config_show_search_delay);
+        updateSearchPanel();
     }
 
     protected void loadDimens() {
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 46c0f83..ef640d5 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.vpndialogs"
-        android:sharedUserId="android.uid.system">
+        package="com.android.vpndialogs">
 
     <application android:label="VpnDialogs"
             android:allowBackup="false" >
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 18b8042..87ec16b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -81,7 +81,7 @@
 
     private int mFailedAttempts = 0;
     private int mFailedBiometricUnlockAttempts = 0;
-    private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 5;
+    private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
 
     private boolean mClockVisible;
 
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
index d7fb19a..58d14ed 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
@@ -58,7 +58,6 @@
         final IccCard.State simState = mUpdateMonitor.getSimState();
         return (simState == IccCard.State.PIN_REQUIRED
                 || simState == IccCard.State.PUK_REQUIRED
-                || simState == IccCard.State.ABSENT
                 || simState == IccCard.State.PERM_DISABLED);
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index d37207c..4af66ce 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -23,7 +23,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.SlidingTab;
 import com.android.internal.widget.WaveView;
-import com.android.internal.widget.multiwaveview.MultiWaveView;
+import com.android.internal.widget.multiwaveview.GlowPadView;
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -32,7 +32,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Vibrator;
@@ -254,29 +253,14 @@
         }
     }
 
-    // This code should be the same as that in SearchPanelView
-    public boolean isAssistantAvailable() {
-        Intent intent = getAssistIntent();
-        return intent == null ? false
-                : mContext.getPackageManager().queryIntentActivities(intent,
-                        PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
+    private boolean isAssistantAvailable() {
+        SearchManager searchManager = getSearchManager();
+        return searchManager != null && searchManager.isAssistantAvailable();
     }
 
     private Intent getAssistIntent() {
-        Intent intent = null;
         SearchManager searchManager = getSearchManager();
-        if (searchManager != null) {
-            ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
-            if (globalSearchActivity != null) {
-                intent = new Intent(Intent.ACTION_ASSIST);
-                intent.setPackage(globalSearchActivity.getPackageName());
-            } else {
-                Slog.w(TAG, "No global search activity");
-            }
-        } else {
-            Slog.w(TAG, "No SearchManager");
-        }
-        return intent;
+        return searchManager != null ? searchManager.getAssistIntent() : null;
     }
 
     private SearchManager getSearchManager() {
@@ -286,16 +270,16 @@
         return mSearchManager;
     }
 
-    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
+    class GlowPadViewMethods implements GlowPadView.OnTriggerListener,
             UnlockWidgetCommonMethods {
-        private final MultiWaveView mMultiWaveView;
+        private final GlowPadView mGlowPadView;
 
-        MultiWaveViewMethods(MultiWaveView multiWaveView) {
-            mMultiWaveView = multiWaveView;
+        GlowPadViewMethods(GlowPadView glowPadView) {
+            mGlowPadView = glowPadView;
         }
 
         public boolean isTargetPresent(int resId) {
-            return mMultiWaveView.getTargetPosition(resId) != -1;
+            return mGlowPadView.getTargetPosition(resId) != -1;
         }
 
         public void updateResources() {
@@ -307,8 +291,8 @@
             } else {
                 resId = R.array.lockscreen_targets_with_camera;
             }
-            if (mMultiWaveView.getTargetResourceId() != resId) {
-                mMultiWaveView.setTargetResources(resId);
+            if (mGlowPadView.getTargetResourceId() != resId) {
+                mGlowPadView.setTargetResources(resId);
             }
 
             // Update the search icon with drawable from the search .apk
@@ -317,7 +301,7 @@
                 if (searchManager != null) {
                     ComponentName component = searchManager.getGlobalSearchActivity();
                     if (component != null) {
-                        if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
+                        if (!mGlowPadView.replaceTargetDrawablesIfPresent(component,
                                 ASSIST_ICON_METADATA_NAME,
                                 com.android.internal.R.drawable.ic_lockscreen_search)) {
                             Slog.w(TAG, "Couldn't grab icon from package " + component);
@@ -343,7 +327,7 @@
         }
 
         public void onTrigger(View v, int target) {
-            final int resId = mMultiWaveView.getResourceIdForTarget(target);
+            final int resId = mGlowPadView.getResourceIdForTarget(target);
             switch (resId) {
                 case com.android.internal.R.drawable.ic_lockscreen_search:
                     Intent assistIntent = getAssistIntent();
@@ -393,33 +377,33 @@
             // Don't poke the wake lock when returning to a state where the handle is
             // not grabbed since that can happen when the system (instead of the user)
             // cancels the grab.
-            if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {
+            if (handle != GlowPadView.OnTriggerListener.NO_HANDLE) {
                 mCallback.pokeWakelock();
             }
         }
 
         public View getView() {
-            return mMultiWaveView;
+            return mGlowPadView;
         }
 
         public void reset(boolean animate) {
-            mMultiWaveView.reset(animate);
+            mGlowPadView.reset(animate);
         }
 
         public void ping() {
-            mMultiWaveView.ping();
+            mGlowPadView.ping();
         }
 
         public void setEnabled(int resourceId, boolean enabled) {
-            mMultiWaveView.setEnableTarget(resourceId, enabled);
+            mGlowPadView.setEnableTarget(resourceId, enabled);
         }
 
         public int getTargetPosition(int resourceId) {
-            return mMultiWaveView.getTargetPosition(resourceId);
+            return mGlowPadView.getTargetPosition(resourceId);
         }
 
         public void cleanUp() {
-            mMultiWaveView.setOnTriggerListener(null);
+            mGlowPadView.setOnTriggerListener(null);
         }
 
         public void onFinishFinalAnimation() {
@@ -531,11 +515,11 @@
             WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
             waveView.setOnTriggerListener(waveViewMethods);
             return waveViewMethods;
-        } else if (unlockWidget instanceof MultiWaveView) {
-            MultiWaveView multiWaveView = (MultiWaveView) unlockWidget;
-            MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
-            multiWaveView.setOnTriggerListener(multiWaveViewMethods);
-            return multiWaveViewMethods;
+        } else if (unlockWidget instanceof GlowPadView) {
+            GlowPadView glowPadView = (GlowPadView) unlockWidget;
+            GlowPadViewMethods glowPadViewMethods = new GlowPadViewMethods(glowPadView);
+            glowPadView.setOnTriggerListener(glowPadViewMethods);
+            return glowPadViewMethods;
         } else {
             throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
         }
@@ -545,12 +529,12 @@
         boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
                 .getCameraDisabled(null);
         boolean disabledBySimState = mUpdateMonitor.isSimLocked();
-        boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof MultiWaveViewMethods)
-                ? ((MultiWaveViewMethods) mUnlockWidgetMethods)
+        boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
                         .isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera)
                         : false;
-        boolean searchTargetPresent = (mUnlockWidgetMethods instanceof MultiWaveViewMethods)
-                ? ((MultiWaveViewMethods) mUnlockWidgetMethods)
+        boolean searchTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
                         .isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_search)
                         : false;
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 9ef8d6b..0911f1f 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManagerNative;
 import android.app.IUiModeManager;
 import android.app.ProgressDialog;
+import android.app.SearchManager;
 import android.app.UiModeManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -235,6 +236,7 @@
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
     static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
+    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
 
     /**
      * These are the system UI flags that, when changing, can cause the layout
@@ -279,6 +281,7 @@
     LocalPowerManager mPowerManager;
     IStatusBarService mStatusBarService;
     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
+    SearchManager mSearchManager;
 
     // Vibrator pattern for haptic feedback of a long press.
     long[] mLongPressVibePattern;
@@ -462,6 +465,7 @@
     Intent mDeskDockIntent;
     boolean mSearchKeyShortcutPending;
     boolean mConsumeSearchKeyUp;
+    boolean mAssistKeyLongPressed;
 
     // support for activating the lock screen while the screen is on
     boolean mAllowLockscreenWhenOn;
@@ -1860,6 +1864,26 @@
                 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
             }
             return -1;
+        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
+            if (down) {
+                if (repeatCount == 0) {
+                    mAssistKeyLongPressed = false;
+                } else if (repeatCount == 1) {
+                    mAssistKeyLongPressed = true;
+                    if (!keyguardOn) {
+                         launchAssistLongPressAction();
+                    }
+                }
+            } else {
+                if (mAssistKeyLongPressed) {
+                    mAssistKeyLongPressed = false;
+                } else {
+                    if (!keyguardOn) {
+                        launchAssistAction();
+                    }
+                }
+            }
+            return -1;
         }
 
         // Shortcuts are invoked through Search+key, so intercept those here
@@ -2050,6 +2074,50 @@
         return false;
     }
 
+    private void launchAssistLongPressAction() {
+        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
+
+        // launch the search activity
+        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        try {
+            SearchManager searchManager = getSearchManager();
+            if (searchManager != null) {
+                searchManager.stopSearch();
+            }
+            mContext.startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Slog.w(TAG, "No activity to handle assist long press action.", e);
+        }
+    }
+
+    private void launchAssistAction() {
+        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
+
+        SearchManager searchManager = getSearchManager();
+        if (searchManager != null) {
+            Intent intent = searchManager.getAssistIntent();
+            if (intent != null) {
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                try {
+                    mContext.startActivity(intent);
+                } catch (ActivityNotFoundException e) {
+                    Slog.w(TAG, "No activity to handle assist action.", e);
+                }
+            }
+        }
+    }
+
+    private SearchManager getSearchManager() {
+        if (mSearchManager == null) {
+            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+        }
+        return mSearchManager;
+    }
+
     /**
      * A home key -> launch home action was detected.  Take the appropriate action
      * given the situation with the keyguard.
@@ -2900,7 +2968,7 @@
     }
 
     public boolean allowAppAnimationsLw() {
-        if (mKeyguard != null && mKeyguard.isVisibleLw()) {
+        if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()) {
             // If keyguard is currently visible, no reason to animate
             // behind it.
             return false;
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index c8e11c2..7e1a80c 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -56,6 +56,8 @@
 
 #define INDENT "  "
 #define INDENT2 "    "
+#define INDENT3 "      "
+#define INDENT4 "        "
 
 namespace android {
 
@@ -78,6 +80,9 @@
 // queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
 const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
 
+// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
+const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
+
 
 static inline nsecs_t now() {
     return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -897,11 +902,11 @@
         const EventEntry* entry,
         const sp<InputApplicationHandle>& applicationHandle,
         const sp<InputWindowHandle>& windowHandle,
-        nsecs_t* nextWakeupTime) {
+        nsecs_t* nextWakeupTime, const char* reason) {
     if (applicationHandle == NULL && windowHandle == NULL) {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
 #if DEBUG_FOCUS
-            ALOGD("Waiting for system to become ready for input.");
+            ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);
 #endif
             mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
             mInputTargetWaitStartTime = currentTime;
@@ -912,8 +917,9 @@
     } else {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
 #if DEBUG_FOCUS
-            ALOGD("Waiting for application to become ready for input: %s",
-                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
+            ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",
+                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
+                    reason);
 #endif
             nsecs_t timeout;
             if (windowHandle != NULL) {
@@ -946,7 +952,7 @@
 
     if (currentTime >= mInputTargetWaitTimeoutTime) {
         onANRLocked(currentTime, applicationHandle, windowHandle,
-                entry->eventTime, mInputTargetWaitStartTime);
+                entry->eventTime, mInputTargetWaitStartTime, reason);
 
         // Force poll loop to wake up immediately on next iteration once we get the
         // ANR response back from the policy.
@@ -1017,13 +1023,11 @@
     // then drop the event.
     if (mFocusedWindowHandle == NULL) {
         if (mFocusedApplicationHandle != NULL) {
-#if DEBUG_FOCUS
-            ALOGD("Waiting because there is no focused window but there is a "
-                    "focused application that may eventually add a window: %s.",
-                    getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
-#endif
             injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplicationHandle, NULL, nextWakeupTime);
+                    mFocusedApplicationHandle, NULL, nextWakeupTime,
+                    "Waiting because no window has focus but there is a "
+                    "focused application that may eventually add a window "
+                    "when it finishes starting up.");
             goto Unresponsive;
         }
 
@@ -1040,21 +1044,18 @@
 
     // If the currently focused window is paused then keep waiting.
     if (mFocusedWindowHandle->getInfo()->paused) {
-#if DEBUG_FOCUS
-        ALOGD("Waiting because focused window is paused.");
-#endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
+                "Waiting because the focused window is paused.");
         goto Unresponsive;
     }
 
     // If the currently focused window is still working on previous events then keep waiting.
     if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) {
-#if DEBUG_FOCUS
-        ALOGD("Waiting because focused window still processing previous input.");
-#endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
+                "Waiting because the focused window has not finished "
+                "processing the input events that were previously delivered to it.");
         goto Unresponsive;
     }
 
@@ -1210,11 +1211,9 @@
         // it is invisible) then wait for it.  Any other focused window may in
         // fact be in ANR state.
         if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
-#if DEBUG_FOCUS
-            ALOGD("Waiting because system error window is pending.");
-#endif
             injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    NULL, NULL, nextWakeupTime);
+                    NULL, NULL, nextWakeupTime,
+                    "Waiting because a system error window is about to be displayed.");
             injectionPermission = INJECTION_PERMISSION_UNKNOWN;
             goto Unresponsive;
         }
@@ -1241,14 +1240,11 @@
                 // but not yet put up a window and the user is starting to get impatient.
                 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
                         && mFocusedApplicationHandle != NULL) {
-#if DEBUG_FOCUS
-                    ALOGD("Waiting because there is no touched window but there is a "
-                            "focused application that may eventually add a new window: %s.",
-                            getApplicationWindowLabelLocked(
-                                    mFocusedApplicationHandle, NULL).string());
-#endif
                     injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                            mFocusedApplicationHandle, NULL, nextWakeupTime);
+                            mFocusedApplicationHandle, NULL, nextWakeupTime,
+                            "Waiting because there is no touchable window that can "
+                            "handle the event but there is focused application that may "
+                            "eventually add a new window when it finishes starting up.");
                     goto Unresponsive;
                 }
 
@@ -1412,21 +1408,18 @@
         if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
             // If the touched window is paused then keep waiting.
             if (touchedWindow.windowHandle->getInfo()->paused) {
-#if DEBUG_FOCUS
-                ALOGD("Waiting because touched window is paused.");
-#endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.windowHandle, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime,
+                        "Waiting because the touched window is paused.");
                 goto Unresponsive;
             }
 
             // If the touched window is still working on previous events then keep waiting.
             if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) {
-#if DEBUG_FOCUS
-                ALOGD("Waiting because touched window still processing previous input.");
-#endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.windowHandle, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime,
+                        "Waiting because the touched window has not finished "
+                        "processing the input events that were previously delivered to it.");
                 goto Unresponsive;
             }
         }
@@ -1897,6 +1890,7 @@
     while (connection->status == Connection::STATUS_NORMAL
             && !connection->outboundQueue.isEmpty()) {
         DispatchEntry* dispatchEntry = connection->outboundQueue.head;
+        dispatchEntry->deliveryTime = currentTime;
 
         // Publish the event.
         status_t status;
@@ -3099,7 +3093,65 @@
         dump.append(INDENT "MonitoringChannels: <none>\n");
     }
 
-    dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
+    nsecs_t currentTime = now();
+
+    if (!mInboundQueue.isEmpty()) {
+        dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
+        for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
+            dump.append(INDENT2);
+            entry->appendDescription(dump);
+            dump.appendFormat(", age=%01.1fms\n",
+                    (currentTime - entry->eventTime) * 0.000001f);
+        }
+    } else {
+        dump.append(INDENT "InboundQueue: <empty>\n");
+    }
+
+    if (!mConnectionsByFd.isEmpty()) {
+        dump.append(INDENT "Connections:\n");
+        for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
+            const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
+            dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
+                    "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
+                    i, connection->getInputChannelName(), connection->getWindowName(),
+                    connection->getStatusLabel(), toString(connection->monitor),
+                    toString(connection->inputPublisherBlocked));
+
+            if (!connection->outboundQueue.isEmpty()) {
+                dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n",
+                        connection->outboundQueue.count());
+                for (DispatchEntry* entry = connection->outboundQueue.head; entry;
+                        entry = entry->next) {
+                    dump.append(INDENT4);
+                    entry->eventEntry->appendDescription(dump);
+                    dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%01.1fms\n",
+                            entry->targetFlags, entry->resolvedAction,
+                            (currentTime - entry->eventEntry->eventTime) * 0.000001f);
+                }
+            } else {
+                dump.append(INDENT3 "OutboundQueue: <empty>\n");
+            }
+
+            if (!connection->waitQueue.isEmpty()) {
+                dump.appendFormat(INDENT3 "WaitQueue: length=%u\n",
+                        connection->waitQueue.count());
+                for (DispatchEntry* entry = connection->waitQueue.head; entry;
+                        entry = entry->next) {
+                    dump.append(INDENT4);
+                    entry->eventEntry->appendDescription(dump);
+                    dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, "
+                            "age=%01.1fms, wait=%01.1fms\n",
+                            entry->targetFlags, entry->resolvedAction,
+                            (currentTime - entry->eventEntry->eventTime) * 0.000001f,
+                            (currentTime - entry->deliveryTime) * 0.000001f);
+                }
+            } else {
+                dump.append(INDENT3 "WaitQueue: <empty>\n");
+            }
+        }
+    } else {
+        dump.append(INDENT "Connections: <none>\n");
+    }
 
     if (isAppSwitchPendingLocked()) {
         dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
@@ -3214,6 +3266,7 @@
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
     commandEntry->connection = connection;
+    commandEntry->eventTime = currentTime;
     commandEntry->seq = seq;
     commandEntry->handled = handled;
 }
@@ -3231,12 +3284,12 @@
 void InputDispatcher::onANRLocked(
         nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
         const sp<InputWindowHandle>& windowHandle,
-        nsecs_t eventTime, nsecs_t waitStartTime) {
+        nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
     ALOGI("Application is not responding: %s.  "
-            "%01.1fms since event, %01.1fms since wait started",
+            "It has been %01.1fms since event, %01.1fms since wait started.  Reason: %s",
             getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
             (currentTime - eventTime) / 1000000.0,
-            (currentTime - waitStartTime) / 1000000.0);
+            (currentTime - waitStartTime) / 1000000.0, reason);
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
@@ -3308,12 +3361,22 @@
 void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
         CommandEntry* commandEntry) {
     sp<Connection> connection = commandEntry->connection;
+    nsecs_t finishTime = commandEntry->eventTime;
     uint32_t seq = commandEntry->seq;
     bool handled = commandEntry->handled;
 
     // Handle post-event policy actions.
     DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
     if (dispatchEntry) {
+        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
+        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
+            String8 msg;
+            msg.appendFormat("Window '%s' spent %01.1fms processing the last input event: ",
+                    connection->getWindowName(), eventDuration * 0.000001f);
+            dispatchEntry->eventEntry->appendDescription(msg);
+            ALOGI("%s", msg.string());
+        }
+
         bool restartEvent;
         if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
             KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
@@ -3656,6 +3719,10 @@
 InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
 }
 
+void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const {
+    msg.append("ConfigurationChangedEvent()");
+}
+
 
 // --- InputDispatcher::DeviceResetEntry ---
 
@@ -3667,6 +3734,10 @@
 InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
 }
 
+void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const {
+    msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId);
+}
+
 
 // --- InputDispatcher::KeyEntry ---
 
@@ -3685,6 +3756,11 @@
 InputDispatcher::KeyEntry::~KeyEntry() {
 }
 
+void InputDispatcher::KeyEntry::appendDescription(String8& msg) const {
+    msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)",
+            action, deviceId, source);
+}
+
 void InputDispatcher::KeyEntry::recycle() {
     releaseInjectionState();
 
@@ -3718,6 +3794,11 @@
 InputDispatcher::MotionEntry::~MotionEntry() {
 }
 
+void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
+    msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)",
+            action, deviceId, source);
+}
+
 
 // --- InputDispatcher::DispatchEntry ---
 
@@ -3728,7 +3809,7 @@
         seq(nextSeq()),
         eventEntry(eventEntry), targetFlags(targetFlags),
         xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
-        resolvedAction(0), resolvedFlags(0) {
+        deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
     eventEntry->refCount += 1;
 }
 
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 06b8d64..c5b8cd7 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -440,6 +440,8 @@
 
         void release();
 
+        virtual void appendDescription(String8& msg) const = 0;
+
     protected:
         EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags);
         virtual ~EventEntry();
@@ -448,6 +450,7 @@
 
     struct ConfigurationChangedEntry : EventEntry {
         ConfigurationChangedEntry(nsecs_t eventTime);
+        virtual void appendDescription(String8& msg) const;
 
     protected:
         virtual ~ConfigurationChangedEntry();
@@ -457,6 +460,7 @@
         int32_t deviceId;
 
         DeviceResetEntry(nsecs_t eventTime, int32_t deviceId);
+        virtual void appendDescription(String8& msg) const;
 
     protected:
         virtual ~DeviceResetEntry();
@@ -488,6 +492,7 @@
                 int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
                 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
                 int32_t repeatCount, nsecs_t downTime);
+        virtual void appendDescription(String8& msg) const;
         void recycle();
 
     protected:
@@ -516,6 +521,7 @@
                 float xPrecision, float yPrecision,
                 nsecs_t downTime, uint32_t pointerCount,
                 const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
+        virtual void appendDescription(String8& msg) const;
 
     protected:
         virtual ~MotionEntry();
@@ -530,6 +536,7 @@
         float xOffset;
         float yOffset;
         float scaleFactor;
+        nsecs_t deliveryTime; // time when the event was actually delivered
 
         // Set to the resolved action and flags when the event is enqueued.
         int32_t resolvedAction;
@@ -978,7 +985,7 @@
     int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
             const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
-            nsecs_t* nextWakeupTime);
+            nsecs_t* nextWakeupTime, const char* reason);
     void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
             const sp<InputChannel>& inputChannel);
     nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
@@ -1056,7 +1063,7 @@
     void onANRLocked(
             nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
-            nsecs_t eventTime, nsecs_t waitStartTime);
+            nsecs_t eventTime, nsecs_t waitStartTime, const char* reason);
 
     // Outbound policy interactions.
     void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 48219a4..2d41f43 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -586,6 +586,10 @@
         mImeSwitcherNotification.defaults = 0; // please be quiet
         mImeSwitcherNotification.sound = null;
         mImeSwitcherNotification.vibrate = null;
+
+        // Tag this notification specially so SystemUI knows it's important
+        mImeSwitcherNotification.kind = new String[] { "android.system.imeswitcher" };
+
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
         mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 985249d..2918dbc 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1702,7 +1702,9 @@
 
         mProximityAlerts.remove(intent);
         if (mProximityAlerts.size() == 0) {
-            removeUpdatesLocked(mProximityReceiver);
+            if (mProximityReceiver != null) {
+                removeUpdatesLocked(mProximityReceiver);
+            }
             mProximityReceiver = null;
             mProximityListener = null;
         }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 6695cb9..f46f8e6 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -618,9 +618,11 @@
                                 PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
 
         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
-        mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mScreenOnIntent.addFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
-        mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mScreenOffIntent.addFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
 
         Resources resources = mContext.getResources();
 
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index a36c673..152e1889 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -98,6 +98,9 @@
     // the two dragging pointers as opposed to use the location of the primary one.
     private static final int MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP = 200;
 
+    // The timeout after which we are no longer trying to detect a gesture.
+    private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
+
     // Temporary array for storing pointer IDs.
     private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
 
@@ -138,6 +141,9 @@
     // Command for delayed sending of a long press.
     private final PerformLongPressDelayed mPerformLongPressDelayed;
 
+    // Command for exiting gesture detection mode after a timeout.
+    private final ExitGestureDetectionModeDelayed mExitGestureDetectionModeDelayed;
+
     // Helper to detect and react to double tap in touch explore mode.
     private final DoubleTapDetector mDoubleTapDetector;
 
@@ -212,6 +218,7 @@
         mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
         mHandler = new Handler(context.getMainLooper());
         mPerformLongPressDelayed = new PerformLongPressDelayed();
+        mExitGestureDetectionModeDelayed = new ExitGestureDetectionModeDelayed();
         mGestureLibrary = GestureLibraries.fromRawResource(context, R.raw.accessibility_gestures);
         mGestureLibrary.setOrientationStyle(4);
         mGestureLibrary.load();
@@ -257,6 +264,7 @@
         mSendHoverEnterDelayed.remove();
         mSendHoverExitDelayed.remove();
         mPerformLongPressDelayed.remove();
+        mExitGestureDetectionModeDelayed.remove();
         // Reset the pointer trackers.
         mReceivedPointerTracker.clear();
         mInjectedPointerTracker.clear();
@@ -304,9 +312,9 @@
         switch (eventType) {
             case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
             case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
-                if (mInjectedPointerTracker.mLastInjectedHoverEvent != null) {
-                    mInjectedPointerTracker.mLastInjectedHoverEvent.recycle();
-                    mInjectedPointerTracker.mLastInjectedHoverEvent = null;
+                if (mInjectedPointerTracker.mLastInjectedHoverEventForClick != null) {
+                    mInjectedPointerTracker.mLastInjectedHoverEventForClick.recycle();
+                    mInjectedPointerTracker.mLastInjectedHoverEventForClick = null;
                 }
                 mLastTouchedWindowId = -1;
             } break;
@@ -420,6 +428,7 @@
                                     mSendHoverEnterDelayed.remove();
                                     mSendHoverExitDelayed.remove();
                                     mPerformLongPressDelayed.remove();
+                                    mExitGestureDetectionModeDelayed.post();
                                 } else {
                                     // We have just decided that the user is touch,
                                     // exploring so start sending events.
@@ -727,6 +736,7 @@
                 }
 
                 mStrokeBuffer.clear();
+                mExitGestureDetectionModeDelayed.remove();
                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
             case MotionEvent.ACTION_CANCEL: {
@@ -1067,7 +1077,8 @@
             final int pointerId = secondTapUp.getPointerId(secondTapUp.getActionIndex());
             final int pointerIndex = secondTapUp.findPointerIndex(pointerId);
 
-            MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
+            MotionEvent lastExploreEvent =
+                mInjectedPointerTracker.getLastInjectedHoverEventForClick();
             if (lastExploreEvent == null) {
                 // No last touch explored event but there is accessibility focus in
                 // the active window. We click in the middle of the focus bounds.
@@ -1263,6 +1274,25 @@
     }
 
     /**
+     * Class for delayed exiting from gesture detecting mode.
+     */
+    private final class ExitGestureDetectionModeDelayed implements Runnable {
+
+        public void post() {
+            mHandler.postDelayed(this, EXIT_GESTURE_DETECTION_TIMEOUT);
+        }
+
+        public void remove() {
+            mHandler.removeCallbacks(this);
+        }
+
+        @Override
+        public void run() {
+            clear();
+        }
+    }
+
+    /**
      * Class for delayed sending of long press.
      */
     private final class PerformLongPressDelayed implements Runnable {
@@ -1299,7 +1329,8 @@
             final int pointerId = mEvent.getPointerId(mEvent.getActionIndex());
             final int pointerIndex = mEvent.findPointerIndex(pointerId);
 
-            MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
+            MotionEvent lastExploreEvent =
+                mInjectedPointerTracker.getLastInjectedHoverEventForClick();
             if (lastExploreEvent == null) {
                 // No last touch explored event but there is accessibility focus in
                 // the active window. We click in the middle of the focus bounds.
@@ -1453,6 +1484,9 @@
         // The last injected hover event.
         private MotionEvent mLastInjectedHoverEvent;
 
+        // The last injected hover event used for performing clicks.
+        private MotionEvent mLastInjectedHoverEventForClick;
+
         /**
          * Processes an injected {@link MotionEvent} event.
          *
@@ -1484,6 +1518,10 @@
                         mLastInjectedHoverEvent.recycle();
                     }
                     mLastInjectedHoverEvent = MotionEvent.obtain(event);
+                    if (mLastInjectedHoverEventForClick != null) {
+                        mLastInjectedHoverEventForClick.recycle();
+                    }
+                    mLastInjectedHoverEventForClick = MotionEvent.obtain(event);
                 } break;
             }
             if (DEBUG) {
@@ -1537,6 +1575,13 @@
             return mLastInjectedHoverEvent;
         }
 
+        /**
+         * @return The the last injected hover event.
+         */
+        public MotionEvent getLastInjectedHoverEventForClick() {
+            return mLastInjectedHoverEventForClick;
+        }
+
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 26c5c3d..17957d2 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -164,6 +164,9 @@
         if (pendingResults != null) {
             pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
         }
+        if (pendingOptions != null) {
+            pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
+        }
         if (uriPermissions != null) {
             if (uriPermissions.readUriPermissions != null) {
                 pw.print(prefix); pw.print("readUriPermissions=");
@@ -202,7 +205,7 @@
         if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
                     pw.print(" nowVisible="); pw.print(nowVisible);
-                    pw.print("lastVisibleTime=");
+                    pw.print(" lastVisibleTime=");
                     TimeUtils.formatDuration(lastVisibleTime, pw); pw.println("");
         }
         if (configDestroy || configChangeFlags != 0) {
@@ -453,6 +456,7 @@
             if (task != null && !finishing) {
                 task.numActivities--;
             }
+            clearOptionsLocked();
         }
     }
 
@@ -466,6 +470,9 @@
             if (task != null && inHistory) {
                 task.numActivities--;
             }
+            if (stopped) {
+                clearOptionsLocked();
+            }
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 6af7a88..e2d6d98 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1055,7 +1055,9 @@
             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
             r.stopped = true;
             r.state = ActivityState.STOPPED;
-            if (!r.finishing) {
+            if (r.finishing) {
+                r.clearOptionsLocked();
+            } else {
                 if (r.configDestroy) {
                     destroyActivityLocked(r, true, false, "stop-config");
                     resumeTopActivityLocked(null);
@@ -1474,6 +1476,21 @@
             return true;
         }
 
+        // If the most recent activity was noHistory but was only stopped rather
+        // than stopped+finished because the device went to sleep, we need to make
+        // sure to finish it as we're making a new activity topmost.
+        final ActivityRecord last = mLastPausedActivity;
+        if (mService.mSleeping && last != null && !last.finishing) {
+            if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
+                    || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
+                if (DEBUG_STATES) {
+                    Slog.d(TAG, "no-history finish of " + last + " on new resume");
+                }
+                requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
+                "no-history");
+            }
+        }
+
         if (prev != null && prev != next) {
             if (!prev.waitingVisible && next != null && !next.nowVisible) {
                 prev.waitingVisible = true;
@@ -3279,10 +3296,20 @@
         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
             if (!r.finishing) {
-                requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
-                        "no-history");
+                if (!mService.mSleeping) {
+                    if (DEBUG_STATES) {
+                        Slog.d(TAG, "no-history finish of " + r);
+                    }
+                    requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
+                            "no-history");
+                } else {
+                    if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
+                            + " on stop because we're just sleeping");
+                }
             }
-        } else if (r.app != null && r.app.thread != null) {
+        }
+
+        if (r.app != null && r.app.thread != null) {
             if (mMainStack) {
                 if (mService.mFocusedActivity == r) {
                     mService.setFocusedActivityLocked(topRunningActivityLocked(null));
@@ -3524,9 +3551,10 @@
     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
             Intent resultData, String reason) {
         int index = indexOfTokenLocked(token);
-        if (DEBUG_RESULTS) Slog.v(
+        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
                 TAG, "Finishing activity @" + index + ": token=" + token
-                + ", result=" + resultCode + ", data=" + resultData);
+                + ", result=" + resultCode + ", data=" + resultData
+                + ", reason=" + reason);
         if (index < 0) {
             return false;
         }
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index e3347cb..c5b1c7b 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -59,11 +59,11 @@
         if ((modeFlagsToClear&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
             globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
             modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            if (readOwners.size() > 0) {
+            if (writeOwners.size() > 0) {
                 for (UriPermissionOwner r : writeOwners) {
                     r.removeWritePermission(this);
                 }
-                readOwners.clear();
+                writeOwners.clear();
             }
         }
     }
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index c4f9ce1..4b82037 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -106,16 +106,16 @@
             return true;
         }
 
-        // Only system user can revoke a package.
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
-            throw new SecurityException("Unauthorized Caller");
-        }
+        // Check if the caller is authorized.
+        enforceControlPermission();
 
         // Reset the interface and hide the notification.
         if (mInterface != null) {
             jniReset(mInterface);
+            long identity = Binder.clearCallingIdentity();
             mCallback.restore();
             hideNotification();
+            Binder.restoreCallingIdentity(identity);
             mInterface = null;
         }
 
@@ -291,6 +291,26 @@
     public void limitReached(String limit, String interfaze) {
     }
 
+    private void enforceControlPermission() {
+        // System user is allowed to control VPN.
+        if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+            return;
+        }
+
+        try {
+            // System dialogs are also allowed to control VPN.
+            PackageManager pm = mContext.getPackageManager();
+            ApplicationInfo app = pm.getApplicationInfo(VpnConfig.DIALOGS_PACKAGE, 0);
+            if (Binder.getCallingUid() == app.uid) {
+                return;
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        throw new SecurityException("Unauthorized Caller");
+    }
+
     private class Connection implements ServiceConnection {
         private IBinder mService;
 
@@ -368,10 +388,8 @@
      * Return the information of the current ongoing legacy VPN.
      */
     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
-        // Only system user can call this method.
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
-            throw new SecurityException("Unauthorized Caller");
-        }
+        // Check if the caller is authorized.
+        enforceControlPermission();
         return (mLegacyVpnRunner == null) ? null : mLegacyVpnRunner.getInfo();
     }
 
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index c4abac9..d4e9cbc 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1407,7 +1407,13 @@
     @Override
     public void snoozeLimit(NetworkTemplate template) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-        performSnooze(template, TYPE_LIMIT);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            performSnooze(template, TYPE_LIMIT);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private void performSnooze(NetworkTemplate template, int type) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 49d2ebd..6643d8c 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -9397,4 +9397,15 @@
             return true;
         }
     }
+
+    public boolean isStorageLow() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
+                    .getService(DeviceStorageMonitorService.SERVICE);
+            return dsm.isMemoryLow();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
 }
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index d25a960..758b6e7 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -85,12 +85,20 @@
         mPolicy = policy;
     }
 
-    void hideWallpapersLocked() {
-        for (final WindowToken token : mService.mWallpaperTokens) {
-            for (final WindowState wallpaper : token.windows) {
-                wallpaper.mWinAnimator.hide();
+    void hideWallpapersLocked(final WindowState w) {
+        if ((mService.mWallpaperTarget == w && mService.mLowerWallpaperTarget == null)
+                || mService.mWallpaperTarget == null) {
+            for (final WindowToken token : mService.mWallpaperTokens) {
+                for (final WindowState wallpaper : token.windows) {
+                    final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+                    if (!winAnimator.mLastHidden) {
+                        winAnimator.hide();
+                        mService.dispatchWallpaperVisibility(wallpaper, false);
+                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
+                }
+                token.hidden = true;
             }
-            token.hidden = true;
         }
     }
 
@@ -271,7 +279,7 @@
                         }
                         mService.mFocusMayChange = true;
                     }
-                    if (win.isReadyForDisplay()) {
+                    if (win.isReadyForDisplay() && !winAnimator.isAnimating()) {
                         mForceHiding = true;
                     }
                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
@@ -285,7 +293,7 @@
                             + " anim=" + win.mWinAnimator.mAnimation);
                 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
                     final boolean changed;
-                    if (mForceHiding) {
+                    if (mForceHiding && !winAnimator.isAnimating()) {
                         changed = win.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
                                 "Now policy hidden: " + win);
@@ -489,11 +497,7 @@
 
             final int N = mWinAnimators.size();
             for (int i = 0; i < N; i++) {
-                final WindowStateAnimator winAnimator = mWinAnimators.get(i);
-                if (winAnimator.mWin.mIsWallpaper && mService.mWallpaperTarget == null) {
-                    continue;
-                }
-                winAnimator.prepareSurfaceLocked(true);
+                mWinAnimators.get(i).prepareSurfaceLocked(true);
             }
 
             if (mDimParams != null) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index ba4df96b..6c8d969 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -127,6 +127,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.ScaleAnimation;
 
@@ -280,6 +281,8 @@
     private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
     private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
 
+    private static final float THUMBNAIL_ANIMATION_DECELERATE_FACTOR = 1.5f;
+
     final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
             new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
         @Override
@@ -882,8 +885,8 @@
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
-                "KEEP_SCREEN_ON_FLAG");
+        mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
+                | PowerManager.ON_AFTER_RELEASE, "KEEP_SCREEN_ON_FLAG");
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
         mInputManager = new InputManagerService(context, mInputMonitor);
@@ -1737,8 +1740,6 @@
                             mWallpaperTarget = oldW;
                             foundW = oldW;
                             foundI = oldI;
-                            mLowerWallpaperTarget = null;
-                            mUpperWallpaperTarget = null;
                         } 
                         // Now set the upper and lower wallpaper targets
                         // correctly, and make sure that we are positioning
@@ -1869,16 +1870,7 @@
 
                 // First, make sure the client has the current visibility
                 // state.
-                if (wallpaper.mWallpaperVisible != visible) {
-                    wallpaper.mWallpaperVisible = visible;
-                    try {
-                        if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
-                                "Setting visibility of wallpaper " + wallpaper
-                                + ": " + visible);
-                        wallpaper.mClient.dispatchAppVisibility(visible);
-                    } catch (RemoteException e) {
-                    }
-                }
+                dispatchWallpaperVisibility(wallpaper, visible);
 
                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
                 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "adjustWallpaper win "
@@ -2088,6 +2080,24 @@
         }
     }
 
+    /**
+     * Check wallpaper for visiblity change and notify window if so.
+     * @param wallpaper The wallpaper to test and notify.
+     * @param visible Current visibility.
+     */
+    void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
+        if (wallpaper.mWallpaperVisible != visible) {
+            wallpaper.mWallpaperVisible = visible;
+            try {
+                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
+                        "Updating visibility of wallpaper " + wallpaper
+                        + ": " + visible + " Callers=" + Debug.getCallers(2));
+                wallpaper.mClient.dispatchAppVisibility(visible);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
     void updateWallpaperVisibilityLocked() {
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
         final int dw = mAppDisplayWidth;
@@ -2112,16 +2122,7 @@
                     updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
                 }
 
-                if (wallpaper.mWallpaperVisible != visible) {
-                    wallpaper.mWallpaperVisible = visible;
-                    try {
-                        if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
-                                "Updating visibility of wallpaper " + wallpaper
-                                + ": " + visible);
-                        wallpaper.mClient.dispatchAppVisibility(visible);
-                    } catch (RemoteException e) {
-                    }
-                }
+                dispatchWallpaperVisibility(wallpaper, visible);
             }
         }
     }
@@ -3159,6 +3160,7 @@
             set.addAnimation(scale);
             alpha.setDuration(duration);
             set.addAnimation(alpha);
+            set.setDetachWallpaper(true);
             a = set;
         } else {
             a = createExitAnimationLocked(transit, duration);
@@ -3183,7 +3185,7 @@
         // it  is the standard duration for that.  Otherwise we use the longer
         // task transition duration.
         int duration;
-        int delayDuration = delayed ? 200 : 0;
+        int delayDuration = delayed ? 270 : 0;
         switch (transit) {
             case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
             case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
@@ -3191,7 +3193,7 @@
                         com.android.internal.R.integer.config_shortAnimTime);
                 break;
             default:
-                duration = delayed ? 200 : 300;
+                duration = delayed ? 250 : 300;
                 break;
         }
         if (thumb) {
@@ -3206,6 +3208,8 @@
             AnimationSet set = new AnimationSet(true);
             Animation alpha = new AlphaAnimation(1, 0);
             scale.setDuration(duration);
+            scale.setInterpolator(
+                    new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
             set.addAnimation(scale);
             alpha.setDuration(duration);
             set.addAnimation(alpha);
@@ -3222,6 +3226,8 @@
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
             scale.setDuration(duration);
+            scale.setInterpolator(
+                    new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
             scale.setFillBefore(true);
             if (delayDuration > 0) {
                 scale.setStartOffset(delayDuration);
@@ -3231,7 +3237,7 @@
             if (delayed) {
                 a = new AlphaAnimation(1, 0);
                 a.setStartOffset(0);
-                a.setDuration(delayDuration - 50);
+                a.setDuration(delayDuration - 120);
                 a.setBackgroundColor(0xFF000000);
             } else {
                 a = createExitAnimationLocked(transit, duration);
@@ -3959,15 +3965,6 @@
         }
     }
 
-    private void cancelWindowAnimations(final AppWindowToken wtoken) {
-        for (int i = wtoken.windows.size() - 1; i >= 0; i--) {
-            final WindowStateAnimator winAnimator = wtoken.windows.get(i).mWinAnimator;
-            if (winAnimator.isAnimating()) {
-                winAnimator.clearAnimation();
-            }
-        }
-    }
-
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -3983,12 +3980,6 @@
             }
             if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                 mAppTransitionReady = true;
-                for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
-                    cancelWindowAnimations(mOpeningApps.get(i));
-                }
-                for (int i = mClosingApps.size() - 1; i >= 0; i--) {
-                    cancelWindowAnimations(mClosingApps.get(i));
-                }
                 final long origId = Binder.clearCallingIdentity();
                 performLayoutAndPlaceSurfacesLocked();
                 Binder.restoreCallingIdentity(origId);
@@ -4336,7 +4327,6 @@
 
                 if (DEBUG_APP_TRANSITIONS) Slog.v(
                         TAG, "Setting dummy animation on: " + wtoken);
-                cancelWindowAnimations(wtoken);
                 wtoken.mAppAnimator.setDummyAnimation();
                 mOpeningApps.remove(wtoken);
                 mClosingApps.remove(wtoken);
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 5908958..579cbb7 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,7 +16,6 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Debug;
-import android.os.RemoteException;
 import android.util.Slog;
 import android.view.Surface;
 import android.view.SurfaceSession;
@@ -379,10 +378,7 @@
             mService.mPendingRemove.add(mWin);
             mWin.mRemoveOnExit = false;
         }
-        if (mService.mWallpaperTarget == mWin && mService.mLowerWallpaperTarget == null) {
-            mAnimator.hideWallpapersLocked();
-            mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-        }
+        mAnimator.hideWallpapersLocked(mWin);
     }
 
     void hide() {
@@ -738,6 +734,7 @@
                     }
                     mSurface.destroy();
                 }
+                mAnimator.hideWallpapersLocked(mWin);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Exception thrown when destroying Window " + this
                     + " surface " + mSurface + " session " + mSession
@@ -763,6 +760,7 @@
                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
                 }
                 mPendingDestroySurface.destroy();
+                mAnimator.hideWallpapersLocked(mWin);
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception thrown when destroying Window "
@@ -1065,13 +1063,13 @@
 
         setSurfaceBoundaries(recoveringMemory);
 
-        if (w.mAttachedHidden || !w.isReadyForDisplay()) {
+        if (mWin.mIsWallpaper && !mWin.mWallpaperVisible) {
+            // Wallpaper is no longer visible and there is no wp target => hide it.
             hide();
-            // TODO: Consider moving the following into hide() and out of finishExit() as well.
-            if (mService.mWallpaperTarget == mWin && mService.mLowerWallpaperTarget == null) {
-                mAnimator.hideWallpapersLocked();
-                mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-            }
+        } else if (w.mAttachedHidden || !w.isReadyForDisplay()) {
+            hide();
+            mAnimator.hideWallpapersLocked(w);
+
             // If we are waiting for this window to handle an
             // orientation change, well, it is hidden, so
             // doesn't really matter.  Note that this does
@@ -1124,6 +1122,9 @@
                                 + " during relayout");
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
+                            if (w.mIsWallpaper) {
+                                mService.dispatchWallpaperVisibility(w, true);
+                            }
                         } else {
                             w.mOrientationChanging = false;
                         }
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index d428fef..0a5e590 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -1204,7 +1204,9 @@
             }
 
             // If the application has requested WRITE_EXTERNAL_STORAGE, we will
-            // force them to always take READ_EXTERNAL_STORAGE as well.
+            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
+            // do this (regardless of target API version) because we can't have
+            // an app with write permission but not read permission.
             if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
                 printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
                 printf("uses-implied-permission:'android.permission.READ_EXTERNAL_STORAGE'," \