Merge "Turn back on global proxy support." into jb-mr2-dev
diff --git a/Android.mk b/Android.mk
index 2ad7a72..e70f9f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -69,7 +69,6 @@
 	core/java/android/app/IAlarmManager.aidl \
 	core/java/android/app/IBackupAgent.aidl \
 	core/java/android/app/IInstrumentationWatcher.aidl \
-	core/java/android/app/INotificationListener.aidl \
 	core/java/android/app/INotificationManager.aidl \
 	core/java/android/app/IProcessObserver.aidl \
 	core/java/android/app/ISearchManager.aidl \
@@ -148,6 +147,7 @@
 	core/java/android/os/IUpdateLock.aidl \
 	core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
+	core/java/android/service/notification/INotificationListener.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
 	core/java/android/service/wallpaper/IWallpaperConnection.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index fc63866..4debdc2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -159,6 +159,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodSession.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 653e25a..1e1f01c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22,6 +22,7 @@
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
+    field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
@@ -2594,6 +2595,10 @@
     method public abstract void setDisplayShowHomeEnabled(boolean);
     method public abstract void setDisplayShowTitleEnabled(boolean);
     method public abstract void setDisplayUseLogoEnabled(boolean);
+    method public void setHomeActionContentDescription(java.lang.CharSequence);
+    method public void setHomeActionContentDescription(int);
+    method public void setHomeAsUpIndicator(android.graphics.drawable.Drawable);
+    method public void setHomeAsUpIndicator(int);
     method public void setHomeButtonEnabled(boolean);
     method public abstract void setIcon(int);
     method public abstract void setIcon(android.graphics.drawable.Drawable);
@@ -18499,10 +18504,6 @@
   protected static abstract interface ContactsContract.DataUsageStatColumns {
     field public static final java.lang.String LAST_TIME_USED = "last_time_used";
     field public static final java.lang.String TIMES_USED = "times_used";
-    field public static final java.lang.String USAGE_TYPE = "usage_type";
-    field public static final int USAGE_TYPE_CALL = 0; // 0x0
-    field public static final int USAGE_TYPE_LONG_TEXT = 1; // 0x1
-    field public static final int USAGE_TYPE_SHORT_TEXT = 2; // 0x2
   }
 
   public static final class ContactsContract.Directory implements android.provider.BaseColumns {
@@ -19922,29 +19923,6 @@
     method public void skip(int);
   }
 
-  public deprecated class FileA3D extends android.renderscript.BaseObj {
-    method public static deprecated android.renderscript.FileA3D createFromAsset(android.renderscript.RenderScript, android.content.res.AssetManager, java.lang.String);
-    method public static deprecated android.renderscript.FileA3D createFromFile(android.renderscript.RenderScript, java.lang.String);
-    method public static deprecated android.renderscript.FileA3D createFromFile(android.renderscript.RenderScript, java.io.File);
-    method public static deprecated android.renderscript.FileA3D createFromResource(android.renderscript.RenderScript, android.content.res.Resources, int);
-    method public deprecated android.renderscript.FileA3D.IndexEntry getIndexEntry(int);
-    method public deprecated int getIndexEntryCount();
-  }
-
-  public static final deprecated class FileA3D.EntryType extends java.lang.Enum {
-    method public static android.renderscript.FileA3D.EntryType valueOf(java.lang.String);
-    method public static final android.renderscript.FileA3D.EntryType[] values();
-    enum_constant public static final deprecated android.renderscript.FileA3D.EntryType MESH;
-    enum_constant public static final deprecated android.renderscript.FileA3D.EntryType UNKNOWN;
-  }
-
-  public static deprecated class FileA3D.IndexEntry {
-    method public deprecated android.renderscript.FileA3D.EntryType getEntryType();
-    method public deprecated android.renderscript.Mesh getMesh();
-    method public deprecated java.lang.String getName();
-    method public deprecated android.renderscript.BaseObj getObject();
-  }
-
   public class Float2 {
     ctor public Float2();
     ctor public Float2(float, float);
@@ -19969,23 +19947,6 @@
     field public float z;
   }
 
-  public deprecated class Font extends android.renderscript.BaseObj {
-    method public static deprecated android.renderscript.Font create(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, android.renderscript.Font.Style, float);
-    method public static deprecated android.renderscript.Font createFromAsset(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, float);
-    method public static deprecated android.renderscript.Font createFromFile(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, float);
-    method public static deprecated android.renderscript.Font createFromFile(android.renderscript.RenderScript, android.content.res.Resources, java.io.File, float);
-    method public static deprecated android.renderscript.Font createFromResource(android.renderscript.RenderScript, android.content.res.Resources, int, float);
-  }
-
-  public static final deprecated class Font.Style extends java.lang.Enum {
-    method public static android.renderscript.Font.Style valueOf(java.lang.String);
-    method public static final android.renderscript.Font.Style[] values();
-    enum_constant public static final deprecated android.renderscript.Font.Style BOLD;
-    enum_constant public static final deprecated android.renderscript.Font.Style BOLD_ITALIC;
-    enum_constant public static final deprecated android.renderscript.Font.Style ITALIC;
-    enum_constant public static final deprecated android.renderscript.Font.Style NORMAL;
-  }
-
   public class Int2 {
     ctor public Int2();
     ctor public Int2(int, int);
@@ -20100,245 +20061,6 @@
     method public void transpose();
   }
 
-  public deprecated class Mesh extends android.renderscript.BaseObj {
-    method public deprecated android.renderscript.Allocation getIndexSetAllocation(int);
-    method public deprecated android.renderscript.Mesh.Primitive getPrimitive(int);
-    method public deprecated int getPrimitiveCount();
-    method public deprecated android.renderscript.Allocation getVertexAllocation(int);
-    method public deprecated int getVertexAllocationCount();
-  }
-
-  public static deprecated class Mesh.AllocationBuilder {
-    ctor public deprecated Mesh.AllocationBuilder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.Mesh.AllocationBuilder addIndexSetAllocation(android.renderscript.Allocation, android.renderscript.Mesh.Primitive);
-    method public deprecated android.renderscript.Mesh.AllocationBuilder addIndexSetType(android.renderscript.Mesh.Primitive);
-    method public deprecated android.renderscript.Mesh.AllocationBuilder addVertexAllocation(android.renderscript.Allocation) throws java.lang.IllegalStateException;
-    method public deprecated android.renderscript.Mesh create();
-    method public deprecated int getCurrentIndexSetIndex();
-    method public deprecated int getCurrentVertexTypeIndex();
-  }
-
-  public static deprecated class Mesh.Builder {
-    ctor public deprecated Mesh.Builder(android.renderscript.RenderScript, int);
-    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Type, android.renderscript.Mesh.Primitive);
-    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Mesh.Primitive);
-    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Element, int, android.renderscript.Mesh.Primitive);
-    method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Type) throws java.lang.IllegalStateException;
-    method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Element, int) throws java.lang.IllegalStateException;
-    method public deprecated android.renderscript.Mesh create();
-    method public deprecated int getCurrentIndexSetIndex();
-    method public deprecated int getCurrentVertexTypeIndex();
-  }
-
-  public static final deprecated class Mesh.Primitive extends java.lang.Enum {
-    method public static android.renderscript.Mesh.Primitive valueOf(java.lang.String);
-    method public static final android.renderscript.Mesh.Primitive[] values();
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE;
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE_STRIP;
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive POINT;
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE;
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_FAN;
-    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_STRIP;
-  }
-
-  public static deprecated class Mesh.TriangleMeshBuilder {
-    ctor public deprecated Mesh.TriangleMeshBuilder(android.renderscript.RenderScript, int, int);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addTriangle(int, int, int);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addVertex(float, float);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addVertex(float, float, float);
-    method public deprecated android.renderscript.Mesh create(boolean);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setColor(float, float, float, float);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setNormal(float, float, float);
-    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setTexture(float, float);
-    field public static final deprecated int COLOR = 1; // 0x1
-    field public static final deprecated int NORMAL = 2; // 0x2
-    field public static final deprecated int TEXTURE_0 = 256; // 0x100
-  }
-
-  public class Program extends android.renderscript.BaseObj {
-    method public void bindConstants(android.renderscript.Allocation, int);
-    method public void bindSampler(android.renderscript.Sampler, int) throws java.lang.IllegalArgumentException;
-    method public void bindTexture(android.renderscript.Allocation, int) throws java.lang.IllegalArgumentException;
-    method public android.renderscript.Type getConstant(int);
-    method public int getConstantCount();
-    method public int getTextureCount();
-    method public java.lang.String getTextureName(int);
-    method public android.renderscript.Program.TextureType getTextureType(int);
-  }
-
-  public static class Program.BaseProgramBuilder {
-    ctor protected Program.BaseProgramBuilder(android.renderscript.RenderScript);
-    method public android.renderscript.Program.BaseProgramBuilder addConstant(android.renderscript.Type) throws java.lang.IllegalStateException;
-    method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType) throws java.lang.IllegalArgumentException;
-    method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType, java.lang.String) throws java.lang.IllegalArgumentException;
-    method public int getCurrentConstantIndex();
-    method public int getCurrentTextureIndex();
-    method protected void initProgram(android.renderscript.Program);
-    method public android.renderscript.Program.BaseProgramBuilder setShader(java.lang.String);
-    method public android.renderscript.Program.BaseProgramBuilder setShader(android.content.res.Resources, int);
-  }
-
-  public static final class Program.TextureType extends java.lang.Enum {
-    method public static android.renderscript.Program.TextureType valueOf(java.lang.String);
-    method public static final android.renderscript.Program.TextureType[] values();
-    enum_constant public static final android.renderscript.Program.TextureType TEXTURE_2D;
-    enum_constant public static final android.renderscript.Program.TextureType TEXTURE_CUBE;
-  }
-
-  public deprecated class ProgramFragment extends android.renderscript.Program {
-  }
-
-  public static deprecated class ProgramFragment.Builder extends android.renderscript.Program.BaseProgramBuilder {
-    ctor public deprecated ProgramFragment.Builder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramFragment create();
-  }
-
-  public deprecated class ProgramFragmentFixedFunction extends android.renderscript.ProgramFragment {
-  }
-
-  public static deprecated class ProgramFragmentFixedFunction.Builder {
-    ctor public deprecated ProgramFragmentFixedFunction.Builder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramFragmentFixedFunction create();
-    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setPointSpriteTexCoordinateReplacement(boolean);
-    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setTexture(android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode, android.renderscript.ProgramFragmentFixedFunction.Builder.Format, int) throws java.lang.IllegalArgumentException;
-    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setVaryingColor(boolean);
-    field public static final deprecated int MAX_TEXTURE = 2; // 0x2
-  }
-
-  public static final deprecated class ProgramFragmentFixedFunction.Builder.EnvMode extends java.lang.Enum {
-    method public static android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode[] values();
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode DECAL;
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode MODULATE;
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode REPLACE;
-  }
-
-  public static final deprecated class ProgramFragmentFixedFunction.Builder.Format extends java.lang.Enum {
-    method public static android.renderscript.ProgramFragmentFixedFunction.Builder.Format valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramFragmentFixedFunction.Builder.Format[] values();
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format ALPHA;
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format LUMINANCE_ALPHA;
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format RGB;
-    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format RGBA;
-  }
-
-  public deprecated class ProgramRaster extends android.renderscript.BaseObj {
-    method public static deprecated android.renderscript.ProgramRaster CULL_BACK(android.renderscript.RenderScript);
-    method public static deprecated android.renderscript.ProgramRaster CULL_FRONT(android.renderscript.RenderScript);
-    method public static deprecated android.renderscript.ProgramRaster CULL_NONE(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramRaster.CullMode getCullMode();
-    method public deprecated boolean isPointSpriteEnabled();
-  }
-
-  public static deprecated class ProgramRaster.Builder {
-    ctor public deprecated ProgramRaster.Builder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramRaster create();
-    method public deprecated android.renderscript.ProgramRaster.Builder setCullMode(android.renderscript.ProgramRaster.CullMode);
-    method public deprecated android.renderscript.ProgramRaster.Builder setPointSpriteEnabled(boolean);
-  }
-
-  public static final deprecated class ProgramRaster.CullMode extends java.lang.Enum {
-    method public static android.renderscript.ProgramRaster.CullMode valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramRaster.CullMode[] values();
-    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode BACK;
-    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode FRONT;
-    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode NONE;
-  }
-
-  public class ProgramStore extends android.renderscript.BaseObj {
-    method public static android.renderscript.ProgramStore BLEND_ALPHA_DEPTH_NONE(android.renderscript.RenderScript);
-    method public static android.renderscript.ProgramStore BLEND_ALPHA_DEPTH_TEST(android.renderscript.RenderScript);
-    method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_NONE(android.renderscript.RenderScript);
-    method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_TEST(android.renderscript.RenderScript);
-    method public android.renderscript.ProgramStore.BlendDstFunc getBlendDstFunc();
-    method public android.renderscript.ProgramStore.BlendSrcFunc getBlendSrcFunc();
-    method public android.renderscript.ProgramStore.DepthFunc getDepthFunc();
-    method public boolean isColorMaskAlphaEnabled();
-    method public boolean isColorMaskBlueEnabled();
-    method public boolean isColorMaskGreenEnabled();
-    method public boolean isColorMaskRedEnabled();
-    method public boolean isDepthMaskEnabled();
-    method public boolean isDitherEnabled();
-  }
-
-  public static final class ProgramStore.BlendDstFunc extends java.lang.Enum {
-    method public static android.renderscript.ProgramStore.BlendDstFunc valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramStore.BlendDstFunc[] values();
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc DST_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_DST_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_SRC_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_SRC_COLOR;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc SRC_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc SRC_COLOR;
-    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ZERO;
-  }
-
-  public static final class ProgramStore.BlendSrcFunc extends java.lang.Enum {
-    method public static android.renderscript.ProgramStore.BlendSrcFunc valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramStore.BlendSrcFunc[] values();
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc DST_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc DST_COLOR;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_DST_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_DST_COLOR;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_SRC_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc SRC_ALPHA;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc SRC_ALPHA_SATURATE;
-    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ZERO;
-  }
-
-  public static class ProgramStore.Builder {
-    ctor public ProgramStore.Builder(android.renderscript.RenderScript);
-    method public android.renderscript.ProgramStore create();
-    method public android.renderscript.ProgramStore.Builder setBlendFunc(android.renderscript.ProgramStore.BlendSrcFunc, android.renderscript.ProgramStore.BlendDstFunc);
-    method public android.renderscript.ProgramStore.Builder setColorMaskEnabled(boolean, boolean, boolean, boolean);
-    method public android.renderscript.ProgramStore.Builder setDepthFunc(android.renderscript.ProgramStore.DepthFunc);
-    method public android.renderscript.ProgramStore.Builder setDepthMaskEnabled(boolean);
-    method public android.renderscript.ProgramStore.Builder setDitherEnabled(boolean);
-  }
-
-  public static final class ProgramStore.DepthFunc extends java.lang.Enum {
-    method public static android.renderscript.ProgramStore.DepthFunc valueOf(java.lang.String);
-    method public static final android.renderscript.ProgramStore.DepthFunc[] values();
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc ALWAYS;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc EQUAL;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc GREATER;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc GREATER_OR_EQUAL;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc LESS;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc LESS_OR_EQUAL;
-    enum_constant public static final android.renderscript.ProgramStore.DepthFunc NOT_EQUAL;
-  }
-
-  public deprecated class ProgramVertex extends android.renderscript.Program {
-    method public deprecated android.renderscript.Element getInput(int);
-    method public deprecated int getInputCount();
-  }
-
-  public static deprecated class ProgramVertex.Builder extends android.renderscript.Program.BaseProgramBuilder {
-    ctor public deprecated ProgramVertex.Builder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramVertex.Builder addInput(android.renderscript.Element) throws java.lang.IllegalStateException;
-    method public deprecated android.renderscript.ProgramVertex create();
-  }
-
-  public deprecated class ProgramVertexFixedFunction extends android.renderscript.ProgramVertex {
-    method public deprecated void bindConstants(android.renderscript.ProgramVertexFixedFunction.Constants);
-  }
-
-  public static deprecated class ProgramVertexFixedFunction.Builder {
-    ctor public deprecated ProgramVertexFixedFunction.Builder(android.renderscript.RenderScript);
-    method public deprecated android.renderscript.ProgramVertexFixedFunction create();
-    method public deprecated android.renderscript.ProgramVertexFixedFunction.Builder setTextureMatrixEnable(boolean);
-  }
-
-  public static deprecated class ProgramVertexFixedFunction.Constants {
-    ctor public deprecated ProgramVertexFixedFunction.Constants(android.renderscript.RenderScript);
-    method public deprecated void destroy();
-    method public deprecated void setModelview(android.renderscript.Matrix4f);
-    method public deprecated void setProjection(android.renderscript.Matrix4f);
-    method public deprecated void setTexture(android.renderscript.Matrix4f);
-  }
-
   public class RSDriverException extends android.renderscript.RSRuntimeException {
     ctor public RSDriverException(java.lang.String);
   }
@@ -20355,35 +20077,6 @@
     ctor public RSRuntimeException(java.lang.String);
   }
 
-  public deprecated class RSSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
-    ctor public deprecated RSSurfaceView(android.content.Context);
-    ctor public deprecated RSSurfaceView(android.content.Context, android.util.AttributeSet);
-    method public deprecated android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
-    method public deprecated void destroyRenderScriptGL();
-    method public deprecated android.renderscript.RenderScriptGL getRenderScriptGL();
-    method public deprecated void pause();
-    method public deprecated void resume();
-    method public deprecated void setRenderScriptGL(android.renderscript.RenderScriptGL);
-    method public deprecated void surfaceChanged(android.view.SurfaceHolder, int, int, int);
-    method public deprecated void surfaceCreated(android.view.SurfaceHolder);
-    method public deprecated void surfaceDestroyed(android.view.SurfaceHolder);
-  }
-
-  public deprecated class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
-    ctor public deprecated RSTextureView(android.content.Context);
-    ctor public deprecated RSTextureView(android.content.Context, android.util.AttributeSet);
-    method public deprecated android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
-    method public deprecated void destroyRenderScriptGL();
-    method public deprecated android.renderscript.RenderScriptGL getRenderScriptGL();
-    method public deprecated void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
-    method public deprecated boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
-    method public deprecated void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
-    method public deprecated void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
-    method public deprecated void pause();
-    method public deprecated void resume();
-    method public deprecated void setRenderScriptGL(android.renderscript.RenderScriptGL);
-  }
-
   public class RenderScript {
     method public void contextDump();
     method public static android.renderscript.RenderScript create(android.content.Context);
@@ -20427,30 +20120,6 @@
     field protected int mLength;
   }
 
-  public deprecated class RenderScriptGL extends android.renderscript.RenderScript {
-    ctor public deprecated RenderScriptGL(android.content.Context, android.renderscript.RenderScriptGL.SurfaceConfig);
-    method public deprecated void bindProgramFragment(android.renderscript.ProgramFragment);
-    method public deprecated void bindProgramRaster(android.renderscript.ProgramRaster);
-    method public deprecated void bindProgramStore(android.renderscript.ProgramStore);
-    method public deprecated void bindProgramVertex(android.renderscript.ProgramVertex);
-    method public deprecated void bindRootScript(android.renderscript.Script);
-    method public deprecated int getHeight();
-    method public deprecated int getWidth();
-    method public deprecated void pause();
-    method public deprecated void resume();
-    method public deprecated void setSurface(android.view.SurfaceHolder, int, int);
-    method public deprecated void setSurfaceTexture(android.graphics.SurfaceTexture, int, int);
-  }
-
-  public static deprecated class RenderScriptGL.SurfaceConfig {
-    ctor public deprecated RenderScriptGL.SurfaceConfig();
-    ctor public deprecated RenderScriptGL.SurfaceConfig(android.renderscript.RenderScriptGL.SurfaceConfig);
-    method public deprecated void setAlpha(int, int);
-    method public deprecated void setColor(int, int);
-    method public deprecated void setDepth(int, int);
-    method public deprecated void setSamples(int, int, float);
-  }
-
   public class Sampler extends android.renderscript.BaseObj {
     method public static android.renderscript.Sampler CLAMP_LINEAR(android.renderscript.RenderScript);
     method public static android.renderscript.Sampler CLAMP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
@@ -20764,6 +20433,19 @@
 
 package android.security {
 
+  public class AndroidKeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec {
+  }
+
+  public static class AndroidKeyPairGeneratorSpec.Builder {
+    ctor public AndroidKeyPairGeneratorSpec.Builder(android.content.Context);
+    method public android.security.AndroidKeyPairGeneratorSpec build();
+    method public android.security.AndroidKeyPairGeneratorSpec.Builder setAlias(java.lang.String);
+    method public android.security.AndroidKeyPairGeneratorSpec.Builder setEndDate(java.util.Date);
+    method public android.security.AndroidKeyPairGeneratorSpec.Builder setSerialNumber(java.math.BigInteger);
+    method public android.security.AndroidKeyPairGeneratorSpec.Builder setStartDate(java.util.Date);
+    method public android.security.AndroidKeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
+  }
+
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -20839,6 +20521,38 @@
 
 }
 
+package android.service.notification {
+
+  public abstract class NotificationListenerService extends android.app.Service {
+    ctor public NotificationListenerService();
+    method public final void clearAllNotifications();
+    method public final void clearNotification(java.lang.String, java.lang.String, int);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
+    method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
+  }
+
+  public class StatusBarNotification implements android.os.Parcelable {
+    ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
+    ctor public StatusBarNotification(android.os.Parcel);
+    method public android.service.notification.StatusBarNotification clone();
+    method public int describeContents();
+    method public int getUserId();
+    method public boolean isClearable();
+    method public boolean isOngoing();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final int id;
+    field public final android.app.Notification notification;
+    field public final java.lang.String pkg;
+    field public final long postTime;
+    field public final java.lang.String tag;
+    field public final android.os.UserHandle user;
+  }
+
+}
+
 package android.service.textservice {
 
   public abstract class SpellCheckerService extends android.app.Service {
@@ -24490,6 +24204,7 @@
     method public float getMax();
     method public float getMin();
     method public float getRange();
+    method public float getResolution();
     method public int getSource();
     method public boolean isFromSource(int);
   }
@@ -25247,14 +24962,6 @@
     field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
   }
 
-  public abstract interface Overlay {
-    method public abstract void add(android.graphics.drawable.Drawable);
-    method public abstract void add(android.view.View);
-    method public abstract void clear();
-    method public abstract void remove(android.graphics.drawable.Drawable);
-    method public abstract void remove(android.view.View);
-  }
-
   public class ScaleGestureDetector {
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
     method public float getCurrentSpan();
@@ -25559,7 +25266,7 @@
     method public int getNextFocusUpId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public int getOverScrollMode();
-    method public android.view.Overlay getOverlay();
+    method public android.view.ViewOverlay getOverlay();
     method public int getPaddingBottom();
     method public int getPaddingEnd();
     method public int getPaddingLeft();
@@ -26300,12 +26007,23 @@
     method public abstract void onChildViewRemoved(android.view.View, android.view.View);
   }
 
+  public class ViewGroupOverlay extends android.view.ViewOverlay {
+    method public void add(android.view.View);
+    method public void remove(android.view.View);
+  }
+
   public abstract interface ViewManager {
     method public abstract void addView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public abstract void removeView(android.view.View);
     method public abstract void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
   }
 
+  public class ViewOverlay {
+    method public void add(android.graphics.drawable.Drawable);
+    method public void clear();
+    method public void remove(android.graphics.drawable.Drawable);
+  }
+
   public abstract interface ViewParent {
     method public abstract void bringChildToFront(android.view.View);
     method public abstract void childDrawableStateChanged(android.view.View);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 1c02960..ccb9e1f 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -39,6 +39,7 @@
 import android.os.UserHandle;
 import android.util.AndroidException;
 import android.view.IWindowManager;
+import com.android.internal.os.BaseCommand;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -50,12 +51,9 @@
 import java.util.HashSet;
 import java.util.List;
 
-public class Am {
+public class Am extends BaseCommand {
 
     private IActivityManager mAm;
-    private String[] mArgs;
-    private int mNextArg;
-    private String mCurArgData;
 
     private int mStartFlags = 0;
     private boolean mWaitOption = false;
@@ -67,33 +65,155 @@
 
     private String mProfileFile;
 
-    // These are magic strings understood by the Eclipse plugin.
-    private static final String FATAL_ERROR_CODE = "Error type 1";
-    private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
-    private static final String NO_CLASS_ERROR_CODE = "Error type 3";
-
     /**
      * Command-line entry point.
      *
      * @param args The command-line arguments
      */
     public static void main(String[] args) {
-        try {
-            (new Am()).run(args);
-        } catch (IllegalArgumentException e) {
-            showUsage();
-            System.err.println("Error: " + e.getMessage());
-        } catch (Exception e) {
-            e.printStackTrace(System.err);
-            System.exit(1);
-        }
+        (new Am()).run(args);
     }
 
-    private void run(String[] args) throws Exception {
-        if (args.length < 1) {
-            showUsage();
-            return;
-        }
+    public void onShowUsage(PrintStream out) {
+        out.println(
+                "usage: am [subcommand] [options]\n" +
+                "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
+                "               [--R COUNT] [-S] [--opengl-trace]\n" +
+                "               [--user <USER_ID> | current] <INTENT>\n" +
+                "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
+                "       am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
+                "       am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
+                "       am kill-all\n" +
+                "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
+                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
+                "               [--user <USER_ID> | current]\n" +
+                "               [--no-window-animation] <COMPONENT>\n" +
+                "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
+                "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
+                "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
+                "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
+                "       am clear-debug-app\n" +
+                "       am monitor [--gdb <port>]\n" +
+                "       am screen-compat [on|off] <PACKAGE>\n" +
+                "       am to-uri [INTENT]\n" +
+                "       am to-intent-uri [INTENT]\n" +
+                "       am switch-user <USER_ID>\n" +
+                "       am stop-user <USER_ID>\n" +
+                "\n" +
+                "am start: start an Activity.  Options are:\n" +
+                "    -D: enable debugging\n" +
+                "    -W: wait for launch to complete\n" +
+                "    --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
+                "    -P <FILE>: like above, but profiling stops when app goes idle\n" +
+                "    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,\n" +
+                "        the top activity will be finished.\n" +
+                "    -S: force stop the target app before starting the activity\n" +
+                "    --opengl-trace: enable tracing of OpenGL functions\n" +
+                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
+                "        specified then run as the current user.\n" +
+                "\n" +
+                "am startservice: start a Service.  Options are:\n" +
+                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
+                "        specified then run as the current user.\n" +
+                "\n" +
+                "am force-stop: force stop everything associated with <PACKAGE>.\n" +
+                "    --user <USER_ID> | all | current: Specify user to force stop;\n" +
+                "        all users if not specified.\n" +
+                "\n" +
+                "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
+                "  processes that are safe to kill -- that is, will not impact the user\n" +
+                "  experience.\n" +
+                "    --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
+                "        all users if not specified.\n" +
+                "\n" +
+                "am kill-all: Kill all background processes.\n" +
+                "\n" +
+                "am broadcast: send a broadcast Intent.  Options are:\n" +
+                "    --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
+                "        specified then send to all users.\n" +
+                "    --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
+                "\n" +
+                "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
+                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
+                "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
+                "        [-e perf true] to generate raw output for performance measurements.\n" +
+                "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
+                "        common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
+                "    -p <FILE>: write profiling data to <FILE>\n" +
+                "    -w: wait for instrumentation to finish before returning.  Required for\n" +
+                "        test runners.\n" +
+                "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
+                "        current user if not specified.\n" +
+                "    --no-window-animation: turn off window animations will running.\n" +
+                "\n" +
+                "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
+                "  may be either a process name or pid.  Options are:\n" +
+                "    --user <USER_ID> | current: When supplying a process name,\n" +
+                "        specify user of process to profile; uses current user if not specified.\n" +
+                "\n" +
+                "am dumpheap: dump the heap of a process.  The given <PROCESS> argument may\n" +
+                "  be either a process name or pid.  Options are:\n" +
+                "    -n: dump native heap instead of managed heap\n" +
+                "    --user <USER_ID> | current: When supplying a process name,\n" +
+                "        specify user of process to dump; uses current user if not specified.\n" +
+                "\n" +
+                "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
+                "    -w: wait for debugger when application starts\n" +
+                "    --persistent: retain this value\n" +
+                "\n" +
+                "am clear-debug-app: clear the previously set-debug-app.\n" +
+                "\n" +
+                "am bug-report: request bug report generation; will launch UI\n" +
+                "    when done to select where it should be delivered.\n" +
+                "\n" +
+                "am monitor: start monitoring for crashes or ANRs.\n" +
+                "    --gdb: start gdbserv on the given port at crash/ANR\n" +
+                "\n" +
+                "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
+                "\n" +
+                "am to-uri: print the given Intent specification as a URI.\n" +
+                "\n" +
+                "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
+                "\n" +
+                "am switch-user: switch to put USER_ID in the foreground, starting\n" +
+                "  execution of that user if it is currently stopped.\n" +
+                "\n" +
+                "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
+                "  code until a later explicit switch to it.\n" +
+                "\n" +
+                "<INTENT> specifications include these flags and arguments:\n" +
+                "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+                "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+                "    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+                "    [--esn <EXTRA_KEY> ...]\n" +
+                "    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+                "    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+                "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+                "    [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
+                "    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
+                "    [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
+                "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+                "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+                "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
+                "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
+                "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+                "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
+                "    [--include-stopped-packages]\n" +
+                "    [--activity-brought-to-front] [--activity-clear-top]\n" +
+                "    [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
+                "    [--activity-launched-from-history] [--activity-multiple-task]\n" +
+                "    [--activity-no-animation] [--activity-no-history]\n" +
+                "    [--activity-no-user-action] [--activity-previous-is-top]\n" +
+                "    [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
+                "    [--activity-single-top] [--activity-clear-task]\n" +
+                "    [--activity-task-on-home]\n" +
+                "    [--receiver-registered-only] [--receiver-replace-pending]\n" +
+                "    [--selector]\n" +
+                "    [<URI> | <PACKAGE> | <COMPONENT>]\n"
+                );
+    }
+
+    public void onRun() throws Exception {
 
         mAm = ActivityManagerNative.getDefault();
         if (mAm == null) {
@@ -101,9 +221,7 @@
             throw new AndroidException("Can't connect to activity manager; is the system running?");
         }
 
-        mArgs = args;
-        String op = args[0];
-        mNextArg = 1;
+        String op = nextArgRequired();
 
         if (op.equals("start")) {
             runStart();
@@ -142,7 +260,7 @@
         } else if (op.equals("stop-user")) {
             runStopUser();
         } else {
-            throw new IllegalArgumentException("Unknown command: " + op);
+            showError("Error: unknown command '" + op + "'");
         }
     }
 
@@ -1303,193 +1421,4 @@
             return true;
         }
     }
-
-    private String nextOption() {
-        if (mCurArgData != null) {
-            String prev = mArgs[mNextArg - 1];
-            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
-        }
-        if (mNextArg >= mArgs.length) {
-            return null;
-        }
-        String arg = mArgs[mNextArg];
-        if (!arg.startsWith("-")) {
-            return null;
-        }
-        mNextArg++;
-        if (arg.equals("--")) {
-            return null;
-        }
-        if (arg.length() > 1 && arg.charAt(1) != '-') {
-            if (arg.length() > 2) {
-                mCurArgData = arg.substring(2);
-                return arg.substring(0, 2);
-            } else {
-                mCurArgData = null;
-                return arg;
-            }
-        }
-        mCurArgData = null;
-        return arg;
-    }
-
-    private String nextArg() {
-        if (mCurArgData != null) {
-            String arg = mCurArgData;
-            mCurArgData = null;
-            return arg;
-        } else if (mNextArg < mArgs.length) {
-            return mArgs[mNextArg++];
-        } else {
-            return null;
-        }
-    }
-
-    private String nextArgRequired() {
-        String arg = nextArg();
-        if (arg == null) {
-            String prev = mArgs[mNextArg - 1];
-            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
-        }
-        return arg;
-    }
-
-    private static void showUsage() {
-        System.err.println(
-                "usage: am [subcommand] [options]\n" +
-                "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
-                "               [--R COUNT] [-S] [--opengl-trace]\n" +
-                "               [--user <USER_ID> | current] <INTENT>\n" +
-                "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
-                "       am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
-                "       am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
-                "       am kill-all\n" +
-                "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
-                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
-                "               [--user <USER_ID> | current]\n" +
-                "               [--no-window-animation] <COMPONENT>\n" +
-                "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
-                "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
-                "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
-                "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
-                "       am clear-debug-app\n" +
-                "       am monitor [--gdb <port>]\n" +
-                "       am screen-compat [on|off] <PACKAGE>\n" +
-                "       am to-uri [INTENT]\n" +
-                "       am to-intent-uri [INTENT]\n" +
-                "       am switch-user <USER_ID>\n" +
-                "       am stop-user <USER_ID>\n" +
-                "\n" +
-                "am start: start an Activity.  Options are:\n" +
-                "    -D: enable debugging\n" +
-                "    -W: wait for launch to complete\n" +
-                "    --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
-                "    -P <FILE>: like above, but profiling stops when app goes idle\n" +
-                "    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,\n" +
-                "        the top activity will be finished.\n" +
-                "    -S: force stop the target app before starting the activity\n" +
-                "    --opengl-trace: enable tracing of OpenGL functions\n" +
-                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
-                "        specified then run as the current user.\n" +
-                "\n" +
-                "am startservice: start a Service.  Options are:\n" +
-                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
-                "        specified then run as the current user.\n" +
-                "\n" +
-                "am force-stop: force stop everything associated with <PACKAGE>.\n" +
-                "    --user <USER_ID> | all | current: Specify user to force stop;\n" +
-                "        all users if not specified.\n" +
-                "\n" +
-                "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
-                "  processes that are safe to kill -- that is, will not impact the user\n" +
-                "  experience.\n" +
-                "    --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
-                "        all users if not specified.\n" +
-                "\n" +
-                "am kill-all: Kill all background processes.\n" +
-                "\n" +
-                "am broadcast: send a broadcast Intent.  Options are:\n" +
-                "    --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
-                "        specified then send to all users.\n" +
-                "    --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
-                "\n" +
-                "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
-                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
-                "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
-                "        [-e perf true] to generate raw output for performance measurements.\n" +
-                "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
-                "        common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
-                "    -p <FILE>: write profiling data to <FILE>\n" +
-                "    -w: wait for instrumentation to finish before returning.  Required for\n" +
-                "        test runners.\n" +
-                "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
-                "        current user if not specified.\n" +
-                "    --no-window-animation: turn off window animations will running.\n" +
-                "\n" +
-                "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
-                "  may be either a process name or pid.  Options are:\n" +
-                "    --user <USER_ID> | current: When supplying a process name,\n" +
-                "        specify user of process to profile; uses current user if not specified.\n" +
-                "\n" +
-                "am dumpheap: dump the heap of a process.  The given <PROCESS> argument may\n" +
-                "  be either a process name or pid.  Options are:\n" +
-                "    -n: dump native heap instead of managed heap\n" +
-                "    --user <USER_ID> | current: When supplying a process name,\n" +
-                "        specify user of process to dump; uses current user if not specified.\n" +
-                "\n" +
-                "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
-                "    -w: wait for debugger when application starts\n" +
-                "    --persistent: retain this value\n" +
-                "\n" +
-                "am clear-debug-app: clear the previously set-debug-app.\n" +
-                "\n" +
-                "am bug-report: request bug report generation; will launch UI\n" +
-                "    when done to select where it should be delivered.\n" +
-                "\n" +
-                "am monitor: start monitoring for crashes or ANRs.\n" +
-                "    --gdb: start gdbserv on the given port at crash/ANR\n" +
-                "\n" +
-                "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
-                "\n" +
-                "am to-uri: print the given Intent specification as a URI.\n" +
-                "\n" +
-                "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
-                "\n" +
-                "am switch-user: switch to put USER_ID in the foreground, starting\n" +
-                "  execution of that user if it is currently stopped.\n" +
-                "\n" +
-                "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
-                "  code until a later explicit switch to it.\n" +
-                "\n" +
-                "<INTENT> specifications include these flags and arguments:\n" +
-                "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
-                "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
-                "    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
-                "    [--esn <EXTRA_KEY> ...]\n" +
-                "    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
-                "    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
-                "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
-                "    [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
-                "    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
-                "    [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
-                "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
-                "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
-                "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
-                "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
-                "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
-                "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
-                "    [--include-stopped-packages]\n" +
-                "    [--activity-brought-to-front] [--activity-clear-top]\n" +
-                "    [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
-                "    [--activity-launched-from-history] [--activity-multiple-task]\n" +
-                "    [--activity-no-animation] [--activity-no-history]\n" +
-                "    [--activity-no-user-action] [--activity-previous-is-top]\n" +
-                "    [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
-                "    [--activity-single-top] [--activity-clear-task]\n" +
-                "    [--activity-task-on-home]\n" +
-                "    [--receiver-registered-only] [--receiver-replace-pending]\n" +
-                "    [--selector]\n" +
-                "    [<URI> | <PACKAGE> | <COMPONENT>]\n"
-                );
-    }
 }
diff --git a/cmds/media/Android.mk b/cmds/media/Android.mk
new file mode 100644
index 0000000..b9451c5
--- /dev/null
+++ b/cmds/media/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2013 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := media_cmd
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := media
+LOCAL_SRC_FILES := media
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
diff --git a/cmds/media/MODULE_LICENSE_APACHE2 b/cmds/media/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/media/MODULE_LICENSE_APACHE2
diff --git a/cmds/media/NOTICE b/cmds/media/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/media/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/cmds/media/media b/cmds/media/media
new file mode 100755
index 0000000..1194442
--- /dev/null
+++ b/cmds/media/media
@@ -0,0 +1,6 @@
+# Script to start "media_cmd" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/media_cmd.jar
+exec app_process $base/bin com.android.commands.media.Media "$@"
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
new file mode 100644
index 0000000..56af7d6
--- /dev/null
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -0,0 +1,220 @@
+/*
+**
+** Copyright 2013, 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.commands.media;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.IAudioService;
+import android.media.IRemoteControlDisplay;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.AndroidException;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import com.android.internal.os.BaseCommand;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+
+public class Media extends BaseCommand {
+
+    private IAudioService mAudioService;
+
+    /**
+     * Command-line entry point.
+     *
+     * @param args The command-line arguments
+     */
+    public static void main(String[] args) {
+        (new Media()).run(args);
+    }
+
+    public void onShowUsage(PrintStream out) {
+        out.println(
+                "usage: media [subcommand] [options]\n" +
+                "       media dispatch KEY\n" +
+                "       media remote-display\n" +
+                "\n" +
+                "media dispatch: dispatch a media key to the current media client.\n" +
+                "                KEY may be: play, pause, play-pause, mute, headsethook,\n" +
+                "                stop, next, previous, rewind, recordm fast-forword.\n" +
+                "media remote-display: monitor remote display updates.\n"
+        );
+    }
+
+    public void onRun() throws Exception {
+        mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService(
+                Context.AUDIO_SERVICE));
+        if (mAudioService == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to audio service; is the system running?");
+        }
+
+        String op = nextArgRequired();
+
+        if (op.equals("dispatch")) {
+            runDispatch();
+        } else if (op.equals("remote-display")) {
+            runRemoteDisplay();
+        } else {
+            showError("Error: unknown command '" + op + "'");
+            return;
+        }
+    }
+
+    private void sendMediaKey(KeyEvent event) {
+        try {
+            mAudioService.dispatchMediaKeyEvent(event);
+        } catch (RemoteException e) {
+        }
+    }
+
+    private void runDispatch() throws Exception {
+        String cmd = nextArgRequired();
+        int keycode;
+        if ("play".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_PLAY;
+        } else if ("pause".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_PAUSE;
+        } else if ("play-pause".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+        } else if ("mute".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MUTE;
+        } else if ("headsethook".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_HEADSETHOOK;
+        } else if ("stop".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_STOP;
+        } else if ("next".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_NEXT;
+        } else if ("previous".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+        } else if ("rewind".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_REWIND;
+        } else if ("record".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_RECORD;
+        } else if ("fast-forward".equals(cmd)) {
+            keycode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
+        } else {
+            showError("Error: unknown dispatch code '" + cmd + "'");
+            return;
+        }
+
+        final long now = SystemClock.uptimeMillis();
+        sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
+        sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
+    }
+
+    class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub {
+        RemoteDisplayMonitor() {
+        }
+
+
+        @Override
+        public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent,
+                boolean clearing) {
+            System.out.println("New client: id=" + clientGeneration
+                    + " intent=" + clientMediaIntent + " clearing=" + clearing);
+        }
+
+        @Override
+        public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
+                long currentPosMs, float speed) {
+            System.out.println("New state: id=" + generationId + " state=" + state
+                    + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed);
+        }
+
+        @Override
+        public void setTransportControlInfo(int generationId, int transportControlFlags,
+                int posCapabilities) {
+            System.out.println("New control info: id=" + generationId
+                    + " flags=0x" + Integer.toHexString(transportControlFlags)
+                    + " cap=0x" + Integer.toHexString(posCapabilities));
+        }
+
+        @Override
+        public void setMetadata(int generationId, Bundle metadata) {
+            System.out.println("New metadata: id=" + generationId
+                    + " data=" + metadata);
+        }
+
+        @Override
+        public void setArtwork(int generationId, Bitmap artwork) {
+            System.out.println("New artwork: id=" + generationId
+                    + " art=" + artwork);
+        }
+
+        @Override
+        public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) {
+            System.out.println("New metadata+artwork: id=" + generationId
+                    + " data=" + metadata + " art=" + artwork);
+        }
+
+        void printUsageMessage() {
+            System.out.println("Monitoring remote control displays...  available commands:");
+            System.out.println("(q)uit: finish monitoring");
+        }
+
+        void run() throws RemoteException {
+            printUsageMessage();
+
+            mAudioService.registerRemoteControlDisplay(this, 0, 0);
+
+            try {
+                InputStreamReader converter = new InputStreamReader(System.in);
+                BufferedReader in = new BufferedReader(converter);
+                String line;
+
+                while ((line = in.readLine()) != null) {
+                    boolean addNewline = true;
+                    if (line.length() <= 0) {
+                        addNewline = false;
+                    } else if ("q".equals(line) || "quit".equals(line)) {
+                        break;
+                    } else {
+                        System.out.println("Invalid command: " + line);
+                    }
+
+                    synchronized (this) {
+                        if (addNewline) {
+                            System.out.println("");
+                        }
+                        printUsageMessage();
+                    }
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                mAudioService.unregisterRemoteControlDisplay(this);
+            }
+        }
+    }
+
+    private void runRemoteDisplay() throws Exception {
+        RemoteDisplayMonitor monitor = new RemoteDisplayMonitor();
+        monitor.run();
+    }
+}
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index 31eba96..815a0ac 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -26,21 +26,15 @@
 import android.util.AndroidException;
 import android.view.Display;
 import android.view.IWindowManager;
+import com.android.internal.os.BaseCommand;
 
+import java.io.PrintStream;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public class Wm {
+public class Wm extends BaseCommand {
 
     private IWindowManager mWm;
-    private String[] mArgs;
-    private int mNextArg;
-    private String mCurArgData;
-
-    // These are magic strings understood by the Eclipse plugin.
-    private static final String FATAL_ERROR_CODE = "Error type 1";
-    private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
-    private static final String NO_CLASS_ERROR_CODE = "Error type 3";
 
     /**
      * Command-line entry point.
@@ -48,23 +42,25 @@
      * @param args The command-line arguments
      */
     public static void main(String[] args) {
-        try {
-            (new Wm()).run(args);
-        } catch (IllegalArgumentException e) {
-            showUsage();
-            System.err.println("Error: " + e.getMessage());
-        } catch (Exception e) {
-            e.printStackTrace(System.err);
-            System.exit(1);
-        }
+        (new Wm()).run(args);
     }
 
-    private void run(String[] args) throws Exception {
-        if (args.length < 1) {
-            showUsage();
-            return;
-        }
+    public void onShowUsage(PrintStream out) {
+        out.println(
+                "usage: wm [subcommand] [options]\n" +
+                "       wm size [reset|WxH]\n" +
+                "       wm density [reset|DENSITY]\n" +
+                "       wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
+                "\n" +
+                "wm size: return or override display size.\n" +
+                "\n" +
+                "wm density: override display density.\n" +
+                "\n" +
+                "wm overscan: set overscan area for display.\n"
+                );
+    }
 
+    public void onRun() throws Exception {
         mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                         Context.WINDOW_SERVICE));
         if (mWm == null) {
@@ -72,9 +68,7 @@
             throw new AndroidException("Can't connect to window manager; is the system running?");
         }
 
-        mArgs = args;
-        String op = args[0];
-        mNextArg = 1;
+        String op = nextArgRequired();
 
         if (op.equals("size")) {
             runDisplaySize();
@@ -83,7 +77,8 @@
         } else if (op.equals("overscan")) {
             runDisplayOverscan();
         } else {
-            throw new IllegalArgumentException("Unknown command: " + op);
+            showError("Error: unknown command '" + op + "'");
+            return;
         }
     }
 
@@ -198,69 +193,4 @@
         } catch (RemoteException e) {
         }
     }
-
-    private String nextOption() {
-        if (mCurArgData != null) {
-            String prev = mArgs[mNextArg - 1];
-            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
-        }
-        if (mNextArg >= mArgs.length) {
-            return null;
-        }
-        String arg = mArgs[mNextArg];
-        if (!arg.startsWith("-")) {
-            return null;
-        }
-        mNextArg++;
-        if (arg.equals("--")) {
-            return null;
-        }
-        if (arg.length() > 1 && arg.charAt(1) != '-') {
-            if (arg.length() > 2) {
-                mCurArgData = arg.substring(2);
-                return arg.substring(0, 2);
-            } else {
-                mCurArgData = null;
-                return arg;
-            }
-        }
-        mCurArgData = null;
-        return arg;
-    }
-
-    private String nextArg() {
-        if (mCurArgData != null) {
-            String arg = mCurArgData;
-            mCurArgData = null;
-            return arg;
-        } else if (mNextArg < mArgs.length) {
-            return mArgs[mNextArg++];
-        } else {
-            return null;
-        }
-    }
-
-    private String nextArgRequired() {
-        String arg = nextArg();
-        if (arg == null) {
-            String prev = mArgs[mNextArg - 1];
-            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
-        }
-        return arg;
-    }
-
-    private static void showUsage() {
-        System.err.println(
-                "usage: wm [subcommand] [options]\n" +
-                "       wm size [reset|WxH]\n" +
-                "       wm density [reset|DENSITY]\n" +
-                "       wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
-                "\n" +
-                "wm size: return or override display size.\n" +
-                "\n" +
-                "wm density: override display density.\n" +
-                "\n" +
-                "wm overscan: set overscan area for display.\n"
-                );
-    }
 }
diff --git a/core/java/android/animation/RectEvaluator.java b/core/java/android/animation/RectEvaluator.java
index 10932bb..28d496b 100644
--- a/core/java/android/animation/RectEvaluator.java
+++ b/core/java/android/animation/RectEvaluator.java
@@ -18,7 +18,7 @@
 import android.graphics.Rect;
 
 /**
- * This evaluator can be used to perform type interpolation between <code>int</code> values.
+ * This evaluator can be used to perform type interpolation between <code>Rect</code> values.
  */
 public class RectEvaluator implements TypeEvaluator<Rect> {
 
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 3602fc4..c4ddf1f 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -695,6 +695,86 @@
     public boolean isTitleTruncated() { return false; }
 
     /**
+     * Set an alternate drawable to display next to the icon/logo/title
+     * when {@link #DISPLAY_HOME_AS_UP} is enabled. This can be useful if you are using
+     * this mode to display an alternate selection for up navigation, such as a sliding drawer.
+     *
+     * <p>If you pass <code>null</code> to this method, the default drawable from the theme
+     * will be used.</p>
+     *
+     * <p>If you implement alternate or intermediate behavior around Up, you should also
+     * call {@link #setHomeActionContentDescription(int) setHomeActionContentDescription()}
+     * to provide a correct description of the action for accessibility support.</p>
+     *
+     * @param indicator A drawable to use for the up indicator, or null to use the theme's default
+     *
+     * @see #setDisplayOptions(int, int)
+     * @see #setDisplayHomeAsUpEnabled(boolean)
+     * @see #setHomeActionContentDescription(int)
+     */
+    public void setHomeAsUpIndicator(Drawable indicator) { }
+
+    /**
+     * Set an alternate drawable to display next to the icon/logo/title
+     * when {@link #DISPLAY_HOME_AS_UP} is enabled. This can be useful if you are using
+     * this mode to display an alternate selection for up navigation, such as a sliding drawer.
+     *
+     * <p>If you pass <code>0</code> to this method, the default drawable from the theme
+     * will be used.</p>
+     *
+     * <p>If you implement alternate or intermediate behavior around Up, you should also
+     * call {@link #setHomeActionContentDescription(int) setHomeActionContentDescription()}
+     * to provide a correct description of the action for accessibility support.</p>
+     *
+     * @param resId Resource ID of a drawable to use for the up indicator, or null
+     *              to use the theme's default
+     *
+     * @see #setDisplayOptions(int, int)
+     * @see #setDisplayHomeAsUpEnabled(boolean)
+     * @see #setHomeActionContentDescription(int)
+     */
+    public void setHomeAsUpIndicator(int resId) { }
+
+    /**
+     * Set an alternate description for the Home/Up action, when enabled.
+     *
+     * <p>This description is commonly used for accessibility/screen readers when
+     * the Home action is enabled. (See {@link #setDisplayHomeAsUpEnabled(boolean)}.)
+     * Examples of this are, "Navigate Home" or "Navigate Up" depending on the
+     * {@link #DISPLAY_HOME_AS_UP} display option. If you have changed the home-as-up
+     * indicator using {@link #setHomeAsUpIndicator(int)} to indicate more specific
+     * functionality such as a sliding drawer, you should also set this to accurately
+     * describe the action.</p>
+     *
+     * <p>Setting this to <code>null</code> will use the system default description.</p>
+     *
+     * @param description New description for the Home action when enabled
+     * @see #setHomeAsUpIndicator(int)
+     * @see #setHomeAsUpIndicator(android.graphics.drawable.Drawable)
+     */
+    public void setHomeActionContentDescription(CharSequence description) { }
+
+    /**
+     * Set an alternate description for the Home/Up action, when enabled.
+     *
+     * <p>This description is commonly used for accessibility/screen readers when
+     * the Home action is enabled. (See {@link #setDisplayHomeAsUpEnabled(boolean)}.)
+     * Examples of this are, "Navigate Home" or "Navigate Up" depending on the
+     * {@link #DISPLAY_HOME_AS_UP} display option. If you have changed the home-as-up
+     * indicator using {@link #setHomeAsUpIndicator(int)} to indicate more specific
+     * functionality such as a sliding drawer, you should also set this to accurately
+     * describe the action.</p>
+     *
+     * <p>Setting this to <code>0</code> will use the system default description.</p>
+     *
+     * @param resId Resource ID of a string to use as the new description
+     *              for the Home action when enabled
+     * @see #setHomeAsUpIndicator(int)
+     * @see #setHomeAsUpIndicator(android.graphics.drawable.Drawable)
+     */
+    public void setHomeActionContentDescription(int resId) { }
+
+    /**
      * Listener interface for ActionBar navigation events.
      */
     public interface OnNavigationListener {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index aca4f9c..c99051b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1853,6 +1853,15 @@
             return true;
         }
 
+        case KILL_UID_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int uid = data.readInt();
+            String reason = data.readString();
+            killUid(uid, reason);
+            reply.writeNoException();
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -3335,6 +3344,7 @@
         data.writeString(reason);
         data.writeInt(secure ? 1 : 0);
         mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0);
+        reply.readException();
         boolean res = reply.readInt() != 0;
         data.recycle();
         reply.recycle();
@@ -4229,5 +4239,17 @@
         reply.recycle();
     }
 
+    public void killUid(int uid, String reason) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(uid);
+        data.writeString(reason);
+        mRemote.transact(KILL_UID_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ae0671b..68a2397 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -86,6 +86,7 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.renderscript.RenderScript;
+import android.security.AndroidKeyStoreProvider;
 
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
@@ -101,6 +102,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
+import java.security.Security;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -5068,6 +5070,8 @@
         // Set the reporter for event logging in libcore
         EventLogger.setReporter(new EventLoggingReporter());
 
+        Security.addProvider(new AndroidKeyStoreProvider());
+
         Process.setArgV0("<pre-initialized>");
 
         Looper.prepareMainLooper();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9bf8830..19d495b 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -371,9 +371,9 @@
                     return new DisplayManager(ctx.getOuterContext());
                 }});
 
-        registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
-                public Object createService(ContextImpl ctx) {
-                    return InputMethodManager.getInstance(ctx);
+        registerService(INPUT_METHOD_SERVICE, new StaticServiceFetcher() {
+                public Object createStaticService() {
+                    return InputMethodManager.getInstance();
                 }});
 
         registerService(TEXT_SERVICES_MANAGER_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index cf4c729..fa8839a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -373,6 +373,8 @@
 
     public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException;
 
+    public void killUid(int uid, String reason) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -632,4 +634,5 @@
     int GET_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;
     int REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162;
     int GET_LAUNCHED_FROM_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+163;
+    int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164;
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 3d9b2ae..92ec3ad 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -17,12 +17,12 @@
 
 package android.app;
 
-import android.app.INotificationListener;
 import android.app.ITransientNotification;
+import android.service.notification.StatusBarNotification;
 import android.app.Notification;
+import android.content.ComponentName;
 import android.content.Intent;
-
-import com.android.internal.statusbar.StatusBarNotification;
+import android.service.notification.INotificationListener;
 
 /** {@hide} */
 interface INotificationManager
@@ -41,7 +41,9 @@
     StatusBarNotification[] getActiveNotifications(String callingPkg);
     StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
 
-    void registerListener(in INotificationListener listener, String pkg, int userid);
+    void registerListener(in INotificationListener listener, in ComponentName component, int userid);
     void unregisterListener(in INotificationListener listener, int userid);
-}
 
+    void clearNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
+    void clearAllNotificationsFromListener(in INotificationListener token);
+}
\ No newline at end of file
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 51867bc..7d8a36e 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -1,7 +1,20 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package android.app;
 
-import com.android.internal.view.IInputMethodSession;
-
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -25,7 +38,6 @@
 import android.view.inputmethod.InputMethodManager;
 
 import java.io.File;
-import java.lang.ref.WeakReference;
 
 /**
  * Convenience for implementing an activity that will be implemented
@@ -65,7 +77,6 @@
 
     private NativeContentView mNativeContentView;
     private InputMethodManager mIMM;
-    private InputMethodCallback mInputMethodCallback;
 
     private int mNativeHandle;
     
@@ -117,22 +128,6 @@
             super(context, attrs);
         }
     }
-    
-    static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
-        WeakReference<NativeActivity> mNa;
-
-        InputMethodCallback(NativeActivity na) {
-            mNa = new WeakReference<NativeActivity>(na);
-        }
-
-        @Override
-        public void finishedEvent(int seq, boolean handled) {
-            NativeActivity na = mNa.get();
-            if (na != null) {
-                na.finishPreDispatchKeyEventNative(na.mNativeHandle, seq, handled);
-            }
-        }
-    }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -141,7 +136,6 @@
         ActivityInfo ai;
         
         mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
-        mInputMethodCallback = new InputMethodCallback(this);
 
         getWindow().takeSurface(this);
         getWindow().takeInputQueue(this);
@@ -353,7 +347,8 @@
     }
     
     void preDispatchKeyEvent(KeyEvent event, int seq) {
-        mIMM.dispatchInputEvent(this, seq, event, mInputMethodCallback);
+        // FIXME: Input dispatch should be redirected back through ViewRootImpl again.
+        finishPreDispatchKeyEventNative(mNativeHandle, seq, false);
     }
 
     void setWindowFlags(int flags, int mask) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ebca041..a7543a8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1603,7 +1603,7 @@
             n.defaults = mDefaults;
             n.flags = mFlags;
             n.bigContentView = makeBigContentView();
-            if (mLedOnMs != 0 && mLedOffMs != 0) {
+            if (mLedOnMs != 0 || mLedOffMs != 0) {
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
             if ((mDefaults & DEFAULT_LIGHTS) != 0) {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 9c0064e..3342068 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -709,7 +709,7 @@
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession().setWallpaperPosition(
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -747,7 +747,7 @@
             int x, int y, int z, Bundle extras) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+            WindowManagerGlobal.getWindowSession().sendWallpaperCommand(
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -767,7 +767,7 @@
      */
     public void clearWallpaperOffsets(IBinder windowToken) {
         try {
-            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession().setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
             // Ignore.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ef9b0bf..03e241a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -256,6 +256,12 @@
      * Return the Looper for the main thread of the current process.  This is
      * the thread used to dispatch calls to application components (activities,
      * services, etc).
+     * <p>
+     * By definition, this method returns the same result as would be obtained
+     * by calling {@link Looper#getMainLooper() Looper.getMainLooper()}.
+     * </p>
+     *
+     * @return The main looper.
      */
     public abstract Looper getMainLooper();
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 49cea3a..384aed8 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1036,25 +1036,10 @@
                     return null;
                 }
             } else if (tagName.equals("uses-permission")) {
-                sa = res.obtainAttributes(attrs,
-                        com.android.internal.R.styleable.AndroidManifestUsesPermission);
-
-                // Note: don't allow this value to be a reference to a resource
-                // that may change.
-                String name = sa.getNonResourceString(
-                        com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
-                boolean required = sa.getBoolean(
-                        com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
-
-                sa.recycle();
-
-                if (name != null && !pkg.requestedPermissions.contains(name)) {
-                    pkg.requestedPermissions.add(name.intern());
-                    pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE);
+                if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
+                    return null;
                 }
 
-                XmlUtils.skipCurrentTag(parser);
-
             } else if (tagName.equals("uses-configuration")) {
                 ConfigurationInfo cPref = new ConfigurationInfo();
                 sa = res.obtainAttributes(attrs,
@@ -1412,6 +1397,39 @@
         return pkg;
     }
 
+    private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
+                                        AttributeSet attrs, String[] outError)
+            throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(attrs,
+                com.android.internal.R.styleable.AndroidManifestUsesPermission);
+
+        // Note: don't allow this value to be a reference to a resource
+        // that may change.
+        String name = sa.getNonResourceString(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
+        boolean required = sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
+
+        sa.recycle();
+
+        if (name != null) {
+            int index = pkg.requestedPermissions.indexOf(name);
+            if (index == -1) {
+                pkg.requestedPermissions.add(name.intern());
+                pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE);
+            } else {
+                if (pkg.requestedPermissionsRequired.get(index) != required) {
+                    outError[0] = "conflicting <uses-permission> entries";
+                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                    return false;
+                }
+            }
+        }
+
+        XmlUtils.skipCurrentTag(parser);
+        return true;
+    }
+
     private static String buildClassName(String pkg, CharSequence clsSeq,
             String[] outError) {
         if (clsSeq == null || clsSeq.length() <= 0) {
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 16b4835..e9e7551 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -152,7 +152,15 @@
      * not return until the current process is exiting.
      */
     public static final native void joinThreadPool();
-    
+
+    /**
+     * Returns true if the specified interface is a proxy.
+     * @hide
+     */
+    public static final boolean isProxy(IInterface iface) {
+        return iface.asBinder() != iface;
+    }
+
     /**
      * Default constructor initializes the object.
      */
diff --git a/core/java/android/os/LatencyTimer.java b/core/java/android/os/LatencyTimer.java
deleted file mode 100644
index ed2f0f9..0000000
--- a/core/java/android/os/LatencyTimer.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * A class to help with measuring latency in your code.
- * 
- * Suggested usage:
- * 1) Instanciate a LatencyTimer as a class field.
- *      private [static] LatencyTimer mLt = new LatencyTimer(100, 1000);
- * 2) At various points in the code call sample with a string and the time delta to some fixed time.
- *    The string should be unique at each point of the code you are measuring.
- *      mLt.sample("before processing event", System.nanoTime() - event.getEventTimeNano());
- *      processEvent(event);
- *      mLt.sample("after processing event ", System.nanoTime() - event.getEventTimeNano());
- *
- * @hide
- */
-public final class LatencyTimer
-{
-    final String TAG = "LatencyTimer";
-    final int mSampleSize;
-    final int mScaleFactor;
-    volatile HashMap<String, long[]> store = new HashMap<String, long[]>();
-
-    /**
-    * Creates a LatencyTimer object
-    * @param sampleSize number of samples to collect before printing out the average
-    * @param scaleFactor divisor used to make each sample smaller to prevent overflow when
-    *        (sampleSize * average sample value)/scaleFactor > Long.MAX_VALUE
-    */
-    public LatencyTimer(int sampleSize, int scaleFactor) {
-        if (scaleFactor == 0) {
-            scaleFactor = 1;
-        }
-        mScaleFactor = scaleFactor;
-        mSampleSize = sampleSize;
-    }
-
-    /**
-     * Add a sample delay for averaging.
-     * @param tag string used for printing out the result. This should be unique at each point of
-     *  this called.
-     * @param delta time difference from an unique point of reference for a particular iteration
-     */
-    public void sample(String tag, long delta) {
-        long[] array = getArray(tag);
-
-        // array[mSampleSize] holds the number of used entries
-        final int index = (int) array[mSampleSize]++;
-        array[index] = delta;
-        if (array[mSampleSize] == mSampleSize) {
-            long totalDelta = 0;
-            for (long d : array) {
-                totalDelta += d/mScaleFactor;
-            }
-            array[mSampleSize] = 0;
-            Log.i(TAG, tag + " average = " + totalDelta / mSampleSize);
-        }
-    }
-
-    private long[] getArray(String tag) {
-        long[] data = store.get(tag);
-        if (data == null) {
-            synchronized(store) {
-                data = store.get(tag);
-                if (data == null) {
-                    data = new long[mSampleSize + 1];
-                    store.put(tag, data);
-                    data[mSampleSize] = 0;
-                }
-            }
-        }
-        return data;
-    }
-}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 38f4d5e..363a1bf 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -192,6 +192,14 @@
     }
 
     /**
+     * Returns true if the current thread is this looper's thread.
+     * @hide
+     */
+    public boolean isCurrentThread() {
+        return Thread.currentThread() == mThread;
+    }
+
+    /**
      * Quits the looper.
      *
      * Causes the {@link #loop} method to terminate as soon as possible.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 66083c8..367d576 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3796,50 +3796,11 @@
      * Columns in the Data_Usage_Stat table
      */
     protected interface DataUsageStatColumns {
-        /** What the referenced {@link Data} was used for.
-         * @see DataUsageStatColumns#USAGE_TYPE_CALL
-         * @see DataUsageStatColumns#USAGE_TYPE_LONG_TEXT
-         * @see DataUsageStatColumns#USAGE_TYPE_SHORT_TEXT
-         */
-        public static final String USAGE_TYPE = "usage_type";
-
         /** The last time (in milliseconds) this {@link Data} was used. */
         public static final String LAST_TIME_USED = "last_time_used";
 
-        /** The number of times the referenced {@link Data} has been used for the purpose described
-         * in {@link DataUsageStatColumns#USAGE_TYPE}.
-         */
+        /** The number of times the referenced {@link Data} has been used. */
         public static final String TIMES_USED = "times_used";
-
-        /**
-         * Integer value for USAGE_TYPE.
-         * This type of usage refers to voice interaction, which includes phone calls, voice chat,
-         * and video chat.
-         *
-         * @see DataUsageFeedback#USAGE_TYPE
-         * @see DataUsageStatColumns#USAGE_TYPE
-         */
-        public static final int USAGE_TYPE_CALL = 0;
-
-        /**
-         * Integer value for USAGE_TYPE.
-         * This type of usage refers to text interaction involving longer messages, which includes
-         * email.
-         *
-         * @see DataUsageFeedback#USAGE_TYPE
-         * @see DataUsageStatColumns#USAGE_TYPE
-         */
-        public static final int USAGE_TYPE_LONG_TEXT = 1;
-
-        /**
-         * Integer value for USAGE_TYPE.
-         * This type of usage for text interaction involving shorter messages, which includes SMS
-         * and text chat with email addresses.
-         *
-         * @see DataUsageFeedback#USAGE_TYPE
-         * @see DataUsageStatColumns#USAGE_TYPE
-         */
-        public static final int USAGE_TYPE_SHORT_TEXT = 2;
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 03ee9eb..88ee414 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -655,6 +655,22 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
 
+    /**
+     * Activity Action: Show Notification listener settings.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @see android.service.notification.NotificationListenerService
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS
+            = "android.settings.NOTIFICATION_LISTENER_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -5398,6 +5414,20 @@
         public static final String CERT_PIN_UPDATE_METADATA_URL = "cert_pin_metadata_url";
 
         /**
+         * URL for intent firewall updates
+         * @hide
+         */
+        public static final String INTENT_FIREWALL_UPDATE_CONTENT_URL =
+                "intent_firewall_content_url";
+
+        /**
+         * URL for intent firewall update metadata
+         * @hide
+         */
+        public static final String INTENT_FIREWALL_UPDATE_METADATA_URL =
+                "intent_firewall_metadata_url";
+
+        /**
          * SELinux enforcement status. If 0, permissive; if 1, enforcing.
          * @hide
          */
diff --git a/core/java/android/app/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
similarity index 89%
rename from core/java/android/app/INotificationListener.aidl
rename to core/java/android/service/notification/INotificationListener.aidl
index f010a2a..425fdc1 100644
--- a/core/java/android/app/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.app;
+package android.service.notification;
 
-import com.android.internal.statusbar.StatusBarNotification;
+import android.service.notification.StatusBarNotification;
 
 /** @hide */
 oneway interface INotificationListener
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
new file mode 100644
index 0000000..86bab2a
--- /dev/null
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.annotation.SdkConstant;
+import android.app.INotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+public abstract class NotificationListenerService extends Service {
+    // TAG = "NotificationListenerService[MySubclass]"
+    private final String TAG = NotificationListenerService.class.getSimpleName()
+            + "[" + getClass().getSimpleName() + "]";
+
+    private INotificationListenerWrapper mWrapper = null;
+
+    private INotificationManager mNoMan;
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.notification.NotificationListenerService";
+
+    /**
+     * Implement this method to learn about new notifications as they are posted by apps.
+     *
+     * @param sbn A data structure encapsulating the original {@link android.app.Notification}
+     *            object as well as its identifying information (tag and id) and source
+     *            (package name).
+     */
+    public abstract void onNotificationPosted(StatusBarNotification sbn);
+
+    /**
+     * Implement this method to learn when notifications are removed.
+     * <P>
+     * This might occur because the user has dismissed the notification using system UI (or another
+     * notification listener) or because the app has withdrawn the notification.
+     *
+     * @param sbn A data structure encapsulating the original {@link android.app.Notification}
+     *            object as well as its identifying information (tag and id) and source
+     *            (package name).
+     */
+    public abstract void onNotificationRemoved(StatusBarNotification sbn);
+
+    private final INotificationManager getNotificationInterface() {
+        if (mNoMan == null) {
+            mNoMan = INotificationManager.Stub.asInterface(
+                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        }
+        return mNoMan;
+    }
+
+    /**
+     * Inform the notification manager about dismissal of a single notification.
+     * <p>
+     * Use this if your listener has a user interface that allows the user to dismiss individual
+     * notifications, similar to the behavior of Android's status bar and notification panel.
+     * It should be called after the user dismisses a single notification using your UI;
+     * upon being informed, the notification manager will actually remove the notification
+     * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
+     * <P>
+     * <b>Note:</b> If your listener allows the user to fire a notification's
+     * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
+     * this method at that time <i>if</i> the Notification in question has the
+     * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
+     *
+     * @param pkg Package of the notifying app.
+     * @param tag Tag of the notification as specified by the notifying app in
+     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
+     * @param id  ID of the notification as specified by the notifying app in
+     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
+     */
+    public final void clearNotification(String pkg, String tag, int id) {
+        try {
+            getNotificationInterface().clearNotificationFromListener(mWrapper, pkg, tag, id);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
+     * Inform the notification manager about dismissal of all notifications.
+     * <p>
+     * Use this if your listener has a user interface that allows the user to dismiss all
+     * notifications, similar to the behavior of Android's status bar and notification panel.
+     * It should be called after the user invokes the "dismiss all" function of your UI;
+     * upon being informed, the notification manager will actually remove all active notifications
+     * and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks.
+     *
+     * {@see #clearNotification(String, String, int)}
+     */
+    public final void clearAllNotifications() {
+        try {
+            getNotificationInterface().clearAllNotificationsFromListener(mWrapper);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (mWrapper == null) {
+            mWrapper = new INotificationListenerWrapper();
+        }
+        return mWrapper;
+    }
+
+    private class INotificationListenerWrapper extends INotificationListener.Stub {
+        @Override
+        public void onNotificationPosted(StatusBarNotification sbn) {
+            NotificationListenerService.this.onNotificationPosted(sbn);
+        }
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn) {
+            NotificationListenerService.this.onNotificationRemoved(sbn);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/statusbar/StatusBarNotification.aidl b/core/java/android/service/notification/StatusBarNotification.aidl
similarity index 93%
rename from core/java/com/android/internal/statusbar/StatusBarNotification.aidl
rename to core/java/android/service/notification/StatusBarNotification.aidl
index bd9e89c..ba81972 100644
--- a/core/java/com/android/internal/statusbar/StatusBarNotification.aidl
+++ b/core/java/android/service/notification/StatusBarNotification.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.statusbar;
+package android.service.notification;
 
 parcelable StatusBarNotification;
 
diff --git a/core/java/com/android/internal/statusbar/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
similarity index 80%
rename from core/java/com/android/internal/statusbar/StatusBarNotification.java
rename to core/java/android/service/notification/StatusBarNotification.java
index 23e87fc..ef5f8c4 100644
--- a/core/java/com/android/internal/statusbar/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.statusbar;
+package android.service.notification;
 
 import android.app.Notification;
 import android.os.Parcel;
@@ -23,34 +23,54 @@
 
 /**
  * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including
- * the IStatusBar (in System UI).
+ * the status bar and any {@link android.service.notification.NotificationListenerService}s.
  */
 public class StatusBarNotification implements Parcelable {
+    /** The package of the app that posted the notification. */
     public final String pkg;
-    public final String basePkg;
+    /** The id supplied to {@link android.app.NotificationManager#notify}. */
     public final int id;
+    /** The tag supplied to {@link android.app.NotificationManager#notify}, or null if no tag
+     * was specified. */
     public final String tag;
+
+    /** The notifying app's calling uid. @hide */
     public final int uid;
+    /** The notifying app's base package. @hide */
+    public final String basePkg;
+    /** @hide */
     public final int initialPid;
     // TODO: make this field private and move callers to an accessor that
     // ensures sourceUser is applied.
+
+    /** The {@link android.app.Notification} supplied to
+     * {@link android.app.NotificationManager#notify}. */
     public final Notification notification;
-    public final int score;
+    /** The {@link android.os.UserHandle} for whom this notification is intended. */
     public final UserHandle user;
+    /** The time (in {@link System#currentTimeMillis} time) the notification was posted,
+     * which may be different than {@link android.app.Notification#when}.
+     */
     public final long postTime;
 
-    /** This is temporarily needed for the JB MR1 PDK. */
+    /** @hide */
+    public final int score;
+
+    /** This is temporarily needed for the JB MR1 PDK.
+     * @hide */
     @Deprecated
     public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
             Notification notification) {
         this(pkg, id, tag, uid, initialPid, score, notification, UserHandle.OWNER);
     }
 
+    /** @hide */
     public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
             Notification notification, UserHandle user) {
         this(pkg, null, id, tag, uid, initialPid, score, notification, user);
     }
 
+    /** @hide */
     public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user) {
         this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
@@ -147,10 +167,17 @@
                 this.score, this.notification);
     }
 
+    /** Convenience method to check the notification's flags for
+     * {@link Notification#FLAG_ONGOING_EVENT}.
+     */
     public boolean isOngoing() {
         return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
     }
 
+    /** Convenience method to check the notification's flags for
+     * either {@link Notification#FLAG_ONGOING_EVENT} or
+     * {@link Notification#FLAG_NO_CLEAR}.
+     */
     public boolean isClearable() {
         return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0)
                 && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 71d8fb6..5db8168 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -762,7 +762,7 @@
             mWindowToken = wrapper.mWindowToken;
             mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
-            mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
+            mSession = WindowManagerGlobal.getWindowSession();
             
             mWindow.setSession(mSession);
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 7918823..8055077 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -451,10 +451,8 @@
      * @param attachInfo AttachInfo tied to the specified view.
      * @param callbacks Callbacks invoked when drawing happens.
      * @param dirty The dirty rectangle to update, can be null.
-     * 
-     * @return true if the dirty rect was ignored, false otherwise
      */
-    abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
             Rect dirty);
 
     /**
@@ -992,11 +990,7 @@
                             mCanvas = createCanvas();
                             mCanvas.setName(mName);
                         }
-                        if (mCanvas != null) {
-                            setEnabled(true);
-                        } else {
-                            Log.w(LOG_TAG, "Hardware accelerated Canvas could not be created");
-                        }
+                        setEnabled(true);
                     }
 
                     return mCanvas != null;
@@ -1340,7 +1334,7 @@
         }
 
         @Override
-        boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+        void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
                 Rect dirty) {
             if (canDraw()) {
                 if (!hasDirtyRegions()) {
@@ -1401,11 +1395,8 @@
                     }
 
                     attachInfo.mIgnoreDirtyState = false;
-                    return dirty == null;
                 }
             }
-
-            return false;
         }
 
         private DisplayList buildDisplayList(View view, HardwareCanvas canvas) {
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index a797176..40ee1ad 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -54,6 +54,7 @@
     private native void nativeTransferTo(InputChannel other);
     private native void nativeReadFromParcel(Parcel parcel);
     private native void nativeWriteToParcel(Parcel parcel);
+    private native void nativeDup(InputChannel target);
     
     private native String nativeGetName();
 
@@ -64,7 +65,7 @@
      */
     public InputChannel() {
     }
-    
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -125,6 +126,15 @@
         nativeTransferTo(outParameter);
     }
 
+    /**
+     * Duplicates the input channel.
+     */
+    public InputChannel dup() {
+        InputChannel target = new InputChannel();
+        nativeDup(target);
+        return target;
+    }
+
     @Override
     public int describeContents() {
         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index dd523d2..2595ee5 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -371,8 +371,8 @@
             if (axis < 0) {
                 break;
             }
-            addMotionRange(axis, in.readInt(),
-                    in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
+            addMotionRange(axis, in.readInt(), in.readFloat(), in.readFloat(), in.readFloat(),
+                    in.readFloat(), in.readFloat());
         }
     }
 
@@ -584,8 +584,8 @@
 
     // Called from native code.
     private void addMotionRange(int axis, int source,
-            float min, float max, float flat, float fuzz) {
-        mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
+            float min, float max, float flat, float fuzz, float resolution) {
+        mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz, resolution));
     }
 
     /**
@@ -625,14 +625,17 @@
         private float mMax;
         private float mFlat;
         private float mFuzz;
+        private float mResolution;
 
-        private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) {
+        private MotionRange(int axis, int source, float min, float max, float flat, float fuzz,
+                float resolution) {
             mAxis = axis;
             mSource = source;
             mMin = min;
             mMax = max;
             mFlat = flat;
             mFuzz = fuzz;
+            mResolution = resolution;
         }
 
         /**
@@ -711,6 +714,14 @@
         public float getFuzz() {
             return mFuzz;
         }
+
+        /**
+         * Gets the resolution for input device measurements with respect to this axis.
+         * @return The resolution in units per millimeter, or units per radian for rotational axes.
+         */
+        public float getResolution() {
+            return mResolution;
+        }
     }
 
     @Override
@@ -734,6 +745,7 @@
             out.writeFloat(range.mMax);
             out.writeFloat(range.mFlat);
             out.writeFloat(range.mFuzz);
+            out.writeFloat(range.mResolution);
         }
         out.writeInt(-1);
     }
@@ -788,6 +800,7 @@
             description.append(" max=").append(range.mMax);
             description.append(" flat=").append(range.mFlat);
             description.append(" fuzz=").append(range.mFuzz);
+            description.append(" resolution=").append(range.mResolution);
             description.append("\n");
         }
         return description.toString();
diff --git a/core/java/android/view/Overlay.java b/core/java/android/view/Overlay.java
deleted file mode 100644
index 6630752..0000000
--- a/core/java/android/view/Overlay.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.view;
-
-import android.graphics.drawable.Drawable;
-
-/**
- * An overlay is an extra layer that sits on top of a View (the "host view")
- * which is drawn after all other content in that view (including children,
- * if the view is a ViewGroup). Interaction with the overlay layer is done in
- * terms of adding/removing views and drawables.
- *
- * @see android.view.View#getOverlay()
- */
-public interface Overlay {
-
-    /**
-     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
-     * the host view. Any drawable added to the overlay should be removed when it is no longer
-     * needed or no longer visible.
-     *
-     * @param drawable The Drawable to be added to the overlay. This drawable will be
-     * drawn when the view redraws its overlay.
-     * @see #remove(android.graphics.drawable.Drawable)
-     * @see #add(View)
-     */
-    void add(Drawable drawable);
-
-    /**
-     * Removes the specified Drawable from the overlay.
-     *
-     * @param drawable The Drawable to be removed from the overlay.
-     * @see #add(android.graphics.drawable.Drawable)
-     */
-    void remove(Drawable drawable);
-
-    /**
-     * Adds a View to the overlay. The bounds of the added view should be
-     * relative to the host view. Any view added to the overlay should be
-     * removed when it is no longer needed or no longer visible.
-     *
-     * <p>If the view has a parent, the view will be removed from that parent
-     * before being added to the overlay. Also, the view will be repositioned
-     * such that it is in the same relative location inside the activity. For
-     * example, if the view's current parent lies 100 pixels to the right
-     * and 200 pixels down from the origin of the overlay's
-     * host view, then the view will be offset by (100, 200).</p>
-     *
-     * @param view The View to be added to the overlay. The added view will be
-     * drawn when the overlay is drawn.
-     * @see #remove(View)
-     * @see #add(android.graphics.drawable.Drawable)
-     */
-    void add(View view);
-
-    /**
-     * Removes the specified View from the overlay.
-     *
-     * @param view The View to be removed from the overlay.
-     * @see #add(View)
-     */
-    void remove(View view);
-
-    /**
-     * Removes all views and drawables from the overlay.
-     */
-    void clear();
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3b06da7..7c82f7e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12107,7 +12107,7 @@
         //System.out.println("Attached! " + this);
         mAttachInfo = info;
         if (mOverlay != null) {
-            mOverlay.dispatchAttachedToWindow(info, visibility);
+            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
         }
         mWindowAttachCount++;
         // We will need to evaluate the drawable state at least once.
@@ -12178,7 +12178,7 @@
 
         mAttachInfo = null;
         if (mOverlay != null) {
-            mOverlay.dispatchDetachedFromWindow();
+            mOverlay.getOverlayView().dispatchDetachedFromWindow();
         }
     }
 
@@ -12831,7 +12831,7 @@
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         dispatchDraw(canvas);
                         if (mOverlay != null && !mOverlay.isEmpty()) {
-                            mOverlay.draw(canvas);
+                            mOverlay.getOverlayView().draw(canvas);
                         }
                     } else {
                         draw(canvas);
@@ -13147,7 +13147,7 @@
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchDraw(canvas);
                 if (mOverlay != null && !mOverlay.isEmpty()) {
-                    mOverlay.draw(canvas);
+                    mOverlay.getOverlayView().draw(canvas);
                 }
             } else {
                 draw(canvas);
@@ -13905,7 +13905,7 @@
             onDrawScrollBars(canvas);
 
             if (mOverlay != null && !mOverlay.isEmpty()) {
-                mOverlay.dispatchDraw(canvas);
+                mOverlay.getOverlayView().dispatchDraw(canvas);
             }
 
             // we're done...
@@ -14049,34 +14049,28 @@
         onDrawScrollBars(canvas);
 
         if (mOverlay != null && !mOverlay.isEmpty()) {
-            mOverlay.dispatchDraw(canvas);
+            mOverlay.getOverlayView().dispatchDraw(canvas);
         }
     }
 
     /**
-     * Called by the addToOverlay() methods to create, attach, and size the overlay as necessary
+     * Returns the overlay for this view, creating it if it does not yet exist.
+     * Adding drawables to the overlay will cause them to be displayed whenever
+     * the view itself is redrawn. Objects in the overlay should be actively
+     * managed: remove them when they should not be displayed anymore. The
+     * overlay will always have the same size as its host view.
+     *
+     * <p>Note: Overlays do not currently work correctly with {@link
+     * SurfaceView} or {@link TextureView}; contents in overlays for these
+     * types of views may not display correctly.</p>
+     *
+     * @return The ViewOverlay object for this view.
+     * @see ViewOverlay
      */
-    private void setupOverlay() {
+    public ViewOverlay getOverlay() {
         if (mOverlay == null) {
             mOverlay = new ViewOverlay(mContext, this);
-            mOverlay.mAttachInfo = mAttachInfo;
-            mOverlay.setRight(mRight);
-            mOverlay.setBottom(mBottom);
         }
-    }
-
-    /**
-     * Returns the overlay for this view, creating it if it does not yet exist. Adding drawables
-     * and/or views to the overlay will cause them to be displayed whenever the view itself is
-     * redrawn. Objects in the overlay should be actively managed: remove them when they should
-     * not be displayed anymore and invalidate this view appropriately when overlay drawables
-     * change. The overlay will always have the same size as its host view.
-     *
-     * @return The Overlay object for this view.
-     * @see Overlay
-     */
-    public Overlay getOverlay() {
-        setupOverlay();
         return mOverlay;
     }
 
@@ -14360,8 +14354,8 @@
     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
         if (mOverlay != null) {
-            mOverlay.setRight(mRight);
-            mOverlay.setBottom(mBottom);
+            mOverlay.getOverlayView().setRight(newWidth);
+            mOverlay.getOverlayView().setBottom(newHeight);
         }
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f615e1bc..311d1d0 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1876,34 +1876,10 @@
                     // have become out of sync.
                     removePointersFromTouchTargets(idBitsToAssign);
 
-                    final float x = ev.getX(actionIndex);
-                    final float y = ev.getY(actionIndex);
-
-                    if (mOverlay != null) {
-                        ViewOverlay overlay = (ViewOverlay) mOverlay;
-                        // Check to see whether the overlay can handle the event
-                        final View child = mOverlay;
-                        if (canViewReceivePointerEvents(child) &&
-                                isTransformedTouchPointInView(x, y, child, null)) {
-                            newTouchTarget = getTouchTarget(child);
-                            if (newTouchTarget != null) {
-                                newTouchTarget.pointerIdBits |= idBitsToAssign;
-                            } else {
-                                resetCancelNextUpFlag(child);
-                                if (dispatchTransformedTouchEvent(ev, false, child,
-                                        idBitsToAssign)) {
-                                    mLastTouchDownTime = ev.getDownTime();
-                                    mLastTouchDownX = ev.getX();
-                                    mLastTouchDownY = ev.getY();
-                                    newTouchTarget = addTouchTarget(child, idBitsToAssign);
-                                    alreadyDispatchedToNewTouchTarget = true;
-                                }
-                            }
-                        }
-                    }
-
                     final int childrenCount = mChildrenCount;
                     if (newTouchTarget == null && childrenCount != 0) {
+                        final float x = ev.getX(actionIndex);
+                        final float y = ev.getY(actionIndex);
                         // Find a child that can receive the event.
                         // Scan children from front to back.
                         final View[] children = mChildren;
@@ -2991,6 +2967,30 @@
     }
 
     /**
+     * Returns the ViewGroupOverlay for this view group, creating it if it does
+     * not yet exist. In addition to {@link ViewOverlay}'s support for drawables,
+     * {@link ViewGroupOverlay} allows views to be added to the overlay. These
+     * views, like overlay drawables, are visual-only; they do not receive input
+     * events and should not be used as anything other than a temporary
+     * representation of a view in a parent container, such as might be used
+     * by an animation effect.
+     *
+     * <p>Note: Overlays do not currently work correctly with {@link
+     * SurfaceView} or {@link TextureView}; contents in overlays for these
+     * types of views may not display correctly.</p>
+     *
+     * @return The ViewGroupOverlay object for this view.
+     * @see ViewGroupOverlay
+     */
+    @Override
+    public ViewGroupOverlay getOverlay() {
+        if (mOverlay == null) {
+            mOverlay = new ViewGroupOverlay(mContext, this);
+        }
+        return (ViewGroupOverlay) mOverlay;
+    }
+
+    /**
      * Returns the index of the child to draw for this iteration. Override this
      * if you want to change the drawing order of children. By default, it
      * returns i.
@@ -3055,11 +3055,12 @@
             }
         }
         if (mOverlay != null) {
-            mOverlay.mRecreateDisplayList = (mOverlay.mPrivateFlags & PFLAG_INVALIDATED)
+            View overlayView = mOverlay.getOverlayView();
+            overlayView.mRecreateDisplayList = (overlayView.mPrivateFlags & PFLAG_INVALIDATED)
                     == PFLAG_INVALIDATED;
-            mOverlay.mPrivateFlags &= ~PFLAG_INVALIDATED;
-            mOverlay.getDisplayList();
-            mOverlay.mRecreateDisplayList = false;
+            overlayView.mPrivateFlags &= ~PFLAG_INVALIDATED;
+            overlayView.getDisplayList();
+            overlayView.mRecreateDisplayList = false;
         }
     }
 
diff --git a/core/java/android/view/ViewGroupOverlay.java b/core/java/android/view/ViewGroupOverlay.java
new file mode 100644
index 0000000..c1b24f2
--- /dev/null
+++ b/core/java/android/view/ViewGroupOverlay.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A group overlay is an extra layer that sits on top of a ViewGroup
+ * (the "host view") which is drawn after all other content in that view
+ * (including the view group's children). Interaction with the overlay
+ * layer is done by adding and removing views and drawables.
+ *
+ * <p>ViewGroupOverlay is a subclass of {@link ViewOverlay}, adding the ability to
+ * manage views for overlays on ViewGroups, in addition to the drawable
+ * support in ViewOverlay.</p>
+ *
+ * @see ViewGroup#getOverlay()
+ */
+public class ViewGroupOverlay extends ViewOverlay {
+
+    ViewGroupOverlay(Context context, View hostView) {
+        super(context, hostView);
+    }
+
+    /**
+     * Adds a View to the overlay. The bounds of the added view should be
+     * relative to the host view. Any view added to the overlay should be
+     * removed when it is no longer needed or no longer visible.
+     *
+     * <p>Views in the overlay are visual-only; they do not receive input
+     * events and do not participate in focus traversal. Overlay views
+     * are intended to be transient, such as might be needed by a temporary
+     * animation effect.</p>
+     *
+     * <p>If the view has a parent, the view will be removed from that parent
+     * before being added to the overlay. Also, the view will be repositioned
+     * such that it is in the same relative location inside the activity. For
+     * example, if the view's current parent lies 100 pixels to the right
+     * and 200 pixels down from the origin of the overlay's
+     * host view, then the view will be offset by (100, 200).</p>
+     *
+     * @param view The View to be added to the overlay. The added view will be
+     * drawn when the overlay is drawn.
+     * @see #remove(View)
+     * @see ViewOverlay#add(Drawable)
+     */
+    public void add(View view) {
+        mOverlayViewGroup.add(view);
+    }
+
+    /**
+     * Removes the specified View from the overlay.
+     *
+     * @param view The View to be removed from the overlay.
+     * @see #add(View)
+     * @see ViewOverlay#remove(Drawable)
+     */
+    public void remove(View view) {
+        mOverlayViewGroup.remove(view);
+    }
+}
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 8b18d53..78e2597 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -23,215 +23,286 @@
 import java.util.ArrayList;
 
 /**
- * ViewOverlay is a container that View uses to host all objects (views and
- * drawables) that are added to its "overlay", gotten through
- * {@link View#getOverlay()}. Views and drawables are added to the overlay
- * via the add/remove methods in this class. These views and drawables are
- * drawn whenever the view itself is drawn; first the view draws its own
- * content (and children, if it is a ViewGroup), then it draws its overlay
- * (if it has one).
+ * An overlay is an extra layer that sits on top of a View (the "host view")
+ * which is drawn after all other content in that view (including children,
+ * if the view is a ViewGroup). Interaction with the overlay layer is done
+ * by adding and removing drawables.
  *
- * Besides managing and drawing the list of drawables, this class serves
- * two purposes:
- * (1) it noops layout calls because children are absolutely positioned and
- * (2) it forwards all invalidation calls to its host view. The invalidation
- * redirect is necessary because the overlay is not a child of the host view
- * and invalidation cannot therefore follow the normal path up through the
- * parent hierarchy.
+ * <p>An overlay requested from a ViewGroup is of type {@link ViewGroupOverlay},
+ * which also supports adding and removing views.</p>
  *
- * @hide
+ * @see View#getOverlay() View.getOverlay()
+ * @see ViewGroup#getOverlay() ViewGroup.getOverlay()
+ * @see ViewGroupOverlay
  */
-class ViewOverlay extends ViewGroup implements Overlay {
+public class ViewOverlay {
 
     /**
-     * The View for which this is an overlay. Invalidations of the overlay are redirected to
-     * this host view.
+     * The actual container for the drawables (and views, if it's a ViewGroupOverlay).
+     * All of the management and rendering details for the overlay are handled in
+     * OverlayViewGroup.
      */
-    View mHostView;
+    OverlayViewGroup mOverlayViewGroup;
 
-    /**
-     * The set of drawables to draw when the overlay is rendered.
-     */
-    ArrayList<Drawable> mDrawables = null;
-
-    ViewOverlay(Context context, View host) {
-        super(context);
-        mHostView = host;
-        mParent = mHostView.getParent();
+    ViewOverlay(Context context, View hostView) {
+        mOverlayViewGroup = new OverlayViewGroup(context, hostView);
     }
 
-    @Override
+    /**
+     * Used internally by View and ViewGroup to handle drawing and invalidation
+     * of the overlay
+     * @return
+     */
+    ViewGroup getOverlayView() {
+        return mOverlayViewGroup;
+    }
+
+    /**
+     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
+     * the host view. Any drawable added to the overlay should be removed when it is no longer
+     * needed or no longer visible.
+     *
+     * @param drawable The Drawable to be added to the overlay. This drawable will be
+     * drawn when the view redraws its overlay.
+     * @see #remove(Drawable)
+     */
     public void add(Drawable drawable) {
-        if (mDrawables == null) {
-            mDrawables = new ArrayList<Drawable>();
-        }
-        if (!mDrawables.contains(drawable)) {
-            // Make each drawable unique in the overlay; can't add it more than once
-            mDrawables.add(drawable);
-            invalidate(drawable.getBounds());
-            drawable.setCallback(this);
-        }
+        mOverlayViewGroup.add(drawable);
     }
 
-    @Override
+    /**
+     * Removes the specified Drawable from the overlay.
+     *
+     * @param drawable The Drawable to be removed from the overlay.
+     * @see #add(Drawable)
+     */
     public void remove(Drawable drawable) {
-        if (mDrawables != null) {
-            mDrawables.remove(drawable);
-            invalidate(drawable.getBounds());
-            drawable.setCallback(null);
-        }
+        mOverlayViewGroup.remove(drawable);
     }
 
-    @Override
-    public void invalidateDrawable(Drawable drawable) {
-        invalidate(drawable.getBounds());
-    }
-
-    @Override
-    public void add(View child) {
-        int deltaX = 0;
-        int deltaY = 0;
-        if (child.getParent() instanceof ViewGroup) {
-            ViewGroup parent = (ViewGroup) child.getParent();
-            if (parent != mHostView) {
-                // Moving to different container; figure out how to position child such that
-                // it is in the same location on the screen
-                int[] parentLocation = new int[2];
-                int[] hostViewLocation = new int[2];
-                parent.getLocationOnScreen(parentLocation);
-                mHostView.getLocationOnScreen(hostViewLocation);
-                child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]);
-                child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]);
-            }
-            parent.removeView(child);
-        }
-        super.addView(child);
-    }
-
-    @Override
-    public void remove(View view) {
-        super.removeView(view);
-    }
-
-    @Override
+    /**
+     * Removes all content from the overlay.
+     */
     public void clear() {
-        removeAllViews();
-        mDrawables.clear();
+        mOverlayViewGroup.clear();
     }
 
     boolean isEmpty() {
-        if (getChildCount() == 0 && (mDrawables == null || mDrawables.size() == 0)) {
-            return true;
-        }
-        return false;
+        return mOverlayViewGroup.isEmpty();
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
-        for (int i = 0; i < numDrawables; ++i) {
-            mDrawables.get(i).draw(canvas);
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        // Noop: children are positioned absolutely
-    }
-
-    /*
-     The following invalidation overrides exist for the purpose of redirecting invalidation to
-     the host view. The overlay is not parented to the host view (since a View cannot be a parent),
-     so the invalidation cannot proceed through the normal parent hierarchy.
-     There is a built-in assumption that the overlay exactly covers the host view, therefore
-     the invalidation rectangles received do not need to be adjusted when forwarded to
-     the host view.
+    /**
+     * OverlayViewGroup is a container that View and ViewGroup use to host
+     * drawables and views added to their overlays  ({@link ViewOverlay} and
+     * {@link ViewGroupOverlay}, respectively). Drawables are added to the overlay
+     * via the add/remove methods in ViewOverlay, Views are added/removed via
+     * ViewGroupOverlay. These drawable and view objects are
+     * drawn whenever the view itself is drawn; first the view draws its own
+     * content (and children, if it is a ViewGroup), then it draws its overlay
+     * (if it has one).
+     *
+     * <p>Besides managing and drawing the list of drawables, this class serves
+     * two purposes:
+     * (1) it noops layout calls because children are absolutely positioned and
+     * (2) it forwards all invalidation calls to its host view. The invalidation
+     * redirect is necessary because the overlay is not a child of the host view
+     * and invalidation cannot therefore follow the normal path up through the
+     * parent hierarchy.</p>
+     *
+     * @see View#getOverlay()
+     * @see ViewGroup#getOverlay()
      */
+    static class OverlayViewGroup extends ViewGroup {
 
-    @Override
-    public void invalidate(Rect dirty) {
-        super.invalidate(dirty);
-        if (mHostView != null) {
-            mHostView.invalidate(dirty);
+        /**
+         * The View for which this is an overlay. Invalidations of the overlay are redirected to
+         * this host view.
+         */
+        View mHostView;
+
+        /**
+         * The set of drawables to draw when the overlay is rendered.
+         */
+        ArrayList<Drawable> mDrawables = null;
+
+        OverlayViewGroup(Context context, View hostView) {
+            super(context);
+            mHostView = hostView;
+            mAttachInfo = mHostView.mAttachInfo;
+            mRight = hostView.getWidth();
+            mBottom = hostView.getHeight();
         }
-    }
 
-    @Override
-    public void invalidate(int l, int t, int r, int b) {
-        super.invalidate(l, t, r, b);
-        if (mHostView != null) {
-            mHostView.invalidate(l, t, r, b);
-        }
-    }
+        public void add(Drawable drawable) {
+            if (mDrawables == null) {
 
-    @Override
-    public void invalidate() {
-        super.invalidate();
-        if (mHostView != null) {
-            mHostView.invalidate();
-        }
-    }
-
-    @Override
-    void invalidate(boolean invalidateCache) {
-        super.invalidate(invalidateCache);
-        if (mHostView != null) {
-            mHostView.invalidate(invalidateCache);
-        }
-    }
-
-    @Override
-    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
-        super.invalidateViewProperty(invalidateParent, forceRedraw);
-        if (mHostView != null) {
-            mHostView.invalidateViewProperty(invalidateParent, forceRedraw);
-        }
-    }
-
-    @Override
-    protected void invalidateParentCaches() {
-        super.invalidateParentCaches();
-        if (mHostView != null) {
-            mHostView.invalidateParentCaches();
-        }
-    }
-
-    @Override
-    protected void invalidateParentIfNeeded() {
-        super.invalidateParentIfNeeded();
-        if (mHostView != null) {
-            mHostView.invalidateParentIfNeeded();
-        }
-    }
-
-    public void invalidateChildFast(View child, final Rect dirty) {
-        if (mHostView != null) {
-            // Note: This is not a "fast" invalidation. Would be nice to instead invalidate using DL
-            // properties and a dirty rect instead of causing a real invalidation of the host view
-            int left = child.mLeft;
-            int top = child.mTop;
-            if (!child.getMatrix().isIdentity()) {
-                child.transformRect(dirty);
+                mDrawables = new ArrayList<Drawable>();
             }
-            dirty.offset(left, top);
-            mHostView.invalidate(dirty);
-        }
-    }
-
-    @Override
-    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
-        if (mHostView != null) {
-            dirty.offset(location[0], location[1]);
-            if (mHostView instanceof ViewGroup) {
-                location[0] = 0;
-                location[1] = 0;
-                super.invalidateChildInParent(location, dirty);
-                return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
-            } else {
-                invalidate(dirty);
+            if (!mDrawables.contains(drawable)) {
+                // Make each drawable unique in the overlay; can't add it more than once
+                mDrawables.add(drawable);
+                invalidate(drawable.getBounds());
+                drawable.setCallback(this);
             }
         }
-        return null;
+
+        public void remove(Drawable drawable) {
+            if (mDrawables != null) {
+                mDrawables.remove(drawable);
+                invalidate(drawable.getBounds());
+                drawable.setCallback(null);
+            }
+        }
+
+        public void add(View child) {
+            if (child.getParent() instanceof ViewGroup) {
+                ViewGroup parent = (ViewGroup) child.getParent();
+                if (parent != mHostView) {
+                    // Moving to different container; figure out how to position child such that
+                    // it is in the same location on the screen
+                    int[] parentLocation = new int[2];
+                    int[] hostViewLocation = new int[2];
+                    parent.getLocationOnScreen(parentLocation);
+                    mHostView.getLocationOnScreen(hostViewLocation);
+                    child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]);
+                    child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]);
+                }
+                parent.removeView(child);
+            }
+            super.addView(child);
+        }
+
+        public void remove(View view) {
+            super.removeView(view);
+        }
+
+        public void clear() {
+            removeAllViews();
+            mDrawables.clear();
+        }
+
+        boolean isEmpty() {
+            if (getChildCount() == 0 &&
+                    (mDrawables == null || mDrawables.size() == 0)) {
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void invalidateDrawable(Drawable drawable) {
+            invalidate(drawable.getBounds());
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            super.dispatchDraw(canvas);
+            final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
+            for (int i = 0; i < numDrawables; ++i) {
+                mDrawables.get(i).draw(canvas);
+            }
+        }
+
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            // Noop: children are positioned absolutely
+        }
+
+        /*
+         The following invalidation overrides exist for the purpose of redirecting invalidation to
+         the host view. The overlay is not parented to the host view (since a View cannot be a
+         parent), so the invalidation cannot proceed through the normal parent hierarchy.
+         There is a built-in assumption that the overlay exactly covers the host view, therefore
+         the invalidation rectangles received do not need to be adjusted when forwarded to
+         the host view.
+         */
+
+        @Override
+        public void invalidate(Rect dirty) {
+            super.invalidate(dirty);
+            if (mHostView != null) {
+                mHostView.invalidate(dirty);
+            }
+        }
+
+        @Override
+        public void invalidate(int l, int t, int r, int b) {
+            super.invalidate(l, t, r, b);
+            if (mHostView != null) {
+                mHostView.invalidate(l, t, r, b);
+            }
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            if (mHostView != null) {
+                mHostView.invalidate();
+            }
+        }
+
+        @Override
+        void invalidate(boolean invalidateCache) {
+            super.invalidate(invalidateCache);
+            if (mHostView != null) {
+                mHostView.invalidate(invalidateCache);
+            }
+        }
+
+        @Override
+        void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
+            super.invalidateViewProperty(invalidateParent, forceRedraw);
+            if (mHostView != null) {
+                mHostView.invalidateViewProperty(invalidateParent, forceRedraw);
+            }
+        }
+
+        @Override
+        protected void invalidateParentCaches() {
+            super.invalidateParentCaches();
+            if (mHostView != null) {
+                mHostView.invalidateParentCaches();
+            }
+        }
+
+        @Override
+        protected void invalidateParentIfNeeded() {
+            super.invalidateParentIfNeeded();
+            if (mHostView != null) {
+                mHostView.invalidateParentIfNeeded();
+            }
+        }
+
+        public void invalidateChildFast(View child, final Rect dirty) {
+            if (mHostView != null) {
+                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
+                // using DisplayList properties and a dirty rect instead of causing a real
+                // invalidation of the host view
+                int left = child.mLeft;
+                int top = child.mTop;
+                if (!child.getMatrix().isIdentity()) {
+                    child.transformRect(dirty);
+                }
+                dirty.offset(left, top);
+                mHostView.invalidate(dirty);
+            }
+        }
+
+        @Override
+        public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
+            if (mHostView != null) {
+                dirty.offset(location[0], location[1]);
+                if (mHostView instanceof ViewGroup) {
+                    location[0] = 0;
+                    location[1] = 0;
+                    super.invalidateChildInParent(location, dirty);
+                    return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
+                } else {
+                    invalidate(dirty);
+                }
+            }
+            return null;
+        }
     }
+
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9387624..22586f6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -42,7 +42,6 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
-import android.os.LatencyTimer;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
@@ -116,9 +115,6 @@
      * at 60 Hz. This can be used to measure the potential framerate.
      */
     private static final String PROPERTY_PROFILE_RENDERING = "viewancestor.profile_rendering";
-    
-    private static final boolean MEASURE_LATENCY = false;
-    private static LatencyTimer lt;
 
     /**
      * Maximum time we allow the user to roll the trackball enough to generate
@@ -138,26 +134,15 @@
     private static boolean sRenderThreadQueried = false;
     private static final Object[] sRenderThreadQueryLock = new Object[0];
 
+    final Context mContext;
     final IWindowSession mWindowSession;
     final Display mDisplay;
     final String mBasePackageName;
 
-    long mLastTrackballTime = 0;
-    final TrackballAxis mTrackballAxisX = new TrackballAxis();
-    final TrackballAxis mTrackballAxisY = new TrackballAxis();
-
-    final SimulatedDpad mSimulatedDpad;
-
-    int mLastJoystickXDirection;
-    int mLastJoystickYDirection;
-    int mLastJoystickXKeyCode;
-    int mLastJoystickYKeyCode;
-
     final int[] mTmpLocation = new int[2];
 
     final TypedValue mTmpValue = new TypedValue();
-    
-    final InputMethodCallback mInputMethodCallback;
+
     final Thread mThread;
 
     final WindowLeaked mLocation;
@@ -197,7 +182,6 @@
     int mHeight;
     Rect mDirty;
     final Rect mCurrentDirty = new Rect();
-    final Rect mPreviousDirty = new Rect();
     boolean mIsAnimating;
 
     CompatibilityInfo.Translator mTranslator;
@@ -232,38 +216,23 @@
     int mClientWindowLayoutFlags;
     boolean mLastOverscanRequested;
 
-     /** Event was not handled and is finished.
-      * @hide */
-    public static final int EVENT_NOT_HANDLED = 0;
-     /** Event was handled and is finished.
-      * @hide */
-    public static final int EVENT_HANDLED = 1;
-    /** Event is waiting on the IME.
-     * @hide */
-    public static final int EVENT_PENDING_IME = 2;
-    /** Event requires post-IME dispatch.
-     * @hide */
-    public static final int EVENT_POST_IME = 3;
-
     // Pool of queued input events.
     private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
     private QueuedInputEvent mQueuedInputEventPool;
     private int mQueuedInputEventPoolSize;
 
     /* Input event queue.
-     * Pending input events are input events waiting to be handled by the application. Current
-     * input events are input events which are being handled but are waiting on some action by the
-     * IME, even if they themselves may not need to be handled by the IME.
+     * Pending input events are input events waiting to be delivered to the input stages
+     * and handled by the application.
      */
     QueuedInputEvent mPendingInputEventHead;
     QueuedInputEvent mPendingInputEventTail;
     int mPendingInputEventCount;
-    QueuedInputEvent mActiveInputEventHead;
-    QueuedInputEvent mActiveInputEventTail;
-    int mActiveInputEventCount;
     boolean mProcessInputEventsScheduled;
     String mPendingInputEventQueueLengthCounterName = "pq";
-    String mActiveInputEventQueueLengthCounterName = "aq";
+
+    InputStage mFirstInputStage;
+    InputStage mFirstPostImeInputStage;
 
     boolean mWindowAttributesChanged = false;
     int mWindowAttributesChangesFlag = 0;
@@ -362,18 +331,8 @@
     }
     
     public ViewRootImpl(Context context, Display display) {
-        super();
-
-        if (MEASURE_LATENCY) {
-            if (lt == null) {
-                lt = new LatencyTimer(100, 1000);
-            }
-        }
-
-        // Initialize the statics when this class is first instantiated. This is
-        // done here instead of in the static block because Zygote does not
-        // allow the spawning of threads.
-        mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+        mContext = context;
+        mWindowSession = WindowManagerGlobal.getWindowSession();
         mDisplay = display;
         mBasePackageName = context.getBasePackageName();
 
@@ -391,7 +350,6 @@
         mWinFrame = new Rect();
         mWindow = new W(this);
         mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
-        mInputMethodCallback = new InputMethodCallback(this);
         mViewVisibility = View.GONE;
         mTransparentRegion = new Region();
         mPreviousTransparentRegion = new Region();
@@ -412,7 +370,6 @@
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mAttachInfo.mScreenOn = powerManager.isScreenOn();
         loadSystemProperties();
-        mSimulatedDpad = new SimulatedDpad(context);
     }
 
     /**
@@ -660,8 +617,22 @@
                     view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
                 }
 
-                mPendingInputEventQueueLengthCounterName = "pq:" + attrs.getTitle();
-                mActiveInputEventQueueLengthCounterName = "aq:" + attrs.getTitle();
+                // Set up the input pipeline.
+                CharSequence counterSuffix = attrs.getTitle();
+                InputStage syntheticStage = new SyntheticInputStage();
+                InputStage viewPostImeStage = new ViewPostImeInputStage(syntheticStage);
+                InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
+                        "aq:native-post-ime:" + counterSuffix);
+                InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
+                InputStage imeStage = new ImeInputStage(earlyPostImeStage,
+                        "aq:ime:" + counterSuffix);
+                InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
+                InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
+                        "aq:native-pre-ime:" + counterSuffix);
+
+                mFirstInputStage = nativePreImeStage;
+                mFirstPostImeInputStage = earlyPostImeStage;
+                mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
             }
         }
     }
@@ -767,10 +738,11 @@
 
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE;
                 mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
-                mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
-                mAttachInfo.mHardwareAccelerated = mAttachInfo.mHardwareAccelerationRequested
-                        = mAttachInfo.mHardwareRenderer != null;
-
+                if (mAttachInfo.mHardwareRenderer != null) {
+                    mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
+                    mAttachInfo.mHardwareAccelerated =
+                            mAttachInfo.mHardwareAccelerationRequested = true;
+                }
             } else if (fakeHwAccelerated) {
                 // The window had wanted to use hardware acceleration, but this
                 // is not allowed in its process.  By setting this flag, it can
@@ -2387,14 +2359,10 @@
                 mResizeAlpha = resizeAlpha;
 
                 mCurrentDirty.set(dirty);
-                mCurrentDirty.union(mPreviousDirty);
-                mPreviousDirty.set(dirty);
                 dirty.setEmpty();
 
-                if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
-                        animating ? null : mCurrentDirty)) {
-                    mPreviousDirty.set(0, 0, mWidth, mHeight);
-                }
+                attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
+                        animating ? null : mCurrentDirty);
             } else {
                 // If we get here with a disabled & requested hardware renderer, something went
                 // wrong (an invalidate posted right before we destroyed the hardware surface
@@ -2449,6 +2417,8 @@
 
             canvas = mSurface.lockCanvas(dirty);
 
+            // The dirty rectangle can be modified by Surface.lockCanvas()
+            //noinspection ConstantConditions
             if (left != dirty.left || top != dirty.top || right != dirty.right ||
                     bottom != dirty.bottom) {
                 attachInfo.mIgnoreDirtyState = true;
@@ -2861,7 +2831,7 @@
             mWindowSession.remove(mWindow);
         } catch (RemoteException e) {
         }
-        
+
         // Dispose the input channel after removing the window so the Window Manager
         // doesn't interpret the input channel being closed as an abnormal termination.
         if (mInputChannel != null) {
@@ -3099,8 +3069,7 @@
                         boolean inTouchMode = msg.arg2 != 0;
                         ensureTouchModeLocally(inTouchMode);
 
-                        if (mAttachInfo.mHardwareRenderer != null &&
-                                mSurface != null && mSurface.isValid()) {
+                        if (mAttachInfo.mHardwareRenderer != null && mSurface.isValid()){
                             mFullRedrawNeeded = true;
                             try {
                                 mAttachInfo.mHardwareRenderer.initializeIfNeeded(
@@ -3365,365 +3334,822 @@
         return false;
     }
 
-    private int deliverInputEvent(QueuedInputEvent q) {
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
-        try {
+    /**
+     * Base class for implementing a stage in the chain of responsibility
+     * for processing input events.
+     * <p>
+     * Events are delivered to the stage by the {@link #deliver} method.  The stage
+     * then has the choice of finishing the event or forwarding it to the next stage.
+     * </p>
+     */
+    abstract class InputStage {
+        private final InputStage mNext;
+
+        protected static final int FORWARD = 0;
+        protected static final int FINISH_HANDLED = 1;
+        protected static final int FINISH_NOT_HANDLED = 2;
+
+        /**
+         * Creates an input stage.
+         * @param next The next stage to which events should be forwarded.
+         */
+        public InputStage(InputStage next) {
+            mNext = next;
+        }
+
+        /**
+         * Delivers an event to be processed.
+         */
+        public final void deliver(QueuedInputEvent q) {
+            if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
+                forward(q);
+            } else if (mView == null || !mAdded) {
+                finish(q, false);
+            } else {
+                apply(q, onProcess(q));
+            }
+        }
+
+        /**
+         * Marks the the input event as finished then forwards it to the next stage.
+         */
+        protected void finish(QueuedInputEvent q, boolean handled) {
+            q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
+            if (handled) {
+                q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
+            }
+            forward(q);
+        }
+
+        /**
+         * Forwards the event to the next stage.
+         */
+        protected void forward(QueuedInputEvent q) {
+            onDeliverToNext(q);
+        }
+
+        /**
+         * Applies a result code from {@link #onProcess} to the specified event.
+         */
+        protected void apply(QueuedInputEvent q, int result) {
+            if (result == FORWARD) {
+                forward(q);
+            } else if (result == FINISH_HANDLED) {
+                finish(q, true);
+            } else if (result == FINISH_NOT_HANDLED) {
+                finish(q, false);
+            } else {
+                throw new IllegalArgumentException("Invalid result: " + result);
+            }
+        }
+
+        /**
+         * Called when an event is ready to be processed.
+         * @return A result code indicating how the event was handled.
+         */
+        protected int onProcess(QueuedInputEvent q) {
+            return FORWARD;
+        }
+
+        /**
+         * Called when an event is being delivered to the next stage.
+         */
+        protected void onDeliverToNext(QueuedInputEvent q) {
+            if (mNext != null) {
+                mNext.deliver(q);
+            } else {
+                finishInputEvent(q);
+            }
+        }
+    }
+
+    /**
+     * Base class for implementing an input pipeline stage that supports
+     * asynchronous and out-of-order processing of input events.
+     * <p>
+     * In addition to what a normal input stage can do, an asynchronous
+     * input stage may also defer an input event that has been delivered to it
+     * and finish or forward it later.
+     * </p>
+     */
+    abstract class AsyncInputStage extends InputStage {
+        private final String mTraceCounter;
+
+        private QueuedInputEvent mQueueHead;
+        private QueuedInputEvent mQueueTail;
+        private int mQueueLength;
+
+        protected static final int DEFER = 3;
+
+        /**
+         * Creates an asynchronous input stage.
+         * @param next The next stage to which events should be forwarded.
+         * @param traceCounter The name of a counter to record the size of
+         * the queue of pending events.
+         */
+        public AsyncInputStage(InputStage next, String traceCounter) {
+            super(next);
+            mTraceCounter = traceCounter;
+        }
+
+        /**
+         * Marks the event as deferred, which is to say that it will be handled
+         * asynchronously.  The caller is responsible for calling {@link #forward}
+         * or {@link #finish} later when it is done handling the event.
+         */
+        protected void defer(QueuedInputEvent q) {
+            q.mFlags |= QueuedInputEvent.FLAG_DEFERRED;
+            enqueue(q);
+        }
+
+        @Override
+        protected void forward(QueuedInputEvent q) {
+            // Clear the deferred flag.
+            q.mFlags &= ~QueuedInputEvent.FLAG_DEFERRED;
+
+            // Fast path if the queue is empty.
+            QueuedInputEvent curr = mQueueHead;
+            if (curr == null) {
+                super.forward(q);
+                return;
+            }
+
+            // Determine whether the event must be serialized behind any others
+            // before it can be delivered to the next stage.  This is done because
+            // deferred events might be handled out of order by the stage.
+            final int deviceId = q.mEvent.getDeviceId();
+            QueuedInputEvent prev = null;
+            boolean blocked = false;
+            while (curr != null && curr != q) {
+                if (!blocked && deviceId == curr.mEvent.getDeviceId()) {
+                    blocked = true;
+                }
+                prev = curr;
+                curr = curr.mNext;
+            }
+
+            // If the event is blocked, then leave it in the queue to be delivered later.
+            // Note that the event might not yet be in the queue if it was not previously
+            // deferred so we will enqueue it if needed.
+            if (blocked) {
+                if (curr == null) {
+                    enqueue(q);
+                }
+                return;
+            }
+
+            // The event is not blocked.  Deliver it immediately.
+            if (curr != null) {
+                curr = curr.mNext;
+                dequeue(q, prev);
+            }
+            super.forward(q);
+
+            // Dequeuing this event may have unblocked successors.  Deliver them.
+            while (curr != null) {
+                if (deviceId == curr.mEvent.getDeviceId()) {
+                    if ((curr.mFlags & QueuedInputEvent.FLAG_DEFERRED) != 0) {
+                        break;
+                    }
+                    QueuedInputEvent next = curr.mNext;
+                    dequeue(curr, prev);
+                    super.forward(curr);
+                    curr = next;
+                } else {
+                    prev = curr;
+                    curr = curr.mNext;
+                }
+            }
+        }
+
+        @Override
+        protected void apply(QueuedInputEvent q, int result) {
+            if (result == DEFER) {
+                defer(q);
+            } else {
+                super.apply(q, result);
+            }
+        }
+
+        private void enqueue(QueuedInputEvent q) {
+            if (mQueueTail == null) {
+                mQueueHead = q;
+                mQueueTail = q;
+            } else {
+                mQueueTail.mNext = q;
+                mQueueTail = q;
+            }
+
+            mQueueLength += 1;
+            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
+        }
+
+        private void dequeue(QueuedInputEvent q, QueuedInputEvent prev) {
+            if (prev == null) {
+                mQueueHead = q.mNext;
+            } else {
+                prev.mNext = q.mNext;
+            }
+            if (mQueueTail == q) {
+                mQueueTail = prev;
+            }
+            q.mNext = null;
+
+            mQueueLength -= 1;
+            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
+        }
+    }
+
+    /**
+     * Delivers pre-ime input events to a native activity.
+     * Does not support pointer events.
+     */
+    final class NativePreImeInputStage extends AsyncInputStage {
+        public NativePreImeInputStage(InputStage next, String traceCounter) {
+            super(next, traceCounter);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
+            return FORWARD;
+        }
+    }
+
+    /**
+     * Delivers pre-ime input events to the view hierarchy.
+     * Does not support pointer events.
+     */
+    final class ViewPreImeInputStage extends InputStage {
+        public ViewPreImeInputStage(InputStage next) {
+            super(next);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
             if (q.mEvent instanceof KeyEvent) {
-                return deliverKeyEvent(q);
+                return processKeyEvent(q);
+            }
+            return FORWARD;
+        }
+
+        private int processKeyEvent(QueuedInputEvent q) {
+            final KeyEvent event = (KeyEvent)q.mEvent;
+            if (mView.dispatchKeyEventPreIme(event)) {
+                return FINISH_HANDLED;
+            }
+            return FORWARD;
+        }
+    }
+
+    /**
+     * Delivers input events to the ime.
+     * Does not support pointer events.
+     */
+    final class ImeInputStage extends AsyncInputStage
+            implements InputMethodManager.FinishedInputEventCallback {
+        public ImeInputStage(InputStage next, String traceCounter) {
+            super(next, traceCounter);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
+            if (mLastWasImTarget) {
+                InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    final InputEvent event = q.mEvent;
+                    if (DEBUG_IMF) Log.v(TAG, "Sending input event to IME: " + event);
+                    int result = imm.dispatchInputEvent(event, q, this, mHandler);
+                    if (result == InputMethodManager.DISPATCH_HANDLED) {
+                        return FINISH_HANDLED;
+                    } else if (result == InputMethodManager.DISPATCH_NOT_HANDLED) {
+                        return FINISH_NOT_HANDLED;
+                    } else {
+                        return DEFER; // callback will be invoked later
+                    }
+                }
+            }
+            return FORWARD;
+        }
+
+        @Override
+        public void onFinishedInputEvent(Object token, boolean handled) {
+            QueuedInputEvent q = (QueuedInputEvent)token;
+            if (handled) {
+                finish(q, true);
+                return;
+            }
+
+            // If the window doesn't currently have input focus, then drop
+            // this event.  This could be an event that came back from the
+            // IME dispatch but the window has lost focus in the meantime.
+            if (!mAttachInfo.mHasWindowFocus && !isTerminalInputEvent(q.mEvent)) {
+                Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
+                finish(q, false);
+                return;
+            }
+
+            forward(q);
+        }
+    }
+
+    /**
+     * Performs early processing of post-ime input events.
+     */
+    final class EarlyPostImeInputStage extends InputStage {
+        public EarlyPostImeInputStage(InputStage next) {
+            super(next);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
+            if (q.mEvent instanceof KeyEvent) {
+                return processKeyEvent(q);
             } else {
                 final int source = q.mEvent.getSource();
                 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-                    return deliverPointerEvent(q);
-                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
-                    return deliverTrackballEvent(q);
-                } else {
-                    return deliverGenericMotionEvent(q);
+                    return processPointerEvent(q);
                 }
             }
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+            return FORWARD;
+        }
+
+        private int processKeyEvent(QueuedInputEvent q) {
+            final KeyEvent event = (KeyEvent)q.mEvent;
+
+            // If the key's purpose is to exit touch mode then we consume it
+            // and consider it handled.
+            if (checkForLeavingTouchModeAndConsume(event)) {
+                return FINISH_HANDLED;
+            }
+
+            // Make sure the fallback event policy sees all keys that will be
+            // delivered to the view hierarchy.
+            mFallbackEventHandler.preDispatchKeyEvent(event);
+            return FORWARD;
+        }
+
+        private int processPointerEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+
+            // Translate the pointer event for compatibility, if needed.
+            if (mTranslator != null) {
+                mTranslator.translateEventInScreenToAppWindow(event);
+            }
+
+            // Enter touch mode on down or scroll.
+            final int action = event.getAction();
+            if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
+                ensureTouchMode(true);
+            }
+
+            // Offset the scroll position.
+            if (mCurScrollY != 0) {
+                event.offsetLocation(0, mCurScrollY);
+            }
+
+            // Remember the touch position for possible drag-initiation.
+            if (event.isTouchEvent()) {
+                mLastTouchPoint.x = event.getRawX();
+                mLastTouchPoint.y = event.getRawY();
+            }
+            return FORWARD;
         }
     }
 
-    private int deliverInputEventPostIme(QueuedInputEvent q) {
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEventPostIme");
-        try {
+    /**
+     * Delivers post-ime input events to a native activity.
+     */
+    final class NativePostImeInputStage extends AsyncInputStage {
+        public NativePostImeInputStage(InputStage next, String traceCounter) {
+            super(next, traceCounter);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
+            return FORWARD;
+        }
+    }
+
+    /**
+     * Delivers post-ime input events to the view hierarchy.
+     */
+    final class ViewPostImeInputStage extends InputStage {
+        public ViewPostImeInputStage(InputStage next) {
+            super(next);
+        }
+
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
             if (q.mEvent instanceof KeyEvent) {
-                return deliverKeyEventPostIme(q);
+                return processKeyEvent(q);
             } else {
                 final int source = q.mEvent.getSource();
-                if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
-                    return deliverTrackballEventPostIme(q);
+                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+                    return processPointerEvent(q);
+                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                    return processTrackballEvent(q);
                 } else {
-                    return deliverGenericMotionEventPostIme(q);
+                    return processGenericMotionEvent(q);
                 }
             }
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
-    }
 
-    private int deliverPointerEvent(QueuedInputEvent q) {
-        final MotionEvent event = (MotionEvent)q.mEvent;
-        final boolean isTouchEvent = event.isTouchEvent();
-        if (mInputEventConsistencyVerifier != null) {
-            if (isTouchEvent) {
-                mInputEventConsistencyVerifier.onTouchEvent(event, 0);
-            } else {
-                mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
+        private int processKeyEvent(QueuedInputEvent q) {
+            final KeyEvent event = (KeyEvent)q.mEvent;
+
+            // Deliver the key to the view hierarchy.
+            if (mView.dispatchKeyEvent(event)) {
+                return FINISH_HANDLED;
             }
+
+            // If the Control modifier is held, try to interpret the key as a shortcut.
+            if (event.getAction() == KeyEvent.ACTION_DOWN
+                    && event.isCtrlPressed()
+                    && event.getRepeatCount() == 0
+                    && !KeyEvent.isModifierKey(event.getKeyCode())) {
+                if (mView.dispatchKeyShortcutEvent(event)) {
+                    return FINISH_HANDLED;
+                }
+            }
+
+            // Apply the fallback event policy.
+            if (mFallbackEventHandler.dispatchKeyEvent(event)) {
+                return FINISH_HANDLED;
+            }
+
+            // Handle automatic focus changes.
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                int direction = 0;
+                switch (event.getKeyCode()) {
+                    case KeyEvent.KEYCODE_DPAD_LEFT:
+                        if (event.hasNoModifiers()) {
+                            direction = View.FOCUS_LEFT;
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_DPAD_RIGHT:
+                        if (event.hasNoModifiers()) {
+                            direction = View.FOCUS_RIGHT;
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_DPAD_UP:
+                        if (event.hasNoModifiers()) {
+                            direction = View.FOCUS_UP;
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_DPAD_DOWN:
+                        if (event.hasNoModifiers()) {
+                            direction = View.FOCUS_DOWN;
+                        }
+                        break;
+                    case KeyEvent.KEYCODE_TAB:
+                        if (event.hasNoModifiers()) {
+                            direction = View.FOCUS_FORWARD;
+                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                            direction = View.FOCUS_BACKWARD;
+                        }
+                        break;
+                }
+                if (direction != 0) {
+                    View focused = mView.findFocus();
+                    if (focused != null) {
+                        View v = focused.focusSearch(direction);
+                        if (v != null && v != focused) {
+                            // do the math the get the interesting rect
+                            // of previous focused into the coord system of
+                            // newly focused view
+                            focused.getFocusedRect(mTempRect);
+                            if (mView instanceof ViewGroup) {
+                                ((ViewGroup) mView).offsetDescendantRectToMyCoords(
+                                        focused, mTempRect);
+                                ((ViewGroup) mView).offsetRectIntoDescendantCoords(
+                                        v, mTempRect);
+                            }
+                            if (v.requestFocus(direction, mTempRect)) {
+                                playSoundEffect(SoundEffectConstants
+                                        .getContantForFocusDirection(direction));
+                                return FINISH_HANDLED;
+                            }
+                        }
+
+                        // Give the focused view a last chance to handle the dpad key.
+                        if (mView.dispatchUnhandledMove(focused, direction)) {
+                            return FINISH_HANDLED;
+                        }
+                    } else {
+                        // find the best view to give focus to in this non-touch-mode with no-focus
+                        View v = focusSearch(null, direction);
+                        if (v != null && v.requestFocus(direction)) {
+                            return FINISH_HANDLED;
+                        }
+                    }
+                }
+            }
+            return FORWARD;
         }
 
-        // If there is no view, then the event will not be handled.
-        if (mView == null || !mAdded) {
-            return EVENT_NOT_HANDLED;
+        private int processPointerEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+
+            if (mView.dispatchPointerEvent(event)) {
+                return FINISH_HANDLED;
+            }
+            return FORWARD;
         }
 
-        // Translate the pointer event for compatibility, if needed.
-        if (mTranslator != null) {
-            mTranslator.translateEventInScreenToAppWindow(event);
+        private int processTrackballEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+
+            if (mView.dispatchTrackballEvent(event)) {
+                return FINISH_HANDLED;
+            }
+            return FORWARD;
         }
 
-        // Enter touch mode on down or scroll.
-        final int action = event.getAction();
-        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
-            ensureTouchMode(true);
-        }
+        private int processGenericMotionEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
 
-        // Offset the scroll position.
-        if (mCurScrollY != 0) {
-            event.offsetLocation(0, mCurScrollY);
+            // Deliver the event to the view.
+            if (mView.dispatchGenericMotionEvent(event)) {
+                return FINISH_HANDLED;
+            }
+            return FORWARD;
         }
-        if (MEASURE_LATENCY) {
-            lt.sample("A Dispatching PointerEvents", System.nanoTime() - event.getEventTimeNano());
-        }
-
-        // Remember the touch position for possible drag-initiation.
-        if (isTouchEvent) {
-            mLastTouchPoint.x = event.getRawX();
-            mLastTouchPoint.y = event.getRawY();
-        }
-
-        // Dispatch touch to view hierarchy.
-        boolean handled = mView.dispatchPointerEvent(event);
-        if (MEASURE_LATENCY) {
-            lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());
-        }
-        return handled ? EVENT_HANDLED : EVENT_NOT_HANDLED;
     }
 
-    private int deliverTrackballEvent(QueuedInputEvent q) {
-        final MotionEvent event = (MotionEvent)q.mEvent;
-        if (mInputEventConsistencyVerifier != null) {
-            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
+    /**
+     * Performs default processing of unhandled input events.
+     */
+    final class SyntheticInputStage extends InputStage {
+        private final TrackballAxis mTrackballAxisX = new TrackballAxis();
+        private final TrackballAxis mTrackballAxisY = new TrackballAxis();
+        private long mLastTrackballTime;
+
+        private int mLastJoystickXDirection;
+        private int mLastJoystickYDirection;
+        private int mLastJoystickXKeyCode;
+        private int mLastJoystickYKeyCode;
+
+        private SimulatedDpad mSimulatedDpad;
+
+        public SyntheticInputStage() {
+            super(null);
+            mSimulatedDpad = new SimulatedDpad(mContext);
         }
 
-        int result = EVENT_POST_IME;
-        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
-            if (LOCAL_LOGV)
-                Log.v(TAG, "Dispatching trackball " + event + " to " + mView);
-
-            // Dispatch to the IME before propagating down the view hierarchy.
-            result = dispatchImeInputEvent(q);
-        }
-        return result;
-    }
-
-    private int deliverTrackballEventPostIme(QueuedInputEvent q) {
-        final MotionEvent event = (MotionEvent) q.mEvent;
-
-        // If there is no view, then the event will not be handled.
-        if (mView == null || !mAdded) {
-            return EVENT_NOT_HANDLED;
+        @Override
+        protected int onProcess(QueuedInputEvent q) {
+            q.mFlags |= QueuedInputEvent.FLAG_RESYNTHESIZED;
+            if (q.mEvent instanceof MotionEvent) {
+                final int source = q.mEvent.getSource();
+                if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                    return processTrackballEvent(q);
+                } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
+                    return processJoystickEvent(q);
+                } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
+                        == InputDevice.SOURCE_TOUCH_NAVIGATION) {
+                    return processTouchNavigationEvent(q);
+                }
+            }
+            return FORWARD;
         }
 
-        // Deliver the trackball event to the view.
-        if (mView.dispatchTrackballEvent(event)) {
-            // If we reach this, we delivered a trackball event to mView and
-            // mView consumed it. Because we will not translate the trackball
-            // event into a key event, touch mode will not exit, so we exit
-            // touch mode here.
-            ensureTouchMode(false);
+        @Override
+        protected void onDeliverToNext(QueuedInputEvent q) {
+            if ((q.mFlags & QueuedInputEvent.FLAG_RESYNTHESIZED) == 0) {
+                // Cancel related synthetic events if any prior stage has handled the event.
+                if (q.mEvent instanceof MotionEvent) {
+                    final int source = q.mEvent.getSource();
+                    if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                        cancelTrackballEvent(q);
+                    } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
+                        cancelJoystickEvent(q);
+                    } else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
+                            == InputDevice.SOURCE_TOUCH_NAVIGATION) {
+                        cancelTouchNavigationEvent(q);
+                    }
+                }
+            }
+            super.onDeliverToNext(q);
+        }
+
+        private int processTrackballEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+
+            // Translate the trackball event into DPAD keys and try to deliver those.
+            final TrackballAxis x = mTrackballAxisX;
+            final TrackballAxis y = mTrackballAxisY;
+            long curTime = SystemClock.uptimeMillis();
+            if ((mLastTrackballTime + MAX_TRACKBALL_DELAY) < curTime) {
+                // It has been too long since the last movement,
+                // so restart at the beginning.
+                x.reset(0);
+                y.reset(0);
+                mLastTrackballTime = curTime;
+            }
+
+            final int action = event.getAction();
+            final int metaState = event.getMetaState();
+            switch (action) {
+                case MotionEvent.ACTION_DOWN:
+                    x.reset(2);
+                    y.reset(2);
+                    enqueueInputEvent(new KeyEvent(curTime, curTime,
+                            KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                            InputDevice.SOURCE_KEYBOARD));
+                    break;
+                case MotionEvent.ACTION_UP:
+                    x.reset(2);
+                    y.reset(2);
+                    enqueueInputEvent(new KeyEvent(curTime, curTime,
+                            KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                            InputDevice.SOURCE_KEYBOARD));
+                    break;
+            }
+
+            if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
+                    + x.step + " dir=" + x.dir + " acc=" + x.acceleration
+                    + " move=" + event.getX()
+                    + " / Y=" + y.position + " step="
+                    + y.step + " dir=" + y.dir + " acc=" + y.acceleration
+                    + " move=" + event.getY());
+            final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
+            final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
+
+            // Generate DPAD events based on the trackball movement.
+            // We pick the axis that has moved the most as the direction of
+            // the DPAD.  When we generate DPAD events for one axis, then the
+            // other axis is reset -- we don't want to perform DPAD jumps due
+            // to slight movements in the trackball when making major movements
+            // along the other axis.
+            int keycode = 0;
+            int movement = 0;
+            float accel = 1;
+            if (xOff > yOff) {
+                movement = x.generate();
+                if (movement != 0) {
+                    keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
+                            : KeyEvent.KEYCODE_DPAD_LEFT;
+                    accel = x.acceleration;
+                    y.reset(2);
+                }
+            } else if (yOff > 0) {
+                movement = y.generate();
+                if (movement != 0) {
+                    keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
+                            : KeyEvent.KEYCODE_DPAD_UP;
+                    accel = y.acceleration;
+                    x.reset(2);
+                }
+            }
+
+            if (keycode != 0) {
+                if (movement < 0) movement = -movement;
+                int accelMovement = (int)(movement * accel);
+                if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
+                        + " accelMovement=" + accelMovement
+                        + " accel=" + accel);
+                if (accelMovement > movement) {
+                    if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
+                            + keycode);
+                    movement--;
+                    int repeatCount = accelMovement - movement;
+                    enqueueInputEvent(new KeyEvent(curTime, curTime,
+                            KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
+                            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                            InputDevice.SOURCE_KEYBOARD));
+                }
+                while (movement > 0) {
+                    if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
+                            + keycode);
+                    movement--;
+                    curTime = SystemClock.uptimeMillis();
+                    enqueueInputEvent(new KeyEvent(curTime, curTime,
+                            KeyEvent.ACTION_DOWN, keycode, 0, metaState,
+                            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                            InputDevice.SOURCE_KEYBOARD));
+                    enqueueInputEvent(new KeyEvent(curTime, curTime,
+                            KeyEvent.ACTION_UP, keycode, 0, metaState,
+                            KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                            InputDevice.SOURCE_KEYBOARD));
+                }
+                mLastTrackballTime = curTime;
+            }
+
+            // Unfortunately we can't tell whether the application consumed the keys, so
+            // we always consider the trackball event handled.
+            return FINISH_HANDLED;
+        }
+
+        private void cancelTrackballEvent(QueuedInputEvent q) {
             mLastTrackballTime = Integer.MIN_VALUE;
-            return EVENT_HANDLED;
-        }
 
-        // Translate the trackball event into DPAD keys and try to deliver those.
-        final TrackballAxis x = mTrackballAxisX;
-        final TrackballAxis y = mTrackballAxisY;
-
-        long curTime = SystemClock.uptimeMillis();
-        if ((mLastTrackballTime + MAX_TRACKBALL_DELAY) < curTime) {
-            // It has been too long since the last movement,
-            // so restart at the beginning.
-            x.reset(0);
-            y.reset(0);
-            mLastTrackballTime = curTime;
-        }
-
-        final int action = event.getAction();
-        final int metaState = event.getMetaState();
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                x.reset(2);
-                y.reset(2);
-                enqueueInputEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
-                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
-                        InputDevice.SOURCE_KEYBOARD));
-                break;
-            case MotionEvent.ACTION_UP:
-                x.reset(2);
-                y.reset(2);
-                enqueueInputEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
-                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
-                        InputDevice.SOURCE_KEYBOARD));
-                break;
-        }
-
-        if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
-                + x.step + " dir=" + x.dir + " acc=" + x.acceleration
-                + " move=" + event.getX()
-                + " / Y=" + y.position + " step="
-                + y.step + " dir=" + y.dir + " acc=" + y.acceleration
-                + " move=" + event.getY());
-        final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
-        final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
-
-        // Generate DPAD events based on the trackball movement.
-        // We pick the axis that has moved the most as the direction of
-        // the DPAD.  When we generate DPAD events for one axis, then the
-        // other axis is reset -- we don't want to perform DPAD jumps due
-        // to slight movements in the trackball when making major movements
-        // along the other axis.
-        int keycode = 0;
-        int movement = 0;
-        float accel = 1;
-        if (xOff > yOff) {
-            movement = x.generate((2/event.getXPrecision()));
-            if (movement != 0) {
-                keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
-                        : KeyEvent.KEYCODE_DPAD_LEFT;
-                accel = x.acceleration;
-                y.reset(2);
-            }
-        } else if (yOff > 0) {
-            movement = y.generate((2/event.getYPrecision()));
-            if (movement != 0) {
-                keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
-                        : KeyEvent.KEYCODE_DPAD_UP;
-                accel = y.acceleration;
-                x.reset(2);
+            // If we reach this, we consumed a trackball event.
+            // Because we will not translate the trackball event into a key event,
+            // touch mode will not exit, so we exit touch mode here.
+            if (mView != null && mAdded) {
+                ensureTouchMode(false);
             }
         }
 
-        if (keycode != 0) {
-            if (movement < 0) movement = -movement;
-            int accelMovement = (int)(movement * accel);
-            if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
-                    + " accelMovement=" + accelMovement
-                    + " accel=" + accel);
-            if (accelMovement > movement) {
-                if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
-                        + keycode);
-                movement--;
-                int repeatCount = accelMovement - movement;
-                enqueueInputEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
-                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
-                        InputDevice.SOURCE_KEYBOARD));
-            }
-            while (movement > 0) {
-                if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
-                        + keycode);
-                movement--;
-                curTime = SystemClock.uptimeMillis();
-                enqueueInputEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, keycode, 0, metaState,
-                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
-                        InputDevice.SOURCE_KEYBOARD));
-                enqueueInputEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, keycode, 0, metaState,
-                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
-                        InputDevice.SOURCE_KEYBOARD));
-            }
-            mLastTrackballTime = curTime;
-        }
-
-        // Unfortunately we can't tell whether the application consumed the keys, so
-        // we always consider the trackball event handled.
-        return EVENT_HANDLED;
-    }
-
-    private int deliverGenericMotionEvent(QueuedInputEvent q) {
-        final MotionEvent event = (MotionEvent)q.mEvent;
-        if (mInputEventConsistencyVerifier != null) {
-            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
-        }
-
-        int result = EVENT_POST_IME;
-        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
-            if (LOCAL_LOGV)
-                Log.v(TAG, "Dispatching generic motion " + event + " to " + mView);
-
-            // Dispatch to the IME before propagating down the view hierarchy.
-            result = dispatchImeInputEvent(q);
-        }
-        return result;
-    }
-
-    private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
-        final MotionEvent event = (MotionEvent) q.mEvent;
-        final int source = event.getSource();
-        final boolean isJoystick = event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK);
-        final boolean isTouchNavigation = event.isFromSource(InputDevice.SOURCE_TOUCH_NAVIGATION);
-
-        // If there is no view, then the event will not be handled.
-        if (mView == null || !mAdded) {
-            if (isJoystick) {
-                updateJoystickDirection(event, false);
-            } else if (isTouchNavigation) {
-                mSimulatedDpad.updateTouchNavigation(this, event, false);
-            }
-            return EVENT_NOT_HANDLED;
-        }
-
-        // Deliver the event to the view.
-        if (mView.dispatchGenericMotionEvent(event)) {
-            if (isJoystick) {
-                updateJoystickDirection(event, false);
-            } else if (isTouchNavigation) {
-                mSimulatedDpad.updateTouchNavigation(this, event, false);
-            }
-            return EVENT_HANDLED;
-        }
-
-        if (isJoystick) {
-            // Translate the joystick event into DPAD keys and try to deliver
-            // those.
+        private int processJoystickEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
             updateJoystickDirection(event, true);
-            return EVENT_HANDLED;
-        }
-        if (isTouchNavigation) {
-            mSimulatedDpad.updateTouchNavigation(this, event, true);
-            return EVENT_HANDLED;
-        }
-        return EVENT_NOT_HANDLED;
-    }
-
-    private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
-        final long time = event.getEventTime();
-        final int metaState = event.getMetaState();
-        final int deviceId = event.getDeviceId();
-        final int source = event.getSource();
-
-        int xDirection = joystickAxisValueToDirection(event.getAxisValue(MotionEvent.AXIS_HAT_X));
-        if (xDirection == 0) {
-            xDirection = joystickAxisValueToDirection(event.getX());
+            return FINISH_HANDLED;
         }
 
-        int yDirection = joystickAxisValueToDirection(event.getAxisValue(MotionEvent.AXIS_HAT_Y));
-        if (yDirection == 0) {
-            yDirection = joystickAxisValueToDirection(event.getY());
+        private void cancelJoystickEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+            updateJoystickDirection(event, false);
         }
 
-        if (xDirection != mLastJoystickXDirection) {
-            if (mLastJoystickXKeyCode != 0) {
-                mHandler.removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
-                enqueueInputEvent(new KeyEvent(time, time,
-                        KeyEvent.ACTION_UP, mLastJoystickXKeyCode, 0, metaState,
-                        deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
-                mLastJoystickXKeyCode = 0;
+        private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
+            final long time = event.getEventTime();
+            final int metaState = event.getMetaState();
+            final int deviceId = event.getDeviceId();
+            final int source = event.getSource();
+
+            int xDirection = joystickAxisValueToDirection(
+                    event.getAxisValue(MotionEvent.AXIS_HAT_X));
+            if (xDirection == 0) {
+                xDirection = joystickAxisValueToDirection(event.getX());
             }
 
-            mLastJoystickXDirection = xDirection;
+            int yDirection = joystickAxisValueToDirection(
+                    event.getAxisValue(MotionEvent.AXIS_HAT_Y));
+            if (yDirection == 0) {
+                yDirection = joystickAxisValueToDirection(event.getY());
+            }
 
-            if (xDirection != 0 && synthesizeNewKeys) {
-                mLastJoystickXKeyCode = xDirection > 0
-                        ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
-                final KeyEvent e = new KeyEvent(time, time,
-                        KeyEvent.ACTION_DOWN, mLastJoystickXKeyCode, 0, metaState,
-                        deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
-                enqueueInputEvent(e);
-                Message m = mHandler.obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
-                m.setAsynchronous(true);
-                mHandler.sendMessageDelayed(m, mViewConfiguration.getKeyRepeatTimeout());
+            if (xDirection != mLastJoystickXDirection) {
+                if (mLastJoystickXKeyCode != 0) {
+                    mHandler.removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
+                    enqueueInputEvent(new KeyEvent(time, time,
+                            KeyEvent.ACTION_UP, mLastJoystickXKeyCode, 0, metaState,
+                            deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
+                    mLastJoystickXKeyCode = 0;
+                }
+
+                mLastJoystickXDirection = xDirection;
+
+                if (xDirection != 0 && synthesizeNewKeys) {
+                    mLastJoystickXKeyCode = xDirection > 0
+                            ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
+                    final KeyEvent e = new KeyEvent(time, time,
+                            KeyEvent.ACTION_DOWN, mLastJoystickXKeyCode, 0, metaState,
+                            deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
+                    enqueueInputEvent(e);
+                    Message m = mHandler.obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
+                    m.setAsynchronous(true);
+                    mHandler.sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
+                }
+            }
+
+            if (yDirection != mLastJoystickYDirection) {
+                if (mLastJoystickYKeyCode != 0) {
+                    mHandler.removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
+                    enqueueInputEvent(new KeyEvent(time, time,
+                            KeyEvent.ACTION_UP, mLastJoystickYKeyCode, 0, metaState,
+                            deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
+                    mLastJoystickYKeyCode = 0;
+                }
+
+                mLastJoystickYDirection = yDirection;
+
+                if (yDirection != 0 && synthesizeNewKeys) {
+                    mLastJoystickYKeyCode = yDirection > 0
+                            ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
+                    final KeyEvent e = new KeyEvent(time, time,
+                            KeyEvent.ACTION_DOWN, mLastJoystickYKeyCode, 0, metaState,
+                            deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
+                    enqueueInputEvent(e);
+                    Message m = mHandler.obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
+                    m.setAsynchronous(true);
+                    mHandler.sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
+                }
             }
         }
 
-        if (yDirection != mLastJoystickYDirection) {
-            if (mLastJoystickYKeyCode != 0) {
-                mHandler.removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
-                enqueueInputEvent(new KeyEvent(time, time,
-                        KeyEvent.ACTION_UP, mLastJoystickYKeyCode, 0, metaState,
-                        deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
-                mLastJoystickYKeyCode = 0;
-            }
-
-            mLastJoystickYDirection = yDirection;
-
-            if (yDirection != 0 && synthesizeNewKeys) {
-                mLastJoystickYKeyCode = yDirection > 0
-                        ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
-                final KeyEvent e = new KeyEvent(time, time,
-                        KeyEvent.ACTION_DOWN, mLastJoystickYKeyCode, 0, metaState,
-                        deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
-                enqueueInputEvent(e);
-                Message m = mHandler.obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
-                m.setAsynchronous(true);
-                mHandler.sendMessageDelayed(m, mViewConfiguration.getKeyRepeatTimeout());
+        private int joystickAxisValueToDirection(float value) {
+            if (value >= 0.5f) {
+                return 1;
+            } else if (value <= -0.5f) {
+                return -1;
+            } else {
+                return 0;
             }
         }
-    }
 
-    private static int joystickAxisValueToDirection(float value) {
-        if (value >= 0.5f) {
-            return 1;
-        } else if (value <= -0.5f) {
-            return -1;
-        } else {
-            return 0;
+        private int processTouchNavigationEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+            mSimulatedDpad.updateTouchNavigation(ViewRootImpl.this, event, true);
+            return FINISH_HANDLED;
+        }
+
+        private void cancelTouchNavigationEvent(QueuedInputEvent q) {
+            final MotionEvent event = (MotionEvent)q.mEvent;
+            mSimulatedDpad.updateTouchNavigation(ViewRootImpl.this, event, false);
         }
     }
 
@@ -3803,136 +4229,6 @@
         return false;
     }
 
-    private int deliverKeyEvent(QueuedInputEvent q) {
-        final KeyEvent event = (KeyEvent)q.mEvent;
-        if (mInputEventConsistencyVerifier != null) {
-            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
-        }
-
-        int result = EVENT_POST_IME;
-        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
-            if (LOCAL_LOGV) Log.v(TAG, "Dispatching key " + event + " to " + mView);
-
-            // Perform predispatching before the IME.
-            if (mView.dispatchKeyEventPreIme(event)) {
-                return EVENT_HANDLED;
-            }
-
-            // Dispatch to the IME before propagating down the view hierarchy.
-            result = dispatchImeInputEvent(q);
-        }
-        return result;
-    }
-
-    private int deliverKeyEventPostIme(QueuedInputEvent q) {
-        final KeyEvent event = (KeyEvent)q.mEvent;
-
-        // If the view went away, then the event will not be handled.
-        if (mView == null || !mAdded) {
-            return EVENT_NOT_HANDLED;
-        }
-
-        // If the key's purpose is to exit touch mode then we consume it and consider it handled.
-        if (checkForLeavingTouchModeAndConsume(event)) {
-            return EVENT_HANDLED;
-        }
-
-        // Make sure the fallback event policy sees all keys that will be delivered to the
-        // view hierarchy.
-        mFallbackEventHandler.preDispatchKeyEvent(event);
-
-        // Deliver the key to the view hierarchy.
-        if (mView.dispatchKeyEvent(event)) {
-            return EVENT_HANDLED;
-        }
-
-        // If the Control modifier is held, try to interpret the key as a shortcut.
-        if (event.getAction() == KeyEvent.ACTION_DOWN
-                && event.isCtrlPressed()
-                && event.getRepeatCount() == 0
-                && !KeyEvent.isModifierKey(event.getKeyCode())) {
-            if (mView.dispatchKeyShortcutEvent(event)) {
-                return EVENT_HANDLED;
-            }
-        }
-
-        // Apply the fallback event policy.
-        if (mFallbackEventHandler.dispatchKeyEvent(event)) {
-            return EVENT_HANDLED;
-        }
-
-        // Handle automatic focus changes.
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            int direction = 0;
-            switch (event.getKeyCode()) {
-                case KeyEvent.KEYCODE_DPAD_LEFT:
-                    if (event.hasNoModifiers()) {
-                        direction = View.FOCUS_LEFT;
-                    }
-                    break;
-                case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    if (event.hasNoModifiers()) {
-                        direction = View.FOCUS_RIGHT;
-                    }
-                    break;
-                case KeyEvent.KEYCODE_DPAD_UP:
-                    if (event.hasNoModifiers()) {
-                        direction = View.FOCUS_UP;
-                    }
-                    break;
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                    if (event.hasNoModifiers()) {
-                        direction = View.FOCUS_DOWN;
-                    }
-                    break;
-                case KeyEvent.KEYCODE_TAB:
-                    if (event.hasNoModifiers()) {
-                        direction = View.FOCUS_FORWARD;
-                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                        direction = View.FOCUS_BACKWARD;
-                    }
-                    break;
-            }
-            if (direction != 0) {
-                View focused = mView.findFocus();
-                if (focused != null) {
-                    View v = focused.focusSearch(direction);
-                    if (v != null && v != focused) {
-                        // do the math the get the interesting rect
-                        // of previous focused into the coord system of
-                        // newly focused view
-                        focused.getFocusedRect(mTempRect);
-                        if (mView instanceof ViewGroup) {
-                            ((ViewGroup) mView).offsetDescendantRectToMyCoords(
-                                    focused, mTempRect);
-                            ((ViewGroup) mView).offsetRectIntoDescendantCoords(
-                                    v, mTempRect);
-                        }
-                        if (v.requestFocus(direction, mTempRect)) {
-                            playSoundEffect(SoundEffectConstants
-                                    .getContantForFocusDirection(direction));
-                            return EVENT_HANDLED;
-                        }
-                    }
-
-                    // Give the focused view a last chance to handle the dpad key.
-                    if (mView.dispatchUnhandledMove(focused, direction)) {
-                        return EVENT_HANDLED;
-                    }
-                } else {
-                    // find the best view to give focus to in this non-touch-mode with no-focus
-                    View v = focusSearch(null, direction);
-                    if (v != null && v.requestFocus(direction)) {
-                        return EVENT_HANDLED;
-                    }
-                }
-            }
-        }
-
-        // Key was unhandled.
-        return EVENT_NOT_HANDLED;
-    }
-
     /* drag/drop */
     void setLocalDragState(Object obj) {
         mLocalDragState = obj;
@@ -4364,13 +4660,25 @@
      * needing a queue on the application's side.
      */
     private static final class QueuedInputEvent {
-        public static final int FLAG_DELIVER_POST_IME = 1;
+        public static final int FLAG_DELIVER_POST_IME = 1 << 0;
+        public static final int FLAG_DEFERRED = 1 << 1;
+        public static final int FLAG_FINISHED = 1 << 2;
+        public static final int FLAG_FINISHED_HANDLED = 1 << 3;
+        public static final int FLAG_RESYNTHESIZED = 1 << 4;
 
         public QueuedInputEvent mNext;
 
         public InputEvent mEvent;
         public InputEventReceiver mReceiver;
         public int mFlags;
+
+        public boolean shouldSkipIme() {
+            if ((mFlags & FLAG_DELIVER_POST_IME) != 0) {
+                return true;
+            }
+            return mEvent instanceof MotionEvent
+                    && mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
+        }
     }
 
     private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
@@ -4443,14 +4751,7 @@
     }
 
     void doProcessInputEvents() {
-        // Handle all of the available pending input events. Currently this will immediately
-        // process all of the events it can until it encounters one that must go through the IME.
-        // After that it will continue adding events to the active input queue but will wait for a
-        // response from the IME, regardless of whether that particular event needs it or not, in
-        // order to guarantee ordering consistency. This could be slightly improved by only
-        // queueing events whose source has previously encountered something that needs to be
-        // handled by the IME, and otherwise handling them immediately since we only need to
-        // guarantee ordering within a given source.
+        // Deliver all pending input events in the queue.
         while (mPendingInputEventHead != null) {
             QueuedInputEvent q = mPendingInputEventHead;
             mPendingInputEventHead = q.mNext;
@@ -4463,25 +4764,7 @@
             Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                     mPendingInputEventCount);
 
-            int result = deliverInputEvent(q);
-
-            if (result == EVENT_HANDLED || result == EVENT_NOT_HANDLED) {
-                finishInputEvent(q, result == EVENT_HANDLED);
-            } else if (result == EVENT_PENDING_IME) {
-                enqueueActiveInputEvent(q);
-            } else {
-                q.mFlags |= QueuedInputEvent.FLAG_DELIVER_POST_IME;
-                // If the IME decided not to handle this event, and we have no events already being
-                // handled by the IME, go ahead and handle this one and then continue to the next
-                // input event. Otherwise, queue it up and handle it after whatever in front of it
-                // in the queue has been handled.
-                if (mActiveInputEventHead == null) {
-                    result = deliverInputEventPostIme(q);
-                    finishInputEvent(q, result == EVENT_HANDLED);
-                } else {
-                    enqueueActiveInputEvent(q);
-                }
-            }
+            deliverInputEvent(q);
         }
 
         // We are done processing all input events that we can process right now
@@ -4492,114 +4775,27 @@
         }
     }
 
-    private void enqueueActiveInputEvent(QueuedInputEvent q) {
-        if (mActiveInputEventHead == null) {
-            mActiveInputEventHead = q;
-            mActiveInputEventTail = q;
-        } else {
-            mActiveInputEventTail.mNext = q;
-            mActiveInputEventTail = q;
-        }
-        mActiveInputEventCount += 1;
-        Trace.traceCounter(Trace.TRACE_TAG_INPUT, mActiveInputEventQueueLengthCounterName,
-                mActiveInputEventCount);
-    }
+    private void deliverInputEvent(QueuedInputEvent q) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
+        try {
+            if (mInputEventConsistencyVerifier != null) {
+                mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
+            }
 
-    private QueuedInputEvent dequeueActiveInputEvent() {
-        return dequeueActiveInputEvent(mActiveInputEventHead);
-    }
-
-
-    private QueuedInputEvent dequeueActiveInputEvent(QueuedInputEvent q) {
-        QueuedInputEvent curr = mActiveInputEventHead;
-        QueuedInputEvent prev = null;
-        while (curr != null && curr != q) {
-            prev = curr;
-            curr = curr.mNext;
-        }
-        if (curr != null) {
-            if (mActiveInputEventHead == curr) {
-                mActiveInputEventHead = curr.mNext;
+            InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
+            if (stage != null) {
+                stage.deliver(q);
             } else {
-                prev.mNext = curr.mNext;
+                finishInputEvent(q);
             }
-            if (mActiveInputEventTail == curr) {
-                mActiveInputEventTail = prev;
-            }
-            curr.mNext = null;
-
-            mActiveInputEventCount -= 1;
-            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mActiveInputEventQueueLengthCounterName,
-                    mActiveInputEventCount);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
-        return curr;
     }
 
-    private QueuedInputEvent findActiveInputEvent(int seq) {
-        QueuedInputEvent q = mActiveInputEventHead;
-        while (q != null && q.mEvent.getSequenceNumber() != seq) {
-            q = q.mNext;
-        }
-        return q;
-    }
-
-    int dispatchImeInputEvent(QueuedInputEvent q) {
-        if (mLastWasImTarget) {
-            InputMethodManager imm = InputMethodManager.peekInstance();
-            if (imm != null) {
-                final InputEvent event = q.mEvent;
-                final int seq = event.getSequenceNumber();
-                if (DEBUG_IMF)
-                    Log.v(TAG, "Sending input event to IME: seq=" + seq + " event=" + event);
-                return imm.dispatchInputEvent(mView.getContext(), seq, event,
-                        mInputMethodCallback);
-            }
-        }
-        return EVENT_POST_IME;
-    }
-
-    void handleImeFinishedEvent(int seq, boolean handled) {
-        QueuedInputEvent q = findActiveInputEvent(seq);
-        if (q != null) {
-            if (DEBUG_IMF) {
-                Log.v(TAG, "IME finished event: seq=" + seq
-                        + " handled=" + handled + " event=" + q);
-            }
-
-            if (handled) {
-                dequeueActiveInputEvent(q);
-                finishInputEvent(q, true);
-            } else {
-                q.mFlags |= QueuedInputEvent.FLAG_DELIVER_POST_IME;
-            }
-
-
-            // Flush all of the input events that are no longer waiting on the IME
-            while (mActiveInputEventHead != null && (mActiveInputEventHead.mFlags &
-                        QueuedInputEvent.FLAG_DELIVER_POST_IME) != 0) {
-                q = dequeueActiveInputEvent();
-                // If the window doesn't currently have input focus, then drop
-                // this event.  This could be an event that came back from the
-                // IME dispatch but the window has lost focus in the meantime.
-                handled = false;
-                if (!mAttachInfo.mHasWindowFocus && !isTerminalInputEvent(q.mEvent)) {
-                    Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
-                } else {
-                    handled = (deliverInputEventPostIme(q) == EVENT_HANDLED);
-                }
-                finishInputEvent(q, handled);
-            }
-        } else {
-            if (DEBUG_IMF) {
-                Log.v(TAG, "IME finished event: seq=" + seq
-                        + " handled=" + handled + ", event not found!");
-            }
-        }
-
-    }
-
-    private void finishInputEvent(QueuedInputEvent q, boolean handled) {
+    private void finishInputEvent(QueuedInputEvent q) {
         if (q.mReceiver != null) {
+            boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
             q.mReceiver.finishInputEvent(q.mEvent, handled);
         } else {
             q.mEvent.recycleIfNeededAfterDispatch();
@@ -4608,7 +4804,7 @@
         recycleQueuedInputEvent(q);
     }
 
-    private static boolean isTerminalInputEvent(InputEvent event) {
+    static boolean isTerminalInputEvent(InputEvent event) {
         if (event instanceof KeyEvent) {
             final KeyEvent keyEvent = (KeyEvent)event;
             return keyEvent.getAction() == KeyEvent.ACTION_UP;
@@ -5144,22 +5340,6 @@
             ((RootViewSurfaceTaker)mView).setSurfaceKeepScreenOn(screenOn);
         }
     }
-    
-    static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
-        private WeakReference<ViewRootImpl> mViewAncestor;
-
-        public InputMethodCallback(ViewRootImpl viewAncestor) {
-            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
-        }
-
-        @Override
-        public void finishedEvent(int seq, boolean handled) {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.handleImeFinishedEvent(seq, handled);
-            }
-        }
-    }
 
     static class W extends IWindow.Stub {
         private final WeakReference<ViewRootImpl> mViewAncestor;
@@ -5332,8 +5512,11 @@
          */
         static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
 
+        static final float FIRST_MOVEMENT_THRESHOLD = 0.5f;
+        static final float SECOND_CUMULATIVE_MOVEMENT_THRESHOLD = 2.0f;
+        static final float SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD = 1.0f;
+
         float position;
-        float absPosition;
         float acceleration = 1;
         long lastMoveTime = 0;
         int step;
@@ -5410,21 +5593,18 @@
                 }
             }
             position += off;
-            return (absPosition = Math.abs(position));
+            return Math.abs(position);
         }
 
         /**
          * Generate the number of discrete movement events appropriate for
          * the currently collected trackball movement.
          *
-         * @param precision The minimum movement required to generate the
-         * first discrete movement.
-         *
          * @return Returns the number of discrete movements, either positive
          * or negative, or 0 if there is not enough trackball movement yet
          * for a discrete movement.
          */
-        int generate(float precision) {
+        int generate() {
             int movement = 0;
             nonAccelMovement = 0;
             do {
@@ -5434,7 +5614,7 @@
                     // to do this as soon as possible instead of waiting for
                     // a full movement, in order to make things look responsive.
                     case 0:
-                        if (absPosition < precision) {
+                        if (Math.abs(position) < FIRST_MOVEMENT_THRESHOLD) {
                             return movement;
                         }
                         movement += dir;
@@ -5445,13 +5625,12 @@
                     // to wait for the second complete trackball motion before
                     // generating the second discrete movement.
                     case 1:
-                        if (absPosition < 2) {
+                        if (Math.abs(position) < SECOND_CUMULATIVE_MOVEMENT_THRESHOLD) {
                             return movement;
                         }
                         movement += dir;
                         nonAccelMovement += dir;
-                        position += dir > 0 ? -2 : 2;
-                        absPosition = Math.abs(position);
+                        position -= SECOND_CUMULATIVE_MOVEMENT_THRESHOLD * dir;
                         step = 2;
                         break;
                     // After the first two, we generate discrete movements
@@ -5462,12 +5641,11 @@
                     // a longer increasing acceleration to continuous movement
                     // in one direction.
                     default:
-                        if (absPosition < 1) {
+                        if (Math.abs(position) < SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD) {
                             return movement;
                         }
                         movement += dir;
-                        position += dir >= 0 ? -1 : 1;
-                        absPosition = Math.abs(position);
+                        position -= dir * SUBSEQUENT_INCREMENTAL_MOVEMENT_THRESHOLD;
                         float acc = acceleration;
                         acc *= 1.1f;
                         acceleration = acc < MAX_ACCELERATION ? acc : acceleration;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7eb26fa..0ff46e9 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -136,11 +136,11 @@
         }
     }
 
-    public static IWindowSession getWindowSession(Looper mainLooper) {
+    public static IWindowSession getWindowSession() {
         synchronized (WindowManagerGlobal.class) {
             if (sWindowSession == null) {
                 try {
-                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
+                    InputMethodManager imm = InputMethodManager.getInstance();
                     IWindowManager windowManager = getWindowManagerService();
                     sWindowSession = windowManager.openSession(
                             imm.getClient(), imm.getInputContext());
@@ -351,7 +351,7 @@
         View view = root.getView();
 
         if (view != null) {
-            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+            InputMethodManager imm = InputMethodManager.getInstance();
             if (imm != null) {
                 imm.windowDismissed(mViews[index].getWindowToken());
             }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 855b6d4..4df4734 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -34,9 +34,11 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.SystemClock;
+import android.os.Trace;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
+import android.util.Pools.Pool;
+import android.util.Pools.SimplePool;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.view.InputChannel;
@@ -45,6 +47,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
+import android.util.SparseArray;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -200,8 +203,9 @@
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManager";
 
-    static final Object mInstanceSync = new Object();
-    static InputMethodManager mInstance;
+    static final String PENDING_EVENT_COUNTER = "aq:imm";
+
+    static InputMethodManager sInstance;
 
     /**
      * @hide Flag for IInputMethodManager.windowGainedFocus: a view in
@@ -232,7 +236,14 @@
      */
     static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
 
-    private static final int MAX_PENDING_EVENT_POOL_SIZE = 4;
+    /** @hide */
+    public static final int DISPATCH_IN_PROGRESS = -1;
+
+    /** @hide */
+    public static final int DISPATCH_NOT_HANDLED = 0;
+
+    /** @hide */
+    public static final int DISPATCH_HANDLED = 1;
 
     final IInputMethodManager mService;
     final Looper mMainLooper;
@@ -323,10 +334,8 @@
     InputChannel mCurChannel;
     ImeInputEventSender mCurSender;
 
-    PendingEvent mPendingEventPool;
-    int mPendingEventPoolSize;
-    PendingEvent mPendingEventHead;
-    PendingEvent mPendingEventTail;
+    final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
+    final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
 
     // -----------------------------------------------------------
     
@@ -334,8 +343,10 @@
     static final int MSG_BIND = 2;
     static final int MSG_UNBIND = 3;
     static final int MSG_SET_ACTIVE = 4;
-    static final int MSG_EVENT_TIMEOUT = 5;
-    
+    static final int MSG_SEND_INPUT_EVENT = 5;
+    static final int MSG_TIMEOUT_INPUT_EVENT = 6;
+    static final int MSG_FLUSH_INPUT_EVENT = 7;
+
     class H extends Handler {
         H(Looper looper) {
             super(looper, null, true);
@@ -453,15 +464,16 @@
                     }
                     return;
                 }
-                case MSG_EVENT_TIMEOUT: {
-                    // Even though the message contains both the sequence number
-                    // and the PendingEvent object itself, we only pass the
-                    // sequence number to the timeoutEvent function because it's
-                    // possible for the PendingEvent object to be dequeued and
-                    // recycled concurrently.  To avoid a possible race, we make
-                    // a point of always looking up the PendingEvent within the
-                    // queue given only the sequence number of the event.
-                    timeoutEvent(msg.arg1);
+                case MSG_SEND_INPUT_EVENT: {
+                    sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
+                    return;
+                }
+                case MSG_TIMEOUT_INPUT_EVENT: {
+                    finishedInputEvent(msg.arg1, false, true);
+                    return;
+                }
+                case MSG_FLUSH_INPUT_EVENT: {
+                    finishedInputEvent(msg.arg1, false, false);
                     return;
                 }
             }
@@ -538,10 +550,6 @@
         mH = new H(looper);
         mIInputContext = new ControlledInputConnectionWrapper(looper,
                 mDummyInputConnection, this);
-        
-        if (mInstance == null) {
-            mInstance = this;
-        }
     }
 
     /**
@@ -549,25 +557,15 @@
      * doesn't already exist.
      * @hide
      */
-    static public InputMethodManager getInstance(Context context) {
-        return getInstance(context.getMainLooper());
-    }
-    
-    /**
-     * Internally, the input method manager can't be context-dependent, so
-     * we have this here for the places that need it.
-     * @hide
-     */
-    static public InputMethodManager getInstance(Looper mainLooper) {
-        synchronized (mInstanceSync) {
-            if (mInstance != null) {
-                return mInstance;
+    public static InputMethodManager getInstance() {
+        synchronized (InputMethodManager.class) {
+            if (sInstance == null) {
+                IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
+                IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
+                sInstance = new InputMethodManager(service, Looper.getMainLooper());
             }
-            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
-            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
-            mInstance = new InputMethodManager(service, mainLooper);
+            return sInstance;
         }
-        return mInstance;
     }
     
     /**
@@ -575,8 +573,8 @@
      * if it exists.
      * @hide
      */
-    static public InputMethodManager peekInstance() {
-        return mInstance;
+    public static InputMethodManager peekInstance() {
+        return sInstance;
     }
     
     /** @hide */
@@ -1585,13 +1583,18 @@
     }
 
     /**
+     * Dispatches an input event to the IME.
+     *
+     * Returns {@link #DISPATCH_HANDLED} if the event was handled.
+     * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
+     * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
+     * callback will be invoked later.
+     *
      * @hide
      */
-    public int dispatchInputEvent(Context context, int seq, InputEvent event,
-            FinishedEventCallback callback) {
+    public int dispatchInputEvent(InputEvent event, Object token,
+            FinishedInputEventCallback callback, Handler handler) {
         synchronized (mH) {
-            if (DEBUG) Log.d(TAG, "dispatchInputEvent");
-
             if (mCurMethod != null) {
                 if (event instanceof KeyEvent) {
                     KeyEvent keyEvent = (KeyEvent)event;
@@ -1599,144 +1602,140 @@
                             && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
                             && keyEvent.getRepeatCount() == 0) {
                         showInputMethodPickerLocked();
-                        return ViewRootImpl.EVENT_HANDLED;
+                        return DISPATCH_HANDLED;
                     }
                 }
 
                 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
-                final long startTime = SystemClock.uptimeMillis();
-                if (mCurChannel != null) {
-                    if (mCurSender == null) {
-                        mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
-                    }
-                    if (mCurSender.sendInputEvent(seq, event)) {
-                        enqueuePendingEventLocked(startTime, seq, mCurId, callback);
-                        return ViewRootImpl.EVENT_PENDING_IME;
-                    } else {
-                        Log.w(TAG, "Unable to send input event to IME: "
-                                + mCurId + " dropping: " + event);
-                    }
+
+                PendingEvent p = obtainPendingEventLocked(
+                        event, token, mCurId, callback, handler);
+                if (mMainLooper.isCurrentThread()) {
+                    // Already running on the IMM thread so we can send the event immediately.
+                    return sendInputEventOnMainLooperLocked(p);
                 }
+
+                // Post the event to the IMM thread.
+                Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
+                msg.setAsynchronous(true);
+                mH.sendMessage(msg);
+                return DISPATCH_IN_PROGRESS;
             }
         }
-        return ViewRootImpl.EVENT_POST_IME;
+        return DISPATCH_NOT_HANDLED;
     }
 
-    void finishedEvent(int seq, boolean handled) {
-        final FinishedEventCallback callback;
+    // Must be called on the main looper
+    void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
+        final boolean handled;
         synchronized (mH) {
-            PendingEvent p = dequeuePendingEventLocked(seq);
-            if (p == null) {
+            int result = sendInputEventOnMainLooperLocked(p);
+            if (result == DISPATCH_IN_PROGRESS) {
+                return;
+            }
+
+            handled = (result == DISPATCH_HANDLED);
+        }
+
+        invokeFinishedInputEventCallback(p, handled);
+    }
+
+    // Must be called on the main looper
+    int sendInputEventOnMainLooperLocked(PendingEvent p) {
+        if (mCurChannel != null) {
+            if (mCurSender == null) {
+                mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
+            }
+
+            final InputEvent event = p.mEvent;
+            final int seq = event.getSequenceNumber();
+            if (mCurSender.sendInputEvent(seq, event)) {
+                mPendingEvents.put(seq, p);
+                Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
+                        mPendingEvents.size());
+
+                Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, p);
+                msg.setAsynchronous(true);
+                mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
+                return DISPATCH_IN_PROGRESS;
+            }
+
+            Log.w(TAG, "Unable to send input event to IME: "
+                    + mCurId + " dropping: " + event);
+        }
+        return DISPATCH_NOT_HANDLED;
+    }
+
+    void finishedInputEvent(int seq, boolean handled, boolean timeout) {
+        final PendingEvent p;
+        synchronized (mH) {
+            int index = mPendingEvents.indexOfKey(seq);
+            if (index < 0) {
                 return; // spurious, event already finished or timed out
             }
-            mH.removeMessages(MSG_EVENT_TIMEOUT, p);
-            callback = p.mCallback;
-            recyclePendingEventLocked(p);
-        }
-        callback.finishedEvent(seq, handled);
-    }
 
-    void timeoutEvent(int seq) {
-        final FinishedEventCallback callback;
-        synchronized (mH) {
-            PendingEvent p = dequeuePendingEventLocked(seq);
-            if (p == null) {
-                return; // spurious, event already finished or timed out
-            }
-            long delay = SystemClock.uptimeMillis() - p.mStartTime;
-            Log.w(TAG, "Timeout waiting for IME to handle input event after "
-                    + delay + "ms: " + p.mInputMethodId);
-            callback = p.mCallback;
-            recyclePendingEventLocked(p);
-        }
-        callback.finishedEvent(seq, false);
-    }
+            p = mPendingEvents.valueAt(index);
+            mPendingEvents.removeAt(index);
+            Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
 
-    private void enqueuePendingEventLocked(
-            long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
-        PendingEvent p = obtainPendingEventLocked(startTime, seq, inputMethodId, callback);
-        if (mPendingEventTail != null) {
-            mPendingEventTail.mNext = p;
-            mPendingEventTail = p;
-        } else {
-            mPendingEventHead = p;
-            mPendingEventTail = p;
-        }
-
-        Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, seq, 0, p);
-        msg.setAsynchronous(true);
-        mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
-    }
-
-    private PendingEvent dequeuePendingEventLocked(int seq) {
-        PendingEvent p = mPendingEventHead;
-        if (p == null) {
-            return null;
-        }
-        if (p.mSeq == seq) {
-            mPendingEventHead = p.mNext;
-            if (mPendingEventHead == null) {
-                mPendingEventTail = null;
-            }
-        } else {
-            PendingEvent prev;
-            do {
-                prev = p;
-                p = p.mNext;
-                if (p == null) {
-                    return null;
-                }
-            } while (p.mSeq != seq);
-            prev.mNext = p.mNext;
-            if (mPendingEventTail == p) {
-                mPendingEventTail = prev;
+            if (timeout) {
+                Log.w(TAG, "Timeout waiting for IME to handle input event after "
+                        + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
+            } else {
+                mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
             }
         }
-        p.mNext = null;
-        return p;
+
+        invokeFinishedInputEventCallback(p, handled);
     }
 
-    private PendingEvent obtainPendingEventLocked(
-            long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
-        PendingEvent p = mPendingEventPool;
-        if (p != null) {
-            mPendingEventPoolSize -= 1;
-            mPendingEventPool = p.mNext;
-            p.mNext = null;
+    // Assumes the event has already been removed from the queue.
+    void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
+        p.mHandled = handled;
+        if (p.mHandler.getLooper().isCurrentThread()) {
+            // Already running on the callback handler thread so we can send the
+            // callback immediately.
+            p.run();
         } else {
-            p = new PendingEvent();
-        }
-
-        p.mStartTime = startTime;
-        p.mSeq = seq;
-        p.mInputMethodId = inputMethodId;
-        p.mCallback = callback;
-        return p;
-    }
-
-    private void recyclePendingEventLocked(PendingEvent p) {
-        p.mInputMethodId = null;
-        p.mCallback = null;
-
-        if (mPendingEventPoolSize < MAX_PENDING_EVENT_POOL_SIZE) {
-            mPendingEventPoolSize += 1;
-            p.mNext = mPendingEventPool;
-            mPendingEventPool = p;
+            // Post the event to the callback handler thread.
+            // In this case, the callback will be responsible for recycling the event.
+            Message msg = Message.obtain(p.mHandler, p);
+            msg.setAsynchronous(true);
+            msg.sendToTarget();
         }
     }
 
     private void flushPendingEventsLocked() {
-        mH.removeMessages(MSG_EVENT_TIMEOUT);
+        mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
 
-        PendingEvent p = mPendingEventHead;
-        while (p != null) {
-            Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, p.mSeq, 0, p);
+        final int count = mPendingEvents.size();
+        for (int i = 0; i < count; i++) {
+            int seq = mPendingEvents.keyAt(i);
+            Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
             msg.setAsynchronous(true);
-            mH.sendMessage(msg);
-            p = p.mNext;
+            msg.sendToTarget();
         }
     }
 
+    private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
+            String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
+        PendingEvent p = mPendingEventPool.acquire();
+        if (p == null) {
+            p = new PendingEvent();
+        }
+        p.mEvent = event;
+        p.mToken = token;
+        p.mInputMethodId = inputMethodId;
+        p.mCallback = callback;
+        p.mHandler = handler;
+        return p;
+    }
+
+    private void recyclePendingEventLocked(PendingEvent p) {
+        p.recycle();
+        mPendingEventPool.release(p);
+    }
+
     public void showInputMethodPicker() {
         synchronized (mH) {
             showInputMethodPickerLocked();
@@ -1946,8 +1945,8 @@
      * the IME has been finished.
      * @hide
      */
-    public interface FinishedEventCallback {
-        public void finishedEvent(int seq, boolean handled);
+    public interface FinishedInputEventCallback {
+        public void onFinishedInputEvent(Object token, boolean handled);
     }
 
     private final class ImeInputEventSender extends InputEventSender {
@@ -1957,16 +1956,34 @@
 
         @Override
         public void onInputEventFinished(int seq, boolean handled) {
-            finishedEvent(seq, handled);
+            finishedInputEvent(seq, handled, false);
         }
     }
 
-    private static final class PendingEvent {
-        public PendingEvent mNext;
-
-        public long mStartTime;
-        public int mSeq;
+    private final class PendingEvent implements Runnable {
+        public InputEvent mEvent;
+        public Object mToken;
         public String mInputMethodId;
-        public FinishedEventCallback mCallback;
+        public FinishedInputEventCallback mCallback;
+        public Handler mHandler;
+        public boolean mHandled;
+
+        public void recycle() {
+            mEvent = null;
+            mToken = null;
+            mInputMethodId = null;
+            mCallback = null;
+            mHandler = null;
+            mHandled = false;
+        }
+
+        @Override
+        public void run() {
+            mCallback.onFinishedInputEvent(mToken, mHandled);
+
+            synchronized (mH) {
+                recyclePendingEventLocked(this);
+            }
+        }
     }
 }
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index 684ec07..17eb2df 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -84,6 +85,7 @@
     // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
     private Timer mTimer;
     private final class TimeupdateTask extends TimerTask {
+        @Override
         public void run() {
             HTML5Audio.this.obtainMessage(TIMEUPDATE).sendToTarget();
         }
@@ -139,11 +141,13 @@
     // (i.e. the webviewcore thread here)
 
     // MediaPlayer.OnBufferingUpdateListener
+    @Override
     public void onBufferingUpdate(MediaPlayer mp, int percent) {
         nativeOnBuffering(percent, mNativePointer);
     }
 
     // MediaPlayer.OnCompletionListener;
+    @Override
     public void onCompletion(MediaPlayer mp) {
         mState = COMPLETE;
         mProcessingOnEnd = true;
@@ -156,6 +160,7 @@
     }
 
     // MediaPlayer.OnErrorListener
+    @Override
     public boolean onError(MediaPlayer mp, int what, int extra) {
         mState = ERROR;
         resetMediaPlayer();
@@ -164,6 +169,7 @@
     }
 
     // MediaPlayer.OnPreparedListener
+    @Override
     public void onPrepared(MediaPlayer mp) {
         mState = PREPARED;
         if (mTimer != null) {
@@ -178,6 +184,7 @@
     }
 
     // MediaPlayer.OnSeekCompleteListener
+    @Override
     public void onSeekComplete(MediaPlayer mp) {
         nativeOnTimeupdate(mp.getCurrentPosition(), mNativePointer);
     }
@@ -231,7 +238,7 @@
                 headers.put(HIDE_URL_LOGS, "true");
             }
 
-            mMediaPlayer.setDataSource(url, headers);
+            mMediaPlayer.setDataSource(mContext, Uri.parse(url), headers);
             mState = INITIALIZED;
             mMediaPlayer.prepareAsync();
         } catch (IOException e) {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 18df0b1..00d87bd 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -25,8 +25,13 @@
 
 /**
  * Top level factory, used creating all the main WebView implementation classes.
+ *
+ * @hide
  */
-class WebViewFactory {
+public final class WebViewFactory {
+    public static final String WEBVIEW_EXPERIMENTAL_PROPERTY = "persist.sys.webview.exp";
+    private static final String DEPRECATED_CHROMIUM_PROPERTY = "webview.use_chromium";
+
     // Default Provider factory class name.
     // TODO: When the Chromium powered WebView is ready, it should be the default factory class.
     private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
@@ -43,16 +48,17 @@
     private static WebViewFactoryProvider sProviderInstance;
     private static final Object sProviderLock = new Object();
 
+    public static boolean isExperimentalWebViewAvailable() {
+        return Build.IS_DEBUGGABLE && (new java.io.File(CHROMIUM_WEBVIEW_JAR).exists());
+    }
+
     static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
             // us honest and minimize usage of WebViewClassic internals when binding the proxy.
             if (sProviderInstance != null) return sProviderInstance;
 
-            // For debug builds, we allow a system property to specify that we should use the
-            // Chromium powered WebView. This enables us to switch between implementations
-            // at runtime. For user (release) builds, don't allow this.
-            if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("webview.use_chromium", false)) {
+            if (isExperimentalWebViewEnabled()) {
                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                 try {
                     sProviderInstance = loadChromiumProvider();
@@ -76,6 +82,20 @@
         }
     }
 
+    // For debug builds, we allow a system property to specify that we should use the
+    // experimtanl Chromium powered WebView. This enables us to switch between
+    // implementations at runtime. For user (release) builds, don't allow this.
+    private static boolean isExperimentalWebViewEnabled() {
+        if (!isExperimentalWebViewAvailable())
+            return false;
+        if (SystemProperties.getBoolean(DEPRECATED_CHROMIUM_PROPERTY, false)) {
+            Log.w(LOGTAG, String.format("The property %s has been deprecated. Please use %s.",
+                    DEPRECATED_CHROMIUM_PROPERTY, WEBVIEW_EXPERIMENTAL_PROPERTY));
+            return true;
+        }
+        return SystemProperties.getBoolean(WEBVIEW_EXPERIMENTAL_PROPERTY, false);
+    }
+
     // TODO: This allows us to have the legacy and Chromium WebView coexist for development
     // and side-by-side testing. After transition, remove this when no longer required.
     private static WebViewFactoryProvider loadChromiumProvider() {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index b2073b1..34cfea5 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -20,6 +20,7 @@
 
 import android.app.AlertDialog;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -77,6 +78,7 @@
     private final PermissionInfoComparator mPermComparator = new PermissionInfoComparator();
     private final List<MyPermissionInfo> mPermsList = new ArrayList<MyPermissionInfo>();
     private final CharSequence mNewPermPrefix;
+    private String mPackageName;
 
     static class MyPermissionGroupInfo extends PermissionGroupInfo {
         CharSequence mLabel;
@@ -138,6 +140,8 @@
         MyPermissionGroupInfo mGroup;
         MyPermissionInfo mPerm;
         AlertDialog mDialog;
+        private boolean mShowRevokeUI = false;
+        private String mPackageName;
 
         public PermissionItemView(Context context, AttributeSet attrs) {
             super(context, attrs);
@@ -145,9 +149,12 @@
         }
 
         public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
-                boolean first, CharSequence newPermPrefix) {
+                boolean first, CharSequence newPermPrefix, String packageName,
+                boolean showRevokeUI) {
             mGroup = grp;
             mPerm = perm;
+            mShowRevokeUI = showRevokeUI;
+            mPackageName = packageName;
 
             ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
             TextView permNameView = (TextView) findViewById(R.id.perm_name);
@@ -206,6 +213,7 @@
                 }
                 builder.setCancelable(true);
                 builder.setIcon(mGroup.loadGroupIcon(pm));
+                addRevokeUIIfNecessary(builder);
                 mDialog = builder.show();
                 mDialog.setCanceledOnTouchOutside(true);
             }
@@ -218,6 +226,30 @@
                 mDialog.dismiss();
             }
         }
+
+        private void addRevokeUIIfNecessary(AlertDialog.Builder builder) {
+            if (!mShowRevokeUI) {
+                return;
+            }
+
+            final boolean isRequired =
+                    ((mPerm.mExistingReqFlags & PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
+
+            if (isRequired) {
+                return;
+            }
+
+            DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    PackageManager pm = getContext().getPackageManager();
+                    pm.revokePermission(mPackageName, mPerm.name);
+                    PermissionItemView.this.setVisibility(View.GONE);
+                }
+            };
+            builder.setNegativeButton(R.string.revoke, ocl);
+            builder.setPositiveButton(R.string.ok, null);
+        }
     }
 
     private AppSecurityPermissions(Context context) {
@@ -230,6 +262,7 @@
 
     public AppSecurityPermissions(Context context, String packageName) {
         this(context);
+        mPackageName = packageName;
         Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
         PackageInfo pkgInfo;
         try {
@@ -252,6 +285,7 @@
         if(info == null) {
             return;
         }
+        mPackageName = info.packageName;
 
         // Convert to a PackageInfo
         PackageInfo installedPkgInfo = null;
@@ -419,15 +453,23 @@
     }
 
     public View getPermissionsView() {
-        return getPermissionsView(WHICH_ALL);
+        return getPermissionsView(WHICH_ALL, false);
+    }
+
+    public View getPermissionsViewWithRevokeButtons() {
+        return getPermissionsView(WHICH_ALL, true);
     }
 
     public View getPermissionsView(int which) {
+        return getPermissionsView(which, false);
+    }
+
+    private View getPermissionsView(int which, boolean showRevokeUI) {
         LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
         LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
         View noPermsView = permsView.findViewById(R.id.no_permissions);
 
-        displayPermissions(mPermGroupsList, displayList, which);
+        displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
         if (displayList.getChildCount() <= 0) {
             noPermsView.setVisibility(View.VISIBLE);
         }
@@ -440,7 +482,7 @@
      * list of permission descriptions.
      */
     private void displayPermissions(List<MyPermissionGroupInfo> groups,
-            LinearLayout permListView, int which) {
+            LinearLayout permListView, int which, boolean showRevokeUI) {
         permListView.removeAllViews();
 
         int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
@@ -451,7 +493,7 @@
             for (int j=0; j<perms.size(); j++) {
                 MyPermissionInfo perm = perms.get(j);
                 View view = getPermissionItemView(grp, perm, j == 0,
-                        which != WHICH_NEW ? mNewPermPrefix : null);
+                        which != WHICH_NEW ? mNewPermPrefix : null, showRevokeUI);
                 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                         ViewGroup.LayoutParams.MATCH_PARENT,
                         ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -470,18 +512,19 @@
     }
 
     private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
-            MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) {
-        return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix);
+            MyPermissionInfo perm, boolean first, CharSequence newPermPrefix, boolean showRevokeUI) {
+        return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix,
+                mPackageName, showRevokeUI);
     }
 
     private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
             MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
-            CharSequence newPermPrefix) {
-        PermissionItemView permView = (PermissionItemView)inflater.inflate(
+            CharSequence newPermPrefix, String packageName, boolean showRevokeUI) {
+            PermissionItemView permView = (PermissionItemView)inflater.inflate(
                 (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0
                         ? R.layout.app_permission_item_money : R.layout.app_permission_item,
                 null);
-        permView.setPermission(grp, perm, first, newPermPrefix);
+        permView.setPermission(grp, perm, first, newPermPrefix, packageName, showRevokeUI);
         return permView;
     }
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 4b62c2d..c7914f3 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2433,7 +2433,7 @@
                     mFirstPosition;
         } else {
             final int lastPos = mFirstPosition + getChildCount() - 1;
-            nextSelected = selectedPos != INVALID_POSITION && selectedPos < lastPos?
+            nextSelected = selectedPos != INVALID_POSITION && selectedPos <= lastPos ?
                     selectedPos - 1 :
                     lastPos;
         }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 529de2e..3df7258 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -220,28 +220,29 @@
     // with MeasureSpec value overflow and RelativeLayout was one source of them.
     // Some apps came to rely on them. :(
     private boolean mAllowBrokenMeasureSpecs = false;
+    // Compatibility hack. Old versions of the platform would not take
+    // margins and padding into account when generating the height measure spec
+    // for children during the horizontal measure pass.
+    private boolean mMeasureVerticalWithPaddingMargin = false;
 
     // A default width used for RTL measure pass
-    private static int DEFAULT_WIDTH = Integer.MAX_VALUE / 2;
+    private static final int DEFAULT_WIDTH = Integer.MAX_VALUE / 2;
 
     public RelativeLayout(Context context) {
         super(context);
-        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
-                Build.VERSION_CODES.JELLY_BEAN_MR1;
+        queryCompatibilityModes(context);
     }
 
     public RelativeLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         initFromAttributes(context, attrs);
-        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
-                Build.VERSION_CODES.JELLY_BEAN_MR1;
+        queryCompatibilityModes(context);
     }
 
     public RelativeLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initFromAttributes(context, attrs);
-        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
-                Build.VERSION_CODES.JELLY_BEAN_MR1;
+        queryCompatibilityModes(context);
     }
 
     private void initFromAttributes(Context context, AttributeSet attrs) {
@@ -251,6 +252,12 @@
         a.recycle();
     }
 
+    private void queryCompatibilityModes(Context context) {
+        int version = context.getApplicationInfo().targetSdkVersion;
+        mAllowBrokenMeasureSpecs = version <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+        mMeasureVerticalWithPaddingMargin = version >= Build.VERSION_CODES.JELLY_BEAN_MR2;
+    }
+
     @Override
     public boolean shouldDelayChildPressedState() {
         return false;
@@ -692,6 +699,11 @@
                 params.leftMargin, params.rightMargin,
                 mPaddingLeft, mPaddingRight,
                 myWidth);
+        int maxHeight = myHeight;
+        if (mMeasureVerticalWithPaddingMargin) {
+            maxHeight = Math.max(0, myHeight - mPaddingTop - mPaddingBottom -
+                    params.topMargin - params.bottomMargin);
+        }
         int childHeightMeasureSpec;
         if (myHeight < 0 && !mAllowBrokenMeasureSpecs) {
             if (params.height >= 0) {
@@ -704,9 +716,9 @@
                 childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
             }
         } else if (params.width == LayoutParams.MATCH_PARENT) {
-            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
         } else {
-            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
         }
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index db20549..acbb2b1 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -812,6 +812,26 @@
         return mActionView != null && mActionView.isTitleTruncated();
     }
 
+    @Override
+    public void setHomeAsUpIndicator(Drawable indicator) {
+        mActionView.setHomeAsUpIndicator(indicator);
+    }
+
+    @Override
+    public void setHomeAsUpIndicator(int resId) {
+        mActionView.setHomeAsUpIndicator(resId);
+    }
+
+    @Override
+    public void setHomeActionContentDescription(CharSequence description) {
+        mActionView.setHomeActionContentDescription(description);
+    }
+
+    @Override
+    public void setHomeActionContentDescription(int resId) {
+        mActionView.setHomeActionContentDescription(resId);
+    }
+
     /**
      * @hide 
      */
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
new file mode 100644
index 0000000..e26b27d
--- /dev/null
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -0,0 +1,146 @@
+/*
+**
+** Copyright 2013, 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.os;
+
+import java.io.PrintStream;
+
+public abstract class BaseCommand {
+
+    protected String[] mArgs;
+    private int mNextArg;
+    private String mCurArgData;
+
+    // These are magic strings understood by the Eclipse plugin.
+    public static final String FATAL_ERROR_CODE = "Error type 1";
+    public static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
+    public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
+    /**
+     * Call to run the command.
+     */
+    public void run(String[] args) {
+        if (args.length < 1) {
+            onShowUsage(System.out);
+            return;
+        }
+
+        mArgs = args;
+        mNextArg = 0;
+        mCurArgData = null;
+
+        try {
+            onRun();
+        } catch (IllegalArgumentException e) {
+            onShowUsage(System.err);
+            System.err.println();
+            System.err.println("Error: " + e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace(System.err);
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Convenience to show usage information to error output.
+     */
+    public void showUsage() {
+        onShowUsage(System.err);
+    }
+
+    /**
+     * Convenience to show usage information to error output along
+     * with an error message.
+     */
+    public void showError(String message) {
+        onShowUsage(System.err);
+        System.err.println();
+        System.err.println(message);
+    }
+
+    /**
+     * Implement the command.
+     */
+    public abstract void onRun() throws Exception;
+
+    /**
+     * Print help text for the command.
+     */
+    public abstract void onShowUsage(PrintStream out);
+
+    /**
+     * Return the next option on the command line -- that is an argument that
+     * starts with '-'.  If the next argument is not an option, null is returned.
+     */
+    public String nextOption() {
+        if (mCurArgData != null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+        }
+        if (mNextArg >= mArgs.length) {
+            return null;
+        }
+        String arg = mArgs[mNextArg];
+        if (!arg.startsWith("-")) {
+            return null;
+        }
+        mNextArg++;
+        if (arg.equals("--")) {
+            return null;
+        }
+        if (arg.length() > 1 && arg.charAt(1) != '-') {
+            if (arg.length() > 2) {
+                mCurArgData = arg.substring(2);
+                return arg.substring(0, 2);
+            } else {
+                mCurArgData = null;
+                return arg;
+            }
+        }
+        mCurArgData = null;
+        return arg;
+    }
+
+    /**
+     * Return the next argument on the command line, whatever it is; if there are
+     * no arguments left, return null.
+     */
+    public String nextArg() {
+        if (mCurArgData != null) {
+            String arg = mCurArgData;
+            mCurArgData = null;
+            return arg;
+        } else if (mNextArg < mArgs.length) {
+            return mArgs[mNextArg++];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Return the next argument on the command line, whatever it is; if there are
+     * no arguments left, throws an IllegalArgumentException to report this to the user.
+     */
+    public String nextArgRequired() {
+        String arg = nextArg();
+        if (arg == null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
+        }
+        return arg;
+    }
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 780f5b3..58b15e2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -17,7 +17,7 @@
 package com.android.internal.statusbar;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
+import android.service.notification.StatusBarNotification;
 
 /** @hide */
 oneway interface IStatusBar
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 04e5bc9..c98ba8d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -19,7 +19,7 @@
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
+import android.service.notification.StatusBarNotification;
 
 /** @hide */
 interface IStatusBarService
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 9143c61..14afe21 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -84,7 +84,7 @@
         dest.writeStrongInterface(method);
         if (channel != null) {
             dest.writeInt(1);
-            channel.writeToParcel(dest, 0);
+            channel.writeToParcel(dest, flags);
         } else {
             dest.writeInt(0);
         }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 2685046..7ca6c1b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -107,7 +107,7 @@
     }
 
     public CharSequence getTitleCondensed() {
-        return mTitleCondensed;
+        return mTitleCondensed != null ? mTitleCondensed : mTitle;
     }
 
     public boolean hasSubMenu() {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b99b39a..59ff597 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -93,6 +93,8 @@
     private CharSequence mSubtitle;
     private Drawable mIcon;
     private Drawable mLogo;
+    private CharSequence mHomeDescription;
+    private int mHomeDescriptionRes;
 
     private HomeView mHomeLayout;
     private HomeView mExpandedHomeLayout;
@@ -288,6 +290,10 @@
             initTitle();
         }
 
+        if (mHomeDescriptionRes != 0) {
+            setHomeActionContentDescription(mHomeDescriptionRes);
+        }
+
         if (mTabScrollView != null && mIncludeTabs) {
             ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
             if (lp != null) {
@@ -589,14 +595,43 @@
             mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
             mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            mUpGoerFive.setContentDescription(buildHomeContentDescription());
+        }
+    }
+
+    /**
+     * Compose a content description for the Home/Up affordance.
+     *
+     * <p>As this encompasses the icon/logo, title and subtitle all in one, we need
+     * a description for the whole wad of stuff that can be localized properly.</p>
+     */
+    private CharSequence buildHomeContentDescription() {
+        final CharSequence homeDesc;
+        if (mHomeDescription != null) {
+            homeDesc = mHomeDescription;
+        } else {
             if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                mUpGoerFive.setContentDescription(mContext.getResources().getText(
-                        R.string.action_bar_up_description));
+                homeDesc = mContext.getResources().getText(R.string.action_bar_up_description);
             } else {
-                mUpGoerFive.setContentDescription(mContext.getResources().getText(
-                        R.string.action_bar_home_description));
+                homeDesc = mContext.getResources().getText(R.string.action_bar_home_description);
             }
         }
+
+        final CharSequence title = getTitle();
+        final CharSequence subtitle = getSubtitle();
+        if (!TextUtils.isEmpty(title)) {
+            final String result;
+            if (!TextUtils.isEmpty(subtitle)) {
+                result = getResources().getString(
+                        R.string.action_bar_home_subtitle_description_format,
+                        title, subtitle, homeDesc);
+            } else {
+                result = getResources().getString(R.string.action_bar_home_description_format,
+                        title, homeDesc);
+            }
+            return result;
+        }
+        return homeDesc;
     }
 
     public void setDisplayOptions(int options) {
@@ -1305,6 +1340,23 @@
         }
     }
 
+    public void setHomeAsUpIndicator(Drawable indicator) {
+        mHomeLayout.setUpIndicator(indicator);
+    }
+
+    public void setHomeAsUpIndicator(int resId) {
+        mHomeLayout.setUpIndicator(resId);
+    }
+
+    public void setHomeActionContentDescription(CharSequence description) {
+        mHomeDescription = description;
+    }
+
+    public void setHomeActionContentDescription(int resId) {
+        mHomeDescriptionRes = resId;
+        mHomeDescription = getResources().getText(resId);
+    }
+
     static class SavedState extends BaseSavedState {
         int expandedMenuItemId;
         boolean isOverflowOpen;
@@ -1339,9 +1391,11 @@
     }
 
     private static class HomeView extends FrameLayout {
-        private View mUpView;
+        private ImageView mUpView;
         private ImageView mIconView;
         private int mUpWidth;
+        private int mUpIndicatorRes;
+        private Drawable mDefaultUpIndicator;
 
         private static final long DEFAULT_TRANSITION_DURATION = 150;
 
@@ -1366,6 +1420,25 @@
             mIconView.setImageDrawable(icon);
         }
 
+        public void setUpIndicator(Drawable d) {
+            mUpView.setImageDrawable(d != null ? d : mDefaultUpIndicator);
+            mUpIndicatorRes = 0;
+        }
+
+        public void setUpIndicator(int resId) {
+            mUpIndicatorRes = resId;
+            mUpView.setImageDrawable(resId != 0 ? getResources().getDrawable(resId) : null);
+        }
+
+        @Override
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            if (mUpIndicatorRes != 0) {
+                // Reload for config change
+                setUpIndicator(mUpIndicatorRes);
+            }
+        }
+
         @Override
         public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
             onPopulateAccessibilityEvent(event);
@@ -1389,8 +1462,9 @@
 
         @Override
         protected void onFinishInflate() {
-            mUpView = findViewById(com.android.internal.R.id.up);
+            mUpView = (ImageView) findViewById(com.android.internal.R.id.up);
             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
+            mDefaultUpIndicator = mUpView.getDrawable();
         }
 
         public int getStartOffset() {
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 9c44a59..9fa9fe4 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -246,6 +246,15 @@
     return name;
 }
 
+static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobject otherObj) {
+    NativeInputChannel* nativeInputChannel =
+            android_view_InputChannel_getNativeInputChannel(env, obj);
+    if (nativeInputChannel) {
+        android_view_InputChannel_setNativeInputChannel(env, otherObj,
+                new NativeInputChannel(nativeInputChannel->getInputChannel()->dup()));
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gInputChannelMethods[] = {
@@ -262,6 +271,8 @@
             (void*)android_view_InputChannel_nativeWriteToParcel },
     { "nativeGetName", "()Ljava/lang/String;",
             (void*)android_view_InputChannel_nativeGetName },
+    { "nativeDup", "(Landroid/view/InputChannel;)V",
+            (void*)android_view_InputChannel_nativeDup },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 576f831..e3a54a8 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -62,8 +62,8 @@
     const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
     for (size_t i = 0; i < ranges.size(); i++) {
         const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
-        env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange,
-                range.axis, range.source, range.min, range.max, range.flat, range.fuzz);
+        env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange, range.axis,
+                range.source, range.min, range.max, range.flat, range.fuzz, range.resolution);
         if (env->ExceptionCheck()) {
             return NULL;
         }
@@ -90,7 +90,7 @@
             "<init>", "(IILjava/lang/String;Ljava/lang/String;ZIILandroid/view/KeyCharacterMap;Z)V");
 
     GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
-            "addMotionRange", "(IIFFFF)V");
+            "addMotionRange", "(IIFFFFF)V");
 
     return 0;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 666d1c6..90e3b8d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2193,6 +2193,14 @@
         android:description="@string/permdesc_accessNotifications"
         android:protectionLevel="signature|system" />
 
+    <!-- Must be required by an {@link
+         android.service.notification.NotificationListenerService},
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+        android:label="@string/permlab_bindNotificationListenerService"
+        android:description="@string/permdesc_bindNotificationListenerService"
+        android:protectionLevel="signature" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
@@ -2301,6 +2309,12 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..7c5826f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..974a292
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_dark.9.png
new file mode 100644
index 0000000..b3196c9
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_light.9.png
new file mode 100644
index 0000000..1f833d3
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
new file mode 100644
index 0000000..e969abc
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_light.9.png
new file mode 100644
index 0000000..3adbc84
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..a321836
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..4c5d692
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_dark.9.png
new file mode 100644
index 0000000..6199dc5
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_light.9.png
new file mode 100644
index 0000000..1b0905a
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
new file mode 100644
index 0000000..c6d7868
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_light.9.png
new file mode 100644
index 0000000..179644c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..039a056
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..c8d68c5
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
new file mode 100644
index 0000000..1fef1ad
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_light.9.png
new file mode 100644
index 0000000..6b22d44
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
new file mode 100644
index 0000000..c219527
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
new file mode 100644
index 0000000..2a1d508
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/layout/select_dialog.xml b/core/res/res/layout/select_dialog.xml
index 80d22f6..eb4d8d9 100644
--- a/core/res/res/layout/select_dialog.xml
+++ b/core/res/res/layout/select_dialog.xml
@@ -32,4 +32,5 @@
     android:cacheColorHint="@null"
     android:divider="?android:attr/listDividerAlertDialog"
     android:scrollbars="vertical"
-    android:overScrollMode="ifContentScrolls" />
+    android:overScrollMode="ifContentScrolls"
+    android:textAlignment="viewStart" />
diff --git a/core/res/res/layout/select_dialog_holo.xml b/core/res/res/layout/select_dialog_holo.xml
index 06a5d96..8a92283 100644
--- a/core/res/res/layout/select_dialog_holo.xml
+++ b/core/res/res/layout/select_dialog_holo.xml
@@ -30,4 +30,5 @@
     android:cacheColorHint="@null"
     android:divider="?android:attr/listDividerAlertDialog"
     android:scrollbars="vertical"
-    android:overScrollMode="ifContentScrolls" />
+    android:overScrollMode="ifContentScrolls"
+    android:textAlignment="viewStart" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index f72fddb..65363da 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Laat die program toe om te verander hoe netwerkgebruik teenoor programme gemeet word. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"kry toegang tot kennisgewings"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings op te haal, te bestudeer en te verwyder, insluitende die kennisgewings wat deur ander programme geplaas is."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Toeganklikheid"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Muurpapier"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Verander muurpapier"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN geaktiveer"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigeer tuis"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigeer op"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opsies"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interne geheue"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-berging"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Toeganklikheid gekanselleer."</string>
     <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
     <string name="owner_name" msgid="2716755460376028154">"Eienaar"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Hierdie program werk nie met rekeninge vir beperkte gebruikers nie"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 73c323c..8ec00c3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ከመተግበሪያዎች በተለየ መልኩ እንዴት የአውታረ መረብ አጠቃቀም እንደተመዘገበ ለመቀየር ለመተግበሪያው ይፈቅዳሉ።ለመደበኛ መተግበሪያዎች አገልግሎት አይውልም።"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"ማሳወቂያዎችን ይድረሱ"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"መተግበሪያው ማሳወቂያዎችን እንዲያስመጣ፣ እንዲመረምር እና እንዲያጸዳ ያስችለዋል፣ በሌሎች መተግበሪያዎች የተለጠፉትንም ጨምሮ።"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ድንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ተደራሽነት"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN ነቅቷል።"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"መነሻ ዳስስ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"አስስ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ተጨማሪ አማራጮች"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"ውስጣዊ ማከማቻ"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD ካርድ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"የUSB  ማከማቻ"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ተደራሽነት ተሰርዟል።"</string>
     <string name="user_switched" msgid="3768006783166984410">"የአሁኑ ተጠቃሚ <xliff:g id="NAME">%1$s</xliff:g>።"</string>
     <string name="owner_name" msgid="2716755460376028154">"ባለቤት"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"ስህተት"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"ይህ መተግበሪያ የተገደቡ ተጠቃሚዎች መለያዎችን አይደግፍም"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 942968b..688f524 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"للسماح للتطبيق بتعديل كيفية حساب استخدام الشبكة في التطبيقات. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"إشعارات الدخول"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"يتيح للتطبيق استرجاع الإشعارات وفحصها ومسحها، بما في ذلك تلك التي نشرتها تطبيقات أخرى."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"يمكنك التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء تأمين الشاشة."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الدخول"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"التنقل إلى الشاشة الرئيسية"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"التنقل إلى أعلى"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"المزيد من الخيارات"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"وحدة تخزين داخلية"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"بطاقة SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"وحدة تخزين USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"تم إلغاء تسهيل الدخول."</string>
     <string name="user_switched" msgid="3768006783166984410">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"المالك"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"خطأ"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"لا يوفر هذا التطبيق حسابات للمستخدمين المقيّدين"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"لم يتم العثور على تطبيق يمكنه التعامل مع هذا الإجراء."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index e6c9ee7..4c88a71 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дазваляе прыкладанням змяняць метад уліку выкарыстання сеткі прыкладаннямі. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"доступ да паведамленняў"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дазваляе прыкладанню атрымлiваць, правяраць i выдаляць апавяшчэннi, у тым лiку апублiкаваныя iншымi прыкладаннямi."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Кіраванне даўжынёй і колькасцю знакаў у паролі разблакоўкі экрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Сачыць за спробамі разблакоўкі экрана"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Спецыяльныя магчымасці"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Шпалеры"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змена шпалер"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN актываваны"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN актывуецца прыкладаннем <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Дакраніцеся, каб кіраваць сеткай."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перайсці да пачатковай старонкі"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перайсці ўверх"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Больш налад"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Унутраная памяць"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-карта"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-назапашвальнік"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Памылка"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Гэтае прыкладанне не падтрымлівае уліковыя запісы для карыстальнікаў з абмежаванымі правамі"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 79600f7..9ff9321 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Разрешава на приложението да променя това как употребата на мрежа се отчита спрямо приложенията. Не е предназначено за нормални приложения."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"достъп до известията"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Разрешава на приложението да извлича, преглежда и изчиства известия, включително публикуваните от други приложения."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Достъпност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN е активирана"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Придвижване към „Начало“"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Придвижване нагоре"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Още опции"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Вътрешно хранилище"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD карта"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB хранилище"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Това приложение не поддържа профили за потребители с ограничения"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 975dc40..6dff5d1 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet que l\'aplicació modifiqui la manera com es calcula l\'ús de la xarxa per part de les aplicacions. No indicat per a les aplicacions normals."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accedeix a les notificacions"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control d\'intents de desbloqueig de pantalla"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Torna a la pàgina d\'inici"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Mou cap a dalt"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Més opcions"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Emmagatzematge intern"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Targeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Emmagatzematge USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Aquesta aplicació no admet comptes per a usuaris limitats"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0adebe9..7036fbe 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikaci upravit způsob výpočtu využití sítě aplikacemi. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"přístup k oznámením"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikacím načítat, zobrazovat a mazat oznámení včetně těch přidaných jinými aplikacemi."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemčení obrazovky a povolené znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Usnadnění"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Síť VPN je aktivována"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Přejít na plochu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Přejít nahoru"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Další možnosti"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interní úložiště"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Úložiště USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Tato aplikace u omezeného počtu uživatelů nepodporuje účty"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index bb4eb72..40dcfbd 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillader, at appen kan ændre den måde, som netværksforbrug udregnes på i forhold til apps. Anvendes ikke af normale apps."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"adgang til underretninger"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, herunder dem, der er sendt af andre apps."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgængelighed"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapet"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift tapet"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Naviger hjem"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Naviger op"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere valgmuligheder"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Internt lager"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lager"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Tilgængelighed er annulleret."</string>
     <string name="user_switched" msgid="3768006783166984410">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Ejer"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Fejl"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Denne applikation understøtter ikke konti for brugere med begrænsede rettigheder"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6a488c7..51a8504 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ermöglicht der App, die Art und Weise zu ändern, wie der Netzwerkverbrauch im Hinblick auf Apps berechnet wird. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"Auf Benachrichtigungen zugreifen"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Bedienungshilfen"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Zur Startseite navigieren"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Nach oben navigieren"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Weitere Optionen"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interner Speicher"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-Karte"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-Speicher"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Fehler"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Diese App unterstützt keine Konten für eingeschränkte Nutzer."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 21b014c..a30b8cf 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Επιτρέπει στην εφαρμογή την τροποποίηση του τρόπου υπολογισμού της χρήσης δικτύου έναντι των εφαρμογών. Δεν προορίζεται για χρήση από συνήθεις εφαρμογές."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"πρόσβαση στις ειδοποιήσεις"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Προσβασιμότητα"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Το VPN ενεργοποιήθηκε"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Πλοήγηση στην αρχική σελίδα"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Πλοήγηση προς τα επάνω"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός χώρος αποθήκευσης"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Κάρτα SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Χώρος αποθήκευσης USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Σφάλμα"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένους χρήστες"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ae698e1..060322d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Allows the app to modify how network usage is accounted against apps. Not for use by normal apps."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"access notifications"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibility"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigate home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigate up"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Internal storage"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"This application does not support accounts for limited users"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No application found to handle this action"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 61d768d..f0786a9 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y elimine notificaciones, incluidas aquellas publicadas por otras aplicaciones."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Desplazarse hasta la página principal"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Desplazarse hacia arriba"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Almacenamiento interno"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Tarjeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Se canceló la accesibilidad."</string>
     <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Esta aplicación no admite cuentas para usuarios restringidos."</string>
+    <string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index bdeed44..ec3308d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y borre notificaciones, incluidas las que han publicado otras aplicaciones."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ir al escritorio"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Desplazarse hacia arriba"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Almacenamiento interno"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Tarjeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accesibilidad cancelada"</string>
     <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Esta aplicación no admite cuentas de usuarios limitados."</string>
+    <string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 9c7a28f..8ec5525 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Võimaldab rakendusel muuta võrgukasutuse loendamist rakenduste suhtes. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"juurdepääsu märguanded"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Võimaldab rakendusel tuua, kontrollida ja kustutada märguandeid, sh neid, mille on postitanud teised rakendused."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Juurdepääsetavus"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustapilt"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Muutke taustapilti"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktiveeritud"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Liigu avalehele"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Liigu üles"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Rohkem valikuid"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Sisemine salvestusruum"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-mäluseade"</string>
@@ -1477,6 +1487,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Omanik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Viga"</string>
-    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Rakendus ei toeta piiratud arvu kasutajate kontot"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Rakendus ei toeta piiratud õigustega kasutajate kontosid"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4a09361..d64265b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"به برنامه اجازه می‎دهد تا نحوه محاسبه کاربرد شبکه در برنامه را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"اعلان‌های دسترسی"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"به برنامه اجازه می‌دهد به بازیابی، بررسی و پاک کردن اعلان‌ها از جمله موارد پست شده توسط سایر برنامه‌ها بپردازد."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"قابلیت دسترسی"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"رفتن به صفحهٔ اصلی"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"حرکت به بالا"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"سایر گزینه‌ها"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"حافظهٔ داخلی"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"کارت SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"حافظهٔ USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"قابلیت دسترسی لغو شد."</string>
     <string name="user_switched" msgid="3768006783166984410">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"دارنده"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"خطا"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"این برنامه حساب‌های تعداد محدودی از کاربران را پشتیبانی نمی‌کند"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"برنامه‌ای برای انجام این عملکرد موجود نیست"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 0f71020..131d937 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Antaa sovelluksen muokata, miten sovellusten verkonkäyttöä lasketaan. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"käytä ilmoituksia"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Esteettömyys"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Siirry etusivulle"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Siirry ylös"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lisää asetuksia"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Sisäinen tallennustila"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kortti"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tallennustila"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Virhe"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Tämä sovellus ei tue rajoitettujen käyttäjien tilejä"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2026f56..9fe514d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet à l\'application de modifier l\'utilisation du réseau par les autres applications. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accéder aux notifications"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilité"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Retour à l\'accueil"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Parcourir vers le haut"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Plus d\'options"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Mémoire de stockage interne"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Carte SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Mémoire de stockage USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Erreur"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Les comptes des utilisateurs en accès limité ne sont pas acceptés pour cette application."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b70bbc0..2fc5e2a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"एप्लिकेशन को यह संशोधित करने देता है कि एप्‍लिकेशन की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"सूचनाओं तक पहुंचें"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"एप्लिकेशन को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य एप्लिकेशन के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"स्‍क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"स्‍क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"पहुंच-योग्यता"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"होम पर नेविगेट करें"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ऊपर नेविगेट करें"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक विकल्प"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"आंतरिक संग्रहण"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD कार्ड"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB संग्रहण"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"पहुंच-योग्यता रद्द की गई."</string>
     <string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"यह एप्लिकेशन सीमित उपयोगकर्ताओं के खातों का समर्थन नहीं करता है"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7b1eee3..9c45b4b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Omogućuje aplikaciji izmjenu načina upotrebe mreže u odnosu na aplikacije. Nije namijenjeno uobičajenim aplikacijama."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"pristup obavijestima"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Omogućuje aplikaciji dohvaćanje, pregledavanje i brisanje obavijesti, uključujući obavijesti drugih aplikacija."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Dostupnost"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Kreni na početnu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Kreni gore"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Više opcija"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interna pohrana"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD kartica"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB pohrana"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Pogreška"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Aplikacija ne podržava račune za ograničene korisnike"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index fc1d663..96380cd 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lehetővé teszi az alkalmazás számára annak módosítását, hogy a hálózathasználatot hogyan számolják el az alkalmazások esetében. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"hozzáférési értesítések"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lehetővé teszi, hogy az alkalmazás értesítéseket kérdezzen le, vizsgáljon és tisztítson meg, beleértve az egyéb alkalmazások által közzétett értesítéseket is."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kisegítő lehetőségek"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiválva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ugrás a főoldalra"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Felfele mozgás"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"További lehetőségek"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Belső tárhely"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kártya"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tár"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Hiba"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ez az alkalmazás nem támogatja a korlátozott jogokkal rendelkező felhasználói fiókokat."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2a9f2fc..40c466b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Mengizinkan apl memodifikasi cara penggunaan jaringan diperhitungkan terhadap apl. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"mengakses pemberitahuan"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Aksesibilitas"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigasi ke beranda"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi naik"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Opsi lainnya"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Penyimpanan internal"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kartu SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Penyimpanan USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Kesalahan"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Aplikasi ini tidak mendukung akun untuk pengguna terbatas"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2273459..79c1f51 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Consente all\'applicazione di modificare il calcolo dell\'utilizzo della rete tra le applicazioni. Da non usare per normali applicazioni."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accesso a notifiche"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Consente all\'app di recuperare, esaminare e cancellare notifiche, comprese quelle pubblicate da altre app."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilità"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN attiva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Vai alla home page"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Vai in alto"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Altre opzioni"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Memoria interna"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Scheda SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Archivio USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Errore"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Questa applicazione non supporta account di utenti con limitazioni"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8c7c74e..5430506 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"הרשאה זו מאפשרת ליישום לשנות את אופן החישוב של נתוני שימוש ברשת מול כל יישום. לא מיועד לשימוש ביישומים רגילים."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להתראות"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר ליישום לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי יישומים אחרים."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"שלוט באורך ובתווים המותרים בסיסמאות לביטול נעילת מסך."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"נגישות"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"נווט לדף הבית"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"נווט למעלה"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"אפשרויות נוספות"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"אחסון פנימי"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"כרטיס SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"אחסון USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"שגיאה"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"היישום הזה לא תומך בחשבונות עבור משתמשים מוגבלים"</string>
     <string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 4ec756e..a828c41 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"アプリに対するネットワーク利用の計算方法を変更することをアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"通知にアクセス"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"通知(他のアプリから投稿されたものも含む)を取得、調査、クリアすることをアプリに許可します。"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"画面ロック解除パスワードの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ユーザー補助"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPNが有効になりました"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"ホームへ移動"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"上へ移動"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"その他のオプション"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"内部ストレージ"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SDカード"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USBストレージ"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"エラー"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"このアプリでは限定ユーザー用のアカウントはサポートしていません"</string>
     <string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index e6010ac..9450a49 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"애플리케이션이 애플리케이션의 네트워크 사용량을 계산하는 방식을 수정할 수 있도록 허용합니다. 일반 애플리케이션에서는 사용하지 않습니다."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"알림 액세스"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"앱이 다른 앱에서 게시한 알림을 비롯하여 알림을 검색하고 살펴보며 삭제할 수 있도록 허용합니다."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"접근성"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN이 활성화됨"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"홈 탐색"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"위로 탐색"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"옵션 더보기"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"내부 저장소"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD 카드"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 저장소"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"오류"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"이 애플리케이션은 제한된 사용자를 위한 계정을 지원하지 않습니다."</string>
     <string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index e8d7c26..e20e1c9 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Leidžiama programai keisti, kaip tinklas naudojamas, palyginti su programomis. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"pasiekti pranešimus"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Programai leidžiama gauti, patikrinti ir išvalyti pranešimus, įskaitant pranešimus, kuriuos paskelbė kitos programos."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pasiekiamumas"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN suaktyvintas"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Naršyti pagrindinį puslapį"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Naršyti į viršų"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Daugiau parinkčių"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Vidinė atmintis"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD kortelė"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmintis"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Klaida"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ši programa nepalaiko apribotų naudotojų paskyrų"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f134005..3bf284f 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ļauj lietotnei mainīt to, kā tīkla lietojums tiek uzskaitīts saistībā ar lietotnēm. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"piekļuve paziņojumiem"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ļauj lietotnei izgūt, pārbaudīt un dzēst paziņojumus, tostarp lietotņu publicētos paziņojumus."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pieejamība"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN ir aktivizēts."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Pārvietoties uz sākuma ekrānu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Pārvietoties augšup"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Vairāk opciju"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Iekšējā atmiņa"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD karte"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmiņa"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Kļūda"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Šajā lietojumprogrammā netiek atbalstīti ierobežotu lietotāju konti."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 3091e7d..894352d 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Membenarkan apl untuk mengubah suai bagaimana penggunaan rangkaian diambil kira terhadap apl. Bukan untuk digunakan oleh apl biasa."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"pemberitahuan akses"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kebolehaksesan"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigasi laman utama"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi ke atas"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lagi pilihan"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Storan dalaman"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kad SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Storan USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Ralat"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Aplikasi ini tidak menyokong akaun untuk pengguna terhad"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9d39ac8..c0f316f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lar appen endre hvordan nettverksbruk regnes ut for apper. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"varseltilgang"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgjengelighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktivert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Gå til startsiden"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Gå opp"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere alternativer"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Intern lagring"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Feil"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Denne appen støtter ikke kontoer for brukere med begrensninger"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b0a6d30..77e243e 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Hiermee kan een app aanpassen hoe het netwerkgebruik wordt toegekend aan apps. Dit wordt niet gebruikt door normale apps."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"toegang tot meldingen"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Hiermee kan de app meldingen ophalen, onderzoeken en wissen, waaronder meldingen die zijn verzonden door andere apps."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Toegankelijkheid"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN is geactiveerd"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigeren naar startpositie"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Omhoog navigeren"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opties"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interne opslag"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-opslag"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Deze app ondersteunt geen accounts voor beperkte gebruikers"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8d3122f..cae4008 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pozwala aplikacji na zmienianie sposobu rozliczania wykorzystania sieci przez aplikacje. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"dostęp do powiadomień"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umożliwia aplikacji pobieranie, sprawdzanie i usuwanie powiadomień, także tych, które pochodzą z innych aplikacji."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
@@ -744,7 +748,7 @@
     <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner życiowy"</string>
     <string name="relationTypeFather" msgid="5228034687082050725">"Ojciec"</string>
     <string name="relationTypeFriend" msgid="7313106762483391262">"Znajomy"</string>
-    <string name="relationTypeManager" msgid="6365677861610137895">"Kierownik"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Menedżer"</string>
     <string name="relationTypeMother" msgid="4578571352962758304">"Matka"</string>
     <string name="relationTypeParent" msgid="4755635567562925226">"Rodzic"</string>
     <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ułatwienia dostępu"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN aktywny"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Przejdź do strony głównej"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Przejdź wyżej"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Więcej opcji"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Pamięć wewnętrzna"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Nośnik USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Błąd"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ta aplikacja nie obsługuje kont użytkowników z ograniczeniami"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5eba00c..407ad6d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que a aplicação modifique o modo como a utilização da rede é contabilizada em relação a aplicações. Nunca é necessário para aplicações normais."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"aceder às notificações"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que a aplicação obtenha, examine e limpe notificações, incluindo as que foram publicadas por outras aplicações."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navegar para página inicial"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navegar para cima"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"memória de armazenamento interno"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Esta aplicação não suporta contas de utilizadores limitados"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 6b0d18a..a14ebdd 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que o aplicativo modifique como o uso da rede é contabilizado em relação aos aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"acessar notificações"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controle o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navegar na página inicial"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navegar para cima"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Armazenamento interno"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"O aplicativo não suporta contas para usuários limitados"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 99fd59d..b850bfd 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1040,6 +1040,10 @@
     <skip />
     <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
     <skip />
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <!-- no translation found for policylab_limitPassword (4497420728857585791) -->
     <skip />
     <!-- no translation found for policydesc_limitPassword (3252114203919510394) -->
@@ -1989,6 +1993,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Agids d\'access"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fund davos"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Midar il fund davos"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <!-- no translation found for vpn_title (19615213552042827) -->
     <skip />
     <!-- no translation found for vpn_title_long (6400714798049252294) -->
@@ -2178,6 +2184,10 @@
     <skip />
     <!-- no translation found for action_menu_overflow_description (2295659037509008453) -->
     <skip />
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <!-- no translation found for storage_internal (4891916833657929263) -->
     <skip />
     <!-- no translation found for storage_sd_card (3282948861378286745) -->
@@ -2397,4 +2407,6 @@
     <skip />
     <!-- no translation found for app_not_found (3429141853498927379) -->
     <skip />
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b11cc2f..f48e540 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicaţiei să modifice modul în care este calculată utilizarea reţelei pentru aplicaţii. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilitate"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigaţi la ecranul de pornire"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigaţi în sus"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mai multe opţiuni"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Stocare internă"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Card SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Eroare"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Această aplicație nu acceptă conturile pentru utilizatori cu permisiuni limitate"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3da7211..eed5868 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Приложение сможет изменять порядок расчета использования сетевых ресурсов различными программами. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"доступ к уведомлениям"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Приложение сможет получать, проверять и удалять уведомления, включая те, что опубликованы другими приложениями."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Спец. возможности"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Сеть VPN активна"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перейти на главную"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перейти вверх"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ещё"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Внутренняя память"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-карта"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-накопитель"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Ошибка"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Приложение не поддерживает аккаунты с ограниченным доступом"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 9ffe30d..a08262e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikácii upraviť používanie siete jednotlivými aplikáciami. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"prístup k upozorneniam"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Zjednodušenie"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Prejsť na plochu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Prejsť na"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Viac možností"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Interné úložisko"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Ukladací priestor USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Táto aplikácia nepodporuje účty v prípade používateľov s obmedzením"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ac1b6ad..0d09190 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Programu omogoča, da spremeni uporabo omrežja na podlagi programov. Ni za uporabo z navadnimi programi."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"dostop do obvestil"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Dovoli aplikaciji, da prenese, razišče in izbriše obvestila, tudi tista, ki so jih objavile druge aplikacije."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pripomočki za osebe s posebnimi potrebami"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Krmarjenje domov"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Krmarjenje navzgor"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Več možnosti"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Notranji pomnilnik"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kartica SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Pomnilnik USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Napaka"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ta aplikacija ne podpira računov za uporabnike z omejitvami"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7e8cf01..5eff70b 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозвољава апликацији да измени начин на који апликације користе мрежу. Не користе је уобичајене апликације."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"приступ обавештењима"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозвољава апликацији да преузима, испитује и брише обавештења, укључујући она која постављају друге апликације."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Приступачност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN је активиран"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Кретање до Почетне"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Кретање нагоре"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Још опција"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Интерна меморија"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD картица"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB меморија"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ова апликација не подржава налоге за кориснике са ограничењем"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 5a54f71..4b831af 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillåter att appen ändrar hur nätverksanvändning redovisas för appar. Används inte av vanliga appar."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"få åtkomst till meddelanden"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillåter att appen hämtar, granskar och raderar meddelanden, även sådana som skickats av andra appar."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tillgänglighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN är aktiverat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Visa startsidan"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigera uppåt"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Fler alternativ"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Internminne"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Fel"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Appen har inte stöd för användarkonton med begränsningar"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 96b013f..b770143 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Huruhusu programu kurekebisha jinsi matumizi ya mtandao yana hesabika dhidi ya programu. Sio ya matumizi na programu za kawaida."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"fikia arifa"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Dhibiti urefu na vibambo vinavyoruhusiwa katika manenosiri ya kufungua skrini."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ufikiaji"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
@@ -1350,7 +1356,7 @@
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"Imefanyika"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Modi ya mabadiliko"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Songa"</string>
-    <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Ingiza"</string>
+    <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"Chagua programu"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Shiriki na"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Shiriki na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Abiri nyumbani"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Ongoza"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Chaguo zaidi"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Hifadhi ya mfumo"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kadi ya SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Hifadhi ya USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ufikivu umeghairiwa."</string>
     <string name="user_switched" msgid="3768006783166984410">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Mmiliki"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Hitilafu"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Programu hii haiwezi kutumiwa na akaunti za watumiaji waliowekewa vizuizi"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 43fdeac..a8bb17b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -154,9 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ตัวเลือกโทรศัพท์"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ล็อกหน้าจอ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ปิดเครื่อง"</string>
-    <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานข้อบกพร่อง"</string>
-    <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานข้อบกพร่อง"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานข้อบกพร่องจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานบั๊ก"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานบั๊ก"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานบั๊กจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"โหมดปิดเสียง"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ปิดเสียงไว้"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"เปิดเสียงแล้ว"</string>
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"อนุญาตให้แอปพลิเคชันแก้ไขวิธีการบันทึกบัญชีการใช้งานเครือข่ายของแอปพลิเคชัน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"เข้าถึงการแจ้งเตือน"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกดู ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"การเข้าถึง"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN เปิดใช้งานแล้ว"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"นำทางไปหน้าแรก"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"นำทางขึ้น"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ตัวเลือกเพิ่มเติม"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"ที่จัดเก็บข้อมูลภายใน"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"การ์ด SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ที่เก็บข้อมูล USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ยกเลิกการเข้าถึงแล้ว"</string>
     <string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"เจ้าของ"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"ข้อผิดพลาด"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"แอปพลิเคชันนี้ไม่สนับสนุนบัญชีผู้ใช้ที่ถูกจำกัด"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index beeb6c0..323a673 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pinapayagan ang app na baguhin kung paano isinasaalang-alang ang paggamit ng network laban sa apps. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"i-access ang mga notification"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Pinapayagan ang app na kumuha, sumuri, at mag-clear ng mga notification, kabilang ang mga na-post ng iba pang apps."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kakayahang Ma-access"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Naka-activate ang VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Magnabiga sa home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Magnabiga pataas"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Higit pang mga pagpipilian"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Panloob na storage"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Hindi sinusuportahan ng application na ito ang mga account para sa mga limitadong user"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2fddf7d..414e9bd9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Uygulamaya, ağın uygulamalara göre nasıl kullanılacağını değiştirme izni verir. Normal uygulamalar tarafından kullanılmak için değildir."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"bildirimlere eriş"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Uygulamanın bildirimler almasına, bildirimleri incelemesine ve temizlemesine izin verir. Buna diğer uygulamalar tarafından yayınlanan bildirimler de dahildir."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Erişebilirlik"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ana sayfaya git"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Yukarı git"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Diğer seçenekler"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Dahili depolama birimi"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD kart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB bellek"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Erişilebilirlik iptal edildi."</string>
     <string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Sahibi"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Hata"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Bu uygulama, kısıtlı kullanıcı hesaplarını desteklemiyor"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6f505b1..cb0b863 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозволяє програмі змінювати метод підрахунку того, як програми використовують мережу. Не для використання звичайними програмами."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"отримувати доступ до сповіщень"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозволяє програмі отримувати, перевіряти й очищати сповіщення, зокрема опубліковані іншими програмами."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів для розблокування екрана та дозволені в них символи."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Доступність"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фоновий малюнок"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перейти на головну"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перейти вгору"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Інші варіанти"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Внутрішня пам’ять"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Карта SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Носій USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Помилка"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ця програма не підтримує облікові записи для обмежених користувачів"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 4fe8d65..1880369 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Cho phép ứng dụng sửa đổi cách tính mức sử dụng mạng so với ứng dụng. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"truy cập thông báo"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Cho phép ứng dụng truy xuất, kiểm tra và xóa thông báo, bao gồm những thông báo được đăng bởi các ứng dụng khác."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Khả năng truy cập"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Đã kích hoạt VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Điều hướng về trang chủ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Điều hướng lên trên"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Tùy chọn khác"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Bộ nhớ trong"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Thẻ SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Bộ lưu trữ USB"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"Lỗi"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Ứng dụng này không hỗ trợ tài khoản cho người dùng giới hạn"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index af1a2ea..7b52f15 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允许该应用修改对于各应用的网络使用情况的统计方式。普通应用不应使用此权限。"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"查看通知"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN 已激活"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"导航首页"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上导航"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多选项"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"内存设备"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
@@ -1479,4 +1489,6 @@
     <string name="error_message_title" msgid="4510373083082500195">"错误"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"此应用不支持受限用户的帐户"</string>
     <string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ed2551d..3faf789 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允許應用程式修改應用程式網路使用量的計算方式 (不建議一般應用程式使用)。"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"存取通知"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"協助工具"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"瀏覽首頁"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上瀏覽"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多選項"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"內部儲存空間"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
@@ -1478,5 +1488,7 @@
     <string name="owner_name" msgid="2716755460376028154">"擁有者"</string>
     <string name="error_message_title" msgid="4510373083082500195">"錯誤"</string>
     <string name="app_no_restricted_accounts" msgid="5322164210667258876">"這個應用程式不支援受限的使用者帳戶。"</string>
-    <string name="app_not_found" msgid="3429141853498927379">"找不到可以處理這個動作的應用程式"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a104729..afd183d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -621,6 +621,10 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ivumela insiza ukuthi iguqule ukuthii ukusetshenziswa kwenethiwekhi kumiswa kanjani ezinsizeni. Ayisetshenziswa izinsiza ezijwayelekile."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"finyelela kuzaziso"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ivumela uhlelo lokusebenza ukuthi lithole, lihlole, liphinde lisuse izaziso, ezifaka lezo ezithunyelwe ezinye izinhlelo zokusebenza."</string>
+    <!-- no translation found for permlab_bindNotificationListenerService (7057764742211656654) -->
+    <skip />
+    <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
@@ -1267,6 +1271,8 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ukufinyeleleka"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
+    <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"I-VPN isiyasebenza"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
@@ -1370,6 +1376,10 @@
     <string name="action_bar_home_description" msgid="5293600496601490216">"Zulazulela ekhaya"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Zulazulela phezulu"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Izinketho ezingaphezulu"</string>
+    <!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
+    <skip />
+    <!-- no translation found for action_bar_home_subtitle_description_format (6985546530471780727) -->
+    <skip />
     <string name="storage_internal" msgid="4891916833657929263">"Isitoreji sangaphakathi"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Ikhadi le-SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Isitoreji se-USB"</string>
@@ -1476,10 +1486,9 @@
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ukufinyelela kukhanseliwe."</string>
     <string name="user_switched" msgid="3768006783166984410">"Umsebenzisi wamanje <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Umnikazi"</string>
-    <!-- no translation found for error_message_title (4510373083082500195) -->
-    <skip />
-    <!-- no translation found for app_no_restricted_accounts (5322164210667258876) -->
-    <skip />
-    <!-- no translation found for app_not_found (3429141853498927379) -->
+    <string name="error_message_title" msgid="4510373083082500195">"Iphutha"</string>
+    <string name="app_no_restricted_accounts" msgid="5322164210667258876">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wabasebenzisi abakhawulelwe"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"Alukho uhlelo lokusebenza olutholakele lokuphatha lesi senzo"</string>
+    <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4a15967..a0e1603 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1816,6 +1816,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_accessNotifications">Allows the app to retrieve, examine, and clear notifications, including those posted by other apps.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindNotificationListenerService">bind to a notification listener service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindNotificationListenerService">Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
@@ -2992,11 +2997,11 @@
     <!-- [CHAR LIMIT=NONE] Stub notification title for an app running a service that has provided
          a bad bad notification for itself. -->
     <string name="app_running_notification_title"><xliff:g id="app_name">%1$s</xliff:g>
-        running</string>
+        is running</string>
     <!-- [CHAR LIMIT=NONE] Stub notification text for an app running a service that has provided
          a bad bad notification for itself. -->
-    <string name="app_running_notification_text"><xliff:g id="app_name">%1$s</xliff:g>
-        is currently running</string>
+    <string name="app_running_notification_text">Touch for more information
+        or to stop the app.</string>
 
     <!-- Preference framework strings. -->
     <string name="ok">OK</string>
@@ -3508,6 +3513,9 @@
     <string name="wallpaper_binding_label">Wallpaper</string>
     <!-- Dialog title for user to select a different wallpaper from service list -->
     <string name="chooser_wallpaper">Change wallpaper</string>
+    <!-- Label to show for a service that is running because it is observing
+         the user's notifications. -->
+    <string name="notification_listener_binding_label">Notification listener</string>
 
     <!-- Do Not Translate: Alternate eri.xml -->
     <string name="alternate_eri_file">/data/eri.xml</string>
@@ -3763,6 +3771,17 @@
     <string name="action_bar_up_description">Navigate up</string>
     <!-- Content description for the action menu overflow button. [CHAR LIMIT=NONE] -->
     <string name="action_menu_overflow_description">More options</string>
+    <!-- Formatting string for describing the action bar's title/home/up affordance.
+         This is a single tappable "button" that includes the app icon, the Up indicator
+         (usually a "<" chevron) and the window title text.
+         %1$s is the title. %2$s is the description of what tapping/clicking the whole
+         thing is going to do. -->
+    <string name="action_bar_home_description_format">%1$s, %2$s</string>
+    <!-- Just like action_bar_home_description_format, but this one will be used
+         if the window is also providing subtitle text.
+         %1$s is the title. %2$s is the subtitle. %3$s is the description of what
+         tapping/clicking the whole thing is going to do. -->
+    <string name="action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>
 
     <!-- Storage description for internal storage. [CHAR LIMIT=NONE] -->
     <string name="storage_internal">Internal storage</string>
@@ -4069,4 +4088,5 @@
     <string name="app_no_restricted_accounts">This application does not support accounts for limited users</string>
     <!-- Message informing user that the requested activity could not be found [CHAR LIMIT=none] -->
     <string name="app_not_found">No application found to handle this action</string>
+    <string name="revoke">Revoke</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ced0851..e06bcd1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -710,6 +710,7 @@
   <java-symbol type="string" name="relationTypeSpouse" />
   <java-symbol type="string" name="relative_time" />
   <java-symbol type="string" name="reset" />
+  <java-symbol type="string" name="revoke" />
   <java-symbol type="string" name="ringtone_default" />
   <java-symbol type="string" name="ringtone_default_with_actual" />
   <java-symbol type="string" name="ringtone_picker_title" />
@@ -870,6 +871,8 @@
   <java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
   <java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" />
   <java-symbol type="string" name="error_message_title" />
+  <java-symbol type="string" name="action_bar_home_description_format" />
+  <java-symbol type="string" name="action_bar_home_subtitle_description_format" />
 
   <java-symbol type="plurals" name="abbrev_in_num_days" />
   <java-symbol type="plurals" name="abbrev_in_num_hours" />
@@ -1638,6 +1641,7 @@
   <java-symbol type="string" name="launch_warning_title" />
   <java-symbol type="string" name="low_internal_storage_view_text" />
   <java-symbol type="string" name="low_internal_storage_view_title" />
+  <java-symbol type="string" name="notification_listener_binding_label" />
   <java-symbol type="string" name="report" />
   <java-symbol type="string" name="select_input_method" />
   <java-symbol type="string" name="select_keyboard_layout_notification_title" />
diff --git a/data/fonts/DroidSerif-Bold.ttf b/data/fonts/DroidSerif-Bold.ttf
index 838d255..16a914e 100644
--- a/data/fonts/DroidSerif-Bold.ttf
+++ b/data/fonts/DroidSerif-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSerif-BoldItalic.ttf b/data/fonts/DroidSerif-BoldItalic.ttf
index 0b1601f..50324fc 100644
--- a/data/fonts/DroidSerif-BoldItalic.ttf
+++ b/data/fonts/DroidSerif-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/DroidSerif-Italic.ttf b/data/fonts/DroidSerif-Italic.ttf
index 2972809..bb2757c 100644
--- a/data/fonts/DroidSerif-Italic.ttf
+++ b/data/fonts/DroidSerif-Italic.ttf
Binary files differ
diff --git a/data/fonts/DroidSerif-Regular.ttf b/data/fonts/DroidSerif-Regular.ttf
index 5b4fe81..da0a2cc 100644
--- a/data/fonts/DroidSerif-Regular.ttf
+++ b/data/fonts/DroidSerif-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
index 40ecd14..072b842 100644
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
index d9067c5..74919ff 100644
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
index 88e4a5b..bd57775 100644
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Light.ttf b/data/fonts/Roboto-Light.ttf
index 2ae4dec..13bf13a 100644
--- a/data/fonts/Roboto-Light.ttf
+++ b/data/fonts/Roboto-Light.ttf
Binary files differ
diff --git a/data/fonts/Roboto-LightItalic.ttf b/data/fonts/Roboto-LightItalic.ttf
index 44177ef..130672a 100644
--- a/data/fonts/Roboto-LightItalic.ttf
+++ b/data/fonts/Roboto-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
index f592adf..0ba95c9 100644
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
index 5ae4d7f..309c22d 100644
--- a/data/fonts/Roboto-Thin.ttf
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
index 9cd3927..0b53ba4 100644
--- a/data/fonts/Roboto-ThinItalic.ttf
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Bold.ttf b/data/fonts/RobotoCondensed-Bold.ttf
index 21c10f5..f0fd409 100644
--- a/data/fonts/RobotoCondensed-Bold.ttf
+++ b/data/fonts/RobotoCondensed-Bold.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-BoldItalic.ttf b/data/fonts/RobotoCondensed-BoldItalic.ttf
index d8edd2d..e67b02b 100644
--- a/data/fonts/RobotoCondensed-BoldItalic.ttf
+++ b/data/fonts/RobotoCondensed-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Italic.ttf b/data/fonts/RobotoCondensed-Italic.ttf
index 4dec2cf..a08414b 100644
--- a/data/fonts/RobotoCondensed-Italic.ttf
+++ b/data/fonts/RobotoCondensed-Italic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Regular.ttf b/data/fonts/RobotoCondensed-Regular.ttf
index 875ea1a..713fd30 100644
--- a/data/fonts/RobotoCondensed-Regular.ttf
+++ b/data/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index f2fd0c4..868227a 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -122,7 +122,7 @@
 receiving the app uses it to invite the specified contact to that
 social network. Most apps will be on the receiving-end of this operation. For example, the
 built-in People app invokes the invite intent when the user selects "Add connection" for a specific
-social app that's listed in a person's contact details.</p> 
+social app that's listed in a person's contact details.</p>
 
 <p>To make your app visible as in the "Add connection" list, your app must provide a sync adapter to
 sync contact information from your social network. You must then indicate to the system that your
@@ -327,7 +327,7 @@
 function). You may provide multiple mipmap levels. If the output texture has not been bound to a
 texture image, it will be automatically bound by the effect as a {@link
 android.opengl.GLES20#GL_TEXTURE_2D} and with one mipmap level (0), which will have the same
-size as the input.</p> 
+size as the input.</p>
 
 <p>All effects listed in {@link android.media.effect.EffectFactory} are guaranteed to be supported.
 However, some additional effects available from external libraries are not supported by all devices,
@@ -452,7 +452,7 @@
 value is greater than zero. Also, some devices may not support identification of eyes and mouth,
 in which case, those fields in the {@link android.hardware.Camera.Face} object will be null.</p>
 
-  
+
 <h4>Focus and metering areas</h4>
 
 <p>Camera apps can now control the areas that the camera uses for focus and for metering white
@@ -495,7 +495,7 @@
 
 <h4>Other camera features</h4>
 
-<ul>  
+<ul>
 <li>While recording video, you can now call {@link android.hardware.Camera#takePicture
 takePicture()} to save a photo without interrupting the video session. Before doing so, you should
 call {@link android.hardware.Camera.Parameters#isVideoSnapshotSupported} to be sure the hardware
@@ -775,7 +775,7 @@
   <li>When invoked, the {@link
 android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} and {@link
 android.view.View#sendAccessibilityEventUnchecked sendAccessibilityEventUnchecked()} methods defer
-to {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}. 
+to {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}.
   <p>Custom implementations of {@link android.view.View} might want to implement {@link
 android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} to
 attach additional accessibility information to the {@link
@@ -1022,46 +1022,6 @@
 
 
 
-<h3 id="RenderScript">RenderScript</h3>
-
-<p>Three major features have been added to RenderScript:</p>
-
-<ul>
-  <li>Off-screen rendering to a framebuffer object</li>
-  <li>Rendering inside a view</li>
-  <li>RS for each from the framework APIs</li>
-</ul>
-
-<p>The {@link android.renderscript.Allocation} class now supports a {@link
-android.renderscript.Allocation#USAGE_GRAPHICS_RENDER_TARGET} memory space, which allows you to
-render things directly into the {@link android.renderscript.Allocation} and use it as a framebuffer
-object.</p>
-
-<p>{@link android.renderscript.RSTextureView} provides a means to display RenderScript graphics
-inside of a {@link android.view.View},  unlike {@link android.renderscript.RSSurfaceView}, which
-creates a separate window. This key difference allows you to do things such as move, transform, or
-animate an {@link android.renderscript.RSTextureView} as well as draw RenderScript graphics inside
-a view that lies within an activity layout.</p>
-
-<p>The {@link android.renderscript.Script#forEach Script.forEach()} method allows you to call
-RenderScript compute scripts from the VM level and have them automatically delegated to available
-cores on the device. You do not use this method directly, but any compute RenderScript that you
-write will have a {@link android.renderscript.Script#forEach forEach()}  method that you can call in
-the reflected RenderScript class. You can call the reflected {@link
-android.renderscript.Script#forEach forEach()} method by passing in an input {@link
-android.renderscript.Allocation} to process, an output {@link android.renderscript.Allocation} to
-write the result to, and a {@link android.renderscript.FieldPacker} data structure in case the
-RenderScript needs more information. Only one of the {@link android.renderscript.Allocation}s is
-necessary and the data structure is optional.</p>
-
-
-
-
-
-
-
-
-
 <h3 id="Enterprise">Enterprise</h3>
 
 <p>Android 4.0 expands the capabilities for enterprise application with the following features.</p>
@@ -1758,7 +1718,7 @@
 notes for more information.</li>
     </ul>
   </dd>
-  
+
   <dt><a href="android-3.1.html">Android 3.1</a></dt>
   <dd>
     <ul>
@@ -1781,7 +1741,7 @@
 notes for many more new APIs.</li>
     </ul>
   </dd>
-  
+
   <dt><a href="android-3.2.html">Android 3.2</a></dt>
   <dd>
     <ul>
diff --git a/docs/html/guide/topics/graphics/renderscript/graphics.jd b/docs/html/guide/topics/graphics/renderscript/graphics.jd
deleted file mode 100644
index 58676ea..0000000
--- a/docs/html/guide/topics/graphics/renderscript/graphics.jd
+++ /dev/null
@@ -1,994 +0,0 @@
-page.title=Graphics
-parent.title=Renderscript
-parent.link=index.html
-
-@jd:body
-
-  <div id="qv-wrapper">
-    <div id="qv">
-      <h2>In this document</h2>
-
-      <ol>
-        <li>
-          <a href="#creating-graphics-rs">Creating a Graphics Renderscript</a>
-          <ol>
-            <li><a href="#creating-native">Creating the Renderscript file</a></li>
-            <li><a href="#creating-entry">Creating the Renderscript entry point class</a></li>
-            <li><a href="#creating-view">Creating the view class</a></li>
-            <li><a href="#creating-activity">Creating the activity class</a></li>
-          </ol>
-        </li>
-        <li>
-          <a href="#drawing">Drawing</a>
-          <ol>
-            <li><a href="#drawing-rsg">Simple drawing</a></li>
-            <li><a href="#drawing-mesh">Drawing with a mesh</a></li>
-          </ol>
-        </li>
-        <li>
-          <a href="#shaders">Shaders</a>
-          <ol>
-            <li><a href="#shader-bindings">Shader bindings</a></li>
-            <li><a href="#shader-sampler">Defining a sampler</a></li>
-          </ol>
-        </li>
-        <li>
-          <a href="#fbo">Rendering to a Framebuffer Object</a>
-        </li>
-      </ol>
-
-      <h2>Related Samples</h2>
-
-      <ol>
-        <li><a href="{@docRoot}resources/samples/RenderScript/Balls/index.html">Balls</a></li>
-
-        <li><a href="{@docRoot}resources/samples/RenderScript/Fountain/index.html">Fountain</a></li>
-
-        <li><a href="{@docRoot}resources/samples/RenderScript/FountainFbo/index.html">FountainFbo</a></li>        
-
-        <li><a href="{@docRoot}resources/samples/RenderScript/HelloWorld/index.html">Hello
-World</a></li>
-
-        <li><a
-href="{@docRoot}resources/samples/RenderScript/MiscSamples/index.html">Misc Samples</a></li>
-      </ol>
-    </div>
-  </div>
-
-  <p>Renderscript provides a number of graphics APIs for rendering, both at the Android
-  framework level as well as at the Renderscript runtime level. For instance, the Android framework APIs let you
-  create meshes and define shaders to customize the graphical rendering pipeline. The native
-  Renderscript graphics APIs let you draw the actual meshes to render your scene. You need to
-  be familiar with both APIs to appropriately render graphics on an Android-powered device.</p>
-
-  <h2 id="creating-graphics-rs">Creating a Graphics Renderscript</h2>
-
-  <p>Renderscript applications require various layers of code, so it is useful to create the following
-  files to help keep your application organized:</p>
-
-  <dl>
-    <dt>The Renderscript <code>.rs</code> file</dt>
-
-    <dd>This file contains the logic to do the graphics rendering.</dd>
-
-    <dt>The Renderscript entry point <code>.java</code> class</dt>
-
-    <dd>This class allows the view class to interact with the code defined in the <code>.rs</code>
-    file. This class contains a Renderscript object (instance of
-    <code>ScriptC_<em>renderscript_file</em></code>), which allows your Android framework code to
-    call the Renderscript code. In general, this class does much of the setup for Renderscript
-    such as shader and mesh building and memory allocation and binding. The SDK samples follow the
-    convention of naming this file ActivityRS.java,
-    where Activity is the name of your main activity class.</dd>
-
-    <dt>The view <code>.java</code> class</dt>
-
-    <dd>This class extends {@link android.renderscript.RSSurfaceView} or {@link
-    android.renderscript.RSTextureView} to provide a surface to render on. A {@link
-    android.renderscript.RSSurfaceView} consumes a whole window, but a {@link
-    android.renderscript.RSTextureView} allows you to draw Renderscript graphics inside of a
-    view and add it to a {@link android.view.ViewGroup} alongside
-    other views. In this class, you create a {@link android.renderscript.RenderScriptGL} context object
-    with a call to {@link android.renderscript.RSSurfaceView#createRenderScriptGL
-    RSSurfaceView.createRenderscriptGL()} or {@link android.renderscript.RSTextureView#createRenderScriptGL
-    RSTextureView.createRenderscriptGL()}. The {@link android.renderscript.RenderScriptGL} context object
-    contains information about the current rendering state of Renderscript such as the vertex and
-    fragment shaders. You pass this context object to the Renderscript entry point class, so that
-    class can modify the rendering context if needed and bind the Renderscript code to the context. Once bound,
-    the view class can use the Renderscript code to display graphics.
-    The view class should also implement callbacks for events inherited from {@link
-    android.view.View}, such as {@link android.view.View#onTouchEvent onTouchEvent()} and {@link
-    android.view.View#onKeyDown onKeyDown()} if you want to detect these types of user interactions.
-    The SDK samples follow the convention of naming this file ActivityView.java,
-    where Activity is the name of your main activity class</dd>
-
-    <dt>The activity <code>.java</code> class</dt>
-
-    <dd>This class is the main activity class and sets your {@link android.renderscript.RSSurfaceView} as the main content
-    view for this activity or uses the {@link android.renderscript.RSTextureView} alongside other views.</dd>
-  </dl>
-  <p>Figure 1 describes how these classes interact with one another in a graphics Renderscript:</p>
-  
-  <img src="{@docRoot}images/rs_graphics.png">
-  <p class="img-caption"><strong>Figure 1.</strong> Graphics Renderscript overview</p>
-
-
-  <p>The following sections describe how to create an application that uses a graphics Renderscript by using
-  the <a href="{@docRoot}resources/samples/RenderScript/Fountain/index.html">Renderscript Fountain
-  sample</a> that is provided in the SDK as a guide (some code has been modified from its original
-  form for simplicity).</p>
-
-  <h3 id="creating-native">Creating the Renderscript file</h3>
-
-  <p>Your Renderscript code resides in <code>.rs</code> and <code>.rsh</code> (headers) files in the
-  <code>&lt;project_root&gt;/src/</code> directory. This code contains the logic to render your
-  graphics and declares all other necessary items such as variables, structs,
-  and pointers. Every graphics <code>.rs</code> file generally contains the following items:</p>
-
-  <ul>
-    <li>A pragma declaration (<code>#pragma rs java_package_name(<em>package.name</em>)</code>) that declares
-    the package name of the <code>.java</code> reflection of this Renderscript.</li>
-
-    <li>A pragma declaration (<code>#pragma version(1)</code>) that declares the version of Renderscript that
-    you are using (1 is the only value for now).</li>
-
-    <li>A <code>#include "rs_graphics.rsh"</code> declaration.</li>
-
-    <li>A <code>root()</code> function. This is the main worker function for your Renderscript and
-    calls Renderscript graphics functions to render scenes. This function is called every time a
-    frame refresh occurs, which is specified as its return value. A <code>0</code> (zero) specified for
-    the return value says to only render the frame when a property of the scene that you are
-    rendering changes. A non-zero positive integer specifies the refresh rate of the frame in
-    milliseconds.
-
-      <p class="note"><strong>Note:</strong> The Renderscript runtime makes its best effort to
-      refresh the frame at the specified rate. For example, if you are creating a live wallpaper
-      and set the return value to 20, the Renderscript runtime renders the wallpaper at 50fps if it has just
-      enough or more resources to do so. It renders as fast as it can if not enough resources
-      are available.</p>
-
-      <p>For more information on using the Renderscript graphics functions, see the <a href=
-      "#drawing">Drawing</a> section.</p>
-    </li>
-
-    <li>An <code>init()</code> function. This allows you to do initialization of your
-    Renderscript before the <code>root()</code> function runs, such as assigning values to variables. This
-    function runs once and is called automatically when the Renderscript starts, before anything
-    else in your Renderscript. Creating this function is optional.</li>
-
-    <li>Any variables, pointers, and structures that you wish to use in your Renderscript code (can
-    be declared in <code>.rsh</code> files if desired)</li>
-  </ul>
-
-  <p>The following code shows how the <code>fountain.rs</code> file is implemented:</p>
-  <pre>
-#pragma version(1)
-
-// Tell which java package name the reflected files should belong to
-#pragma rs java_package_name(com.example.android.rs.fountain)
-
-//declare shader binding
-#pragma stateFragment(parent)
-
-// header with graphics APIs, must include explicitly
-#include "rs_graphics.rsh"
-
-static int newPart = 0;
-
-// the mesh to render
-rs_mesh partMesh;
-
-// the point representing where a particle is rendered
-typedef struct __attribute__((packed, aligned(4))) Point {
-    float2 delta;
-    float2 position;
-    uchar4 color;
-} Point_t;
-Point_t *point;
-
-// main worker function that renders particles onto the screen
-int root() {
-    float dt = min(rsGetDt(), 0.1f);
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    const float height = rsgGetHeight();
-    const int size = rsAllocationGetDimX(rsGetAllocation(point));
-    float dy2 = dt * (10.f);
-    Point_t * p = point;
-    for (int ct=0; ct &lt; size; ct++) {
-        p-&gt;delta.y += dy2;
-        p-&gt;position += p-&gt;delta;
-        if ((p-&gt;position.y &gt; height) &amp;&amp; (p-&gt;delta.y &gt; 0)) {
-            p-&gt;delta.y *= -0.3f;
-        }
-        p++;
-    }
-
-    rsgDrawMesh(partMesh);
-    return 1;
-}
-
-// adds particles to the screen to render
-static float4 partColor[10];
-void addParticles(int rate, float x, float y, int index, bool newColor)
-{
-    if (newColor) {
-        partColor[index].x = rsRand(0.5f, 1.0f);
-        partColor[index].y = rsRand(1.0f);
-        partColor[index].z = rsRand(1.0f);
-    }
-    float rMax = ((float)rate) * 0.02f;
-    int size = rsAllocationGetDimX(rsGetAllocation(point));
-    uchar4 c = rsPackColorTo8888(partColor[index]);
-
-    Point_t * np = &amp;point[newPart];
-    float2 p = {x, y};
-    while (rate--) {
-        float angle = rsRand(3.14f * 2.f);
-        float len = rsRand(rMax);
-        np-&gt;delta.x = len * sin(angle);
-        np-&gt;delta.y = len * cos(angle);
-        np-&gt;position = p;
-        np-&gt;color = c;
-        newPart++;
-        np++;
-        if (newPart &gt;= size) {
-            newPart = 0;
-            np = &amp;point[newPart];
-        }
-    }
-}
-</pre>
-
-  <h3 id="creating-entry">Creating the Renderscript entry point class</h3>
-
-  <p>When you create a Renderscript (<code>.rs</code>) file, it is helpful to create a
-  corresponding Android framework class that is an entry point into the <code>.rs</code> file.
-  The most important thing this class does is receive a {@link android.renderscript.RenderScriptGL} rendering context
-  object from the <a href="#creating-view">view class</a> and binds the actual Renderscript
-  code to the rendering context. This notifies your view class of the code that it needs
-  to render graphics.
-  </p>
-
-  <p>In addition, this class should contain all of the things needed to set up Renderscript.
-  Some important things that you need to do in this class are:</p>
-
-  <ul>
-    <li>Create a Renderscript object 
-  <code>ScriptC_<em>rs_filename</em></code>. The Renderscript object is attached to the Renderscript bytecode, which is platform-independent and
-  gets compiled on the device when the Renderscript application runs. The bytecode is referenced
-  as a raw resource and is passed into the constructor for the Renderscript object.
-  For example, this is how the <a href="{@docRoot}resources/samples/RenderScript/Fountain/index.html">Fountain</a>
-  sample creates the Renderscript object:
-  <pre>
-  RenderScriptGL rs;  //obtained from the view class
-  Resources res;      //obtained from the view class
-  ...
-  ScriptC_fountain mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain);
-  </pre>
-  </li>
-  <li>Allocate any necessary memory and bind it to your Renderscript code via the Renderscript object.</li>
-  <li>Build any necessary meshes and bind them to the Renderscript code via the Renderscript object.</li>
-  <li>Create any necessary programs and bind them to the Renderscript code via the Renderscript object.</li>
-  </ul>
-
-  <p>The following code shows how the <a href=
-  "{@docRoot}resources/samples/RenderScript/Fountain/src/com/example/android/rs/fountain/FountainRS.html">
-  FountainRS</a> class is implemented:</p>
-  <pre>
-package com.example.android.rs.fountain;
-
-import android.content.res.Resources;
-import android.renderscript.*;
-import android.util.Log;
-
-public class FountainRS {
-    public static final int PART_COUNT = 50000;
-
-    public FountainRS() {
-    }
-
-    /**
-     * This provides us with the Renderscript context and resources
-     * that allow us to create the Renderscript object
-     */
-    private Resources mRes;
-    private RenderScriptGL mRS;
-
-    // Renderscript object
-    private ScriptC_fountain mScript;
-
-    // Called by the view class to initialize the Renderscript context and renderer
-    public void init(RenderScriptGL rs, Resources res) {
-        mRS = rs;
-        mRes = res;
-
-        /**
-         * Create a shader and bind to the Renderscript context
-         */
-        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
-        pfb.setVaryingColor(true);
-        rs.bindProgramFragment(pfb.create());
-
-        /**
-         * Allocate memory for the particles to render and create the mesh to draw
-         */
-        ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);
-        Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
-        smb.addVertexAllocation(points.getAllocation());
-        smb.addIndexSetType(Mesh.Primitive.POINT);
-        Mesh sm = smb.create();
-
-       /**
-        * Create and bind the Renderscript object to the Renderscript context
-        */
-        mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain);
-        mScript.set_partMesh(sm);
-        mScript.bind_point(points);
-        mRS.bindRootScript(mScript);
-    }
-
-    boolean holdingColor[] = new boolean[10];
-
-    /**
-     * Calls Renderscript functions (invoke_addParticles)
-     * via the Renderscript object to add particles to render
-     * based on where a user touches the screen.
-     */
-    public void newTouchPosition(float x, float y, float pressure, int id) {
-        if (id &gt;= holdingColor.length) {
-            return;
-        }
-        int rate = (int)(pressure * pressure * 500.f);
-        if (rate &gt; 500) {
-            rate = 500;
-        }
-        if (rate &gt; 0) {
-            mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]);
-            holdingColor[id] = true;
-        } else {
-            holdingColor[id] = false;
-        }
-
-    }
-}
-</pre>
-
-
-  <h3 id="creating-view">Creating the view class</h3>
-
-
-  <p>To display graphics, you need a view to render on. Create a class that extends {@link
-  android.renderscript.RSSurfaceView} or {@link android.renderscript.RSTextureView}. This class
-  allows you to create a {@link android.renderscript.RenderScriptGL} context object by calling and
-  pass it to the Rendscript entry point class to bind the two. Once bound, the content is aware
-  of the code that it needs to use to render graphics with. If your Renderscript code
-  depends on any type of information that the view is aware of, such as touches from the user,
-  you can also use this class to relay that information to the Renderscript entry point class.
-  The following code shows how the <code>FountainView</code> class is implemented:</p>
-  <pre>
-package com.example.android.rs.fountain;
-
-import android.renderscript.RSTextureView;
-import android.renderscript.RenderScriptGL;
-import android.content.Context;
-import android.view.MotionEvent;
-
-public class FountainView extends RSTextureView {
-
-    public FountainView(Context context) {
-        super(context);
-    }
-    // Renderscript context
-    private RenderScriptGL mRS;
-    // Renderscript entry point object that calls Renderscript code
-    private FountainRS mRender;
-
-    /**
-     * Create Renderscript context and initialize Renderscript entry point
-     */
-    &#064;Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        android.util.Log.e("rs", "onAttachedToWindow");
-        if (mRS == null) {
-            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            mRS = createRenderScriptGL(sc);
-            mRender = new FountainRS();
-            mRender.init(mRS, getResources());
-        }
-    }
-
-    &#064;Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        android.util.Log.e("rs", "onDetachedFromWindow");
-        if (mRS != null) {
-            mRS = null;
-            destroyRenderScriptGL();
-        }
-    }
-
-
-    /**
-     * Use callbacks to relay data to Renderscript entry point class
-     */
-    &#064;Override
-    public boolean onTouchEvent(MotionEvent ev)
-    {
-        int act = ev.getActionMasked();
-        if (act == ev.ACTION_UP) {
-            mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
-            return false;
-        } else if (act == MotionEvent.ACTION_POINTER_UP) {
-            // only one pointer going up, we can get the index like this
-            int pointerIndex = ev.getActionIndex();
-            int pointerId = ev.getPointerId(pointerIndex);
-            mRender.newTouchPosition(0, 0, 0, pointerId);
-        }
-        int count = ev.getHistorySize();
-        int pcount = ev.getPointerCount();
-
-        for (int p=0; p &lt; pcount; p++) {
-            int id = ev.getPointerId(p);
-            mRender.newTouchPosition(ev.getX(p),
-                                     ev.getY(p),
-                                     ev.getPressure(p),
-                                     id);
-
-            for (int i=0; i &lt; count; i++) {
-                mRender.newTouchPosition(ev.getHistoricalX(p, i),
-                                         ev.getHistoricalY(p, i),
-                                         ev.getHistoricalPressure(p, i),
-                                         id);
-            }
-        }
-        return true;
-    }
-}
-</pre>
-
-  <h3 id="creating-activity">Creating the activity class</h3>
-
-  <p>Applications that use Renderscript still behave like normal Android applications, so you
-   need an activity class that handles activity lifecycle callback events appropriately. The activity class
-   also sets your {@link android.renderscript.RSSurfaceView} view class to be the main content view of the
-   activity or uses your {@link android.renderscript.RSTextureView}
-  in a {@link android.view.ViewGroup} alongside other views.</p>
-
-  <p>The following code shows how the <a href="{@docRoot}resources/samples/RenderScript/Fountain/index.html">Fountain</a>
-  sample declares its activity class:</p>
-  <pre>
-package com.example.android.rs.fountain;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-public class Fountain extends Activity {
-
-    private static final String LOG_TAG = "libRS_jni";
-    private static final boolean DEBUG  = false;
-    private static final boolean LOG_ENABLED = false;
-
-    private FountainView mView;
-
-    &#064;Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        // Create our Preview view and set it as 
-        // the content of our activity
-        mView = new FountainView(this);
-        setContentView(mView);
-    }
-
-    &#064;Override
-    protected void onResume() {
-        Log.e("rs", "onResume");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onResume();
-        mView.resume();
-    }
-
-    &#064;Override
-    protected void onPause() {
-        Log.e("rs", "onPause");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onPause();
-        mView.pause();
-
-    }
-
-    static void log(String message) {
-        if (LOG_ENABLED) {
-            Log.v(LOG_TAG, message);
-        }
-    }
-}
-</pre>
-
-<p>Now that you have an idea of what is involved in a Renderscript graphics application, you can
-start building your own. It might be easiest to begin with one of the
-<a href="{@docRoot}resources/samples/RenderScript/index.html">Renderscript samples</a> as a starting
-point if this is your first time using Renderscript.</p>
-
-  <h2 id="drawing">Drawing</h2>
-  <p>The following sections describe how to use the graphics functions to draw with Renderscript.</p>
-
-  <h3 id="drawing-rsg">Simple drawing</h3>
-
-  <p>The native Renderscript APIs provide a few convenient functions to easily draw a polygon or text to
-  the screen. You call these in your <code>root()</code> function to have them render to the {@link
-  android.renderscript.RSSurfaceView} or {@link android.renderscript.RSTextureView}. These functions are
-  available for simple drawing and should not be used for complex graphics rendering:</p>
-
-  <ul>
-    <li><code>rsgDrawRect()</code>: Sets up a mesh and draws a rectangle to the screen. It uses the
-    top left vertex and bottom right vertex of the rectangle to draw.</li>
-
-    <li><code>rsgDrawQuad()</code>: Sets up a mesh and draws a quadrilateral to the screen.</li>
-
-    <li><code>rsgDrawQuadTexCoords()</code>: Sets up a mesh and draws a quadrilateral to the screen
-    using the provided coordinates of a texture.</li>
-
-    <li><code>rsgDrawText()</code>: Draws specified text to the screen. Use <code>rsgFontColor()</code>
-    to set the color of the text.</li>
-  </ul>
-
-  <h3 id="drawing-mesh">Drawing with a mesh</h3>
-
-  <p>When you want to render complex scenes to the screen, instantiate a {@link
-  android.renderscript.Mesh} and draw it with <code>rsgDrawMesh()</code>. A {@link
-  android.renderscript.Mesh} is a collection of allocations that represent vertex data (positions,
-  normals, texture coordinates) and index data that provides information on how to draw triangles
-  and lines with the provided vertex data. You can build a Mesh in three different ways:</p>
-
-  <ul>
-    <li>Build the mesh with the {@link android.renderscript.Mesh.TriangleMeshBuilder} class, which
-    allows you to specify a set of vertices and indices for each triangle that you want to draw.</li>
-
-    <li>Build the mesh using an {@link android.renderscript.Allocation} or a set of {@link
-    android.renderscript.Allocation}s with the {@link android.renderscript.Mesh.AllocationBuilder}
-    class. This approach allows you to build a mesh with vertices already stored in memory, which allows you
-    to specify the vertices in Renderscript or Android framework code.</li>
-
-    <li>Build the mesh with the {@link android.renderscript.Mesh.Builder} class. You should use
-    this convenience method when you know the data types you want to use to build your mesh, but
-    don't want to make separate memory allocations like with {@link
-    android.renderscript.Mesh.AllocationBuilder}. You can specify the types that you want and this
-    mesh builder automatically creates the memory allocations for you.</li>
-  </ul>
-
-  <p>To create a mesh using the {@link android.renderscript.Mesh.TriangleMeshBuilder}, you need to
-  supply it with a set of vertices and the indices for the vertices that comprise the triangle. For
-  example, the following code specifies three vertices, which are added to an internal array,
-  indexed in the order they were added. The call to {@link
-  android.renderscript.Mesh.TriangleMeshBuilder#addTriangle addTriangle()} draws the triangle with
-  vertex 0, 1, and 2 (the vertices are drawn counter-clockwise).</p>
-  <pre>
-int float2VtxSize = 2;
-Mesh.TriangleMeshBuilder triangles = new Mesh.TriangleMeshBuilder(renderscriptGL,
-float2VtxSize, Mesh.TriangleMeshBuilder.COLOR);
-triangles.addVertex(300.f, 300.f);
-triangles.addVertex(150.f, 450.f);
-triangles.addVertex(450.f, 450.f);
-triangles.addTriangle(0 , 1, 2);
-Mesh smP = triangle.create(true);
-script.set_mesh(smP);
-</pre>
-
-  <p>To draw a mesh using the {@link android.renderscript.Mesh.AllocationBuilder}, you need to
-  supply it with one or more allocations that contain the vertex data:</p>
-  <pre>
-Allocation vertices;
-
-...
-Mesh.AllocationBuilder triangle = new Mesh.AllocationBuilder(mRS);
-smb.addVertexAllocation(vertices.getAllocation());
-smb.addIndexSetType(Mesh.Primitive.TRIANGLE);
-Mesh smP = smb.create();
-script.set_mesh(smP);
-</pre>
-
-  <p>In your Renderscript code, draw the built mesh to the screen:</p>
-  <pre>
-rs_mesh mesh;
-...
-
-int root(){
-...
-rsgDrawMesh(mesh);
-...
-return 0; //specify a non zero, positive integer to specify the frame refresh.
-          //0 refreshes the frame only when the mesh changes.
-}
-</pre>
-
-  <h2 id="shader">Programs</h2>
-
-  <p>You can attach four program objects to the {@link android.renderscript.RenderScriptGL} context
-  to customize the rendering pipeline. For example, you can create vertex and fragment shaders in
-  GLSL or build a raster program object that controls culling. The four programs mirror a
-  traditional graphical rendering pipeline:</p>
-
-  <table>
-    <tr>
-      <th>Android Object Type</th>
-
-      <th>Renderscript Native Type</th>
-
-      <th>Description</th>
-    </tr>
-
-    <tr>
-      <td>{@link android.renderscript.ProgramVertex}</td>
-
-      <td>rs_program_vertex</td>
-
-      <td>
-        <p>The Renderscript vertex program, also known as a vertex shader, describes the stage in
-        the graphics pipeline responsible for manipulating geometric data in a user-defined way.
-        The object is constructed by providing Renderscript with the following data:</p>
-
-        <ul>
-          <li>An {@link android.renderscript.Element} describing its varying inputs or attributes</li>
-
-          <li>GLSL shader string that defines the body of the program</li>
-
-          <li>a {@link android.renderscript.Type} that describes the layout of an
-          Allocation containing constant or uniform inputs</li>
-        </ul>
-
-        <p>Once the program is created, bind it to the {@link android.renderscript.RenderScriptGL}
-        graphics context by calling {@link android.renderscript.RenderScriptGL#bindProgramVertex
-        bindProgramVertex()}. It is then used for all subsequent draw calls until you bind a new
-        program. If the program has constant inputs, the user needs to bind an allocation
-        containing those inputs. The allocation's type must match the one provided during creation.
-        </p>
-
-        <p>The Renderscript runtime then does all the necessary plumbing to send those constants to
-        the graphics hardware. Varying inputs to the shader, such as position, normal, and texture
-        coordinates are matched by name between the input {@link android.renderscript.Element}
-        and the mesh object that is being drawn. The signatures don't have to be exact or in any
-        strict order. As long as the input name in the shader matches a channel name and size
-        available on the mesh, the Renderscript runtime handles connecting the two. Unlike OpenGL
-        there is no need to link the vertex and fragment programs.</p>
-
-        <p>To bind shader constants to the program, declare a <code>struct</code> that contains the necessary
-        shader constants in your Renderscript code. This <code>struct</code> is generated into a
-        reflected class that you can use as a constant input element during the program's creation.
-        It is an easy way to create an instance of this <code>struct</code> as an allocation. You would then
-        bind this {@link android.renderscript.Allocation} to the program and the
-        Renderscript runtime sends the data that is contained in the <code>struct</code> to the hardware
-        when necessary. To update shader constants, you change the values in the
-        {@link android.renderscript.Allocation} and notify the Renderscript
-        code of the change.</p>
-
-        <p>The {@link android.renderscript.ProgramVertexFixedFunction.Builder} class also
-        lets you build a simple vertex shader without writing GLSL code.
-        </p>
-      </td>
-    </tr>
-
-    <tr>
-      <td>{@link android.renderscript.ProgramFragment}</td>
-
-      <td>rs_program_fragment</td>
-
-      <td>
-        <p>The Renderscript fragment program, also known as a fragment shader, is responsible for
-        manipulating pixel data in a user-defined way. It's constructed from a GLSL shader string
-        containing the program body, texture inputs, and a {@link android.renderscript.Type}
-        object that describes the constants
-        used by the program. Like the vertex programs, when an {@link android.renderscript.Allocation}
-        with constant input
-        values is bound to the shader, its values are sent to the graphics program automatically.
-        Note that the values inside the {@link android.renderscript.Allocation} are not explicitly tracked.
-        If they change between two draw calls using the same program object, notify the runtime of that change by
-        calling <code>rsgAllocationSyncAll()</code>, so it can send the new values to hardware. Communication
-        between the vertex and fragment programs is handled internally in the GLSL code. For
-        example, if the fragment program is expecting a varying input called <code>varTex0</code>, the GLSL code
-        inside the program vertex must provide it.</p>
-
-        <p>To bind shader constructs to the program, declare a <code>struct</code> that contains the necessary
-        shader constants in your Renderscript code. This <code>struct</code> is generated into a
-        reflected class that you can use as a constant input element during the program's creation.
-        It is an easy way to create an instance of this <code>struct</code> as an allocation. You would then
-        bind this {@link android.renderscript.Allocation} to the program and the
-        Renderscript runtime sends the data that is contained in the <code>struct</code> to the hardware
-        when necessary. To update shader constants, you change the values in the
-        {@link android.renderscript.Allocation} and notify the Renderscript
-        code of the change.</p>
-
-        <p>The {@link android.renderscript.ProgramFragmentFixedFunction.Builder} class also
-        lets you build a simple fragment shader without writing GLSL code.
-        </p>
-      </td>
-    </tr>
-
-    <tr>
-      <td>{@link android.renderscript.ProgramStore}</td>
-
-      <td>rs_program_store</td>
-
-      <td>The Renderscript store program contains a set of parameters that control how the graphics
-      hardware writes to the framebuffer. It could be used to enable and disable depth writes and
-      testing, setup various blending modes for effects like transparency and define write masks
-      for color components.</td>
-    </tr>
-
-    <tr>
-      <td>{@link android.renderscript.ProgramRaster}</td>
-
-      <td>rs_program_raster</td>
-
-      <td>The Renderscript raster program is primarily used to specify whether point sprites are enabled and to
-      control the culling mode. By default back faces are culled.</td>
-    </tr>
-  </table>
-
-  <p>The following example defines a vertex shader in GLSL and binds it to a Renderscript context object:</p>
-  <pre>
-    private RenderScriptGL glRenderer;      //rendering context
-    private ScriptField_Point mPoints;      //vertices
-    private ScriptField_VpConsts mVpConsts; //shader constants
-
-    ...
-
-     ProgramVertex.Builder sb = new ProgramVertex.Builder(glRenderer);
-        String t =  "varying vec4 varColor;\n" +
-                    "void main() {\n" +
-                    "  vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
-                    "  pos.xy = ATTRIB_position;\n" +
-                    "  gl_Position = UNI_MVP * pos;\n" +
-                    "  varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
-                    "  gl_PointSize = ATTRIB_size;\n" +
-                    "}\n";
-        sb.setShader(t);
-        sb.addConstant(mVpConsts.getType());
-        sb.addInput(mPoints.getElement());
-        ProgramVertex pvs = sb.create();
-        pvs.bindConstants(mVpConsts.getAllocation(), 0);
-        glRenderer.bindProgramVertex(pvs);
-</pre>
-
-
-  <p>The <a href=
-  "{@docRoot}resources/samples/RenderScript/MiscSamples/src/com/example/android/rs/miscsamples/RsRenderStatesRS.html">
-  RsRenderStatesRS</a> sample has many examples on how to create a shader without writing GLSL.</p>
-
-  <h3 id="shader-bindings">Program bindings</h3>
-
-  <p>You can also declare four pragmas that control default program bindings to the {@link
-  android.renderscript.RenderScriptGL} context when the script is executing:</p>
-
-  <ul>
-    <li><code>stateVertex</code></li>
-
-    <li><code>stateFragment</code></li>
-
-    <li><code>stateRaster</code></li>
-
-    <li><code>stateStore</code></li>
-  </ul>
-
-  <p>The possible values for each pragma are <code>parent</code> or <code>default</code>. Using
-  <code>default</code> binds the shaders to the graphical context with the system defaults.</p>
-
-  <p>Using <code>parent</code> binds the shaders in the same manner as it is bound in the calling
-  script. If this is the root script, the parent state is taken from the bind points that are set
-  by the {@link android.renderscript.RenderScriptGL} bind methods.</p>
-
-  <p>For example, you can define this at the top of your graphics Renderscript code to have
-  the vertex and store programs inherent the bind properties from their parent scripts:</p>
-  <pre>
-#pragma stateVertex(parent)
-#pragma stateStore(parent)
-</pre>
-
-  <h3 id="shader-sampler">Defining a sampler</h3>
-
-  <p>A {@link android.renderscript.Sampler} object defines how data is extracted from textures.
-  Samplers are bound to a {@link android.renderscript.ProgramFragment} alongside the texture
-  whose sampling they control. These
-  objects are used to specify such things as edge clamping behavior, whether mip-maps are used, and
-  the amount of anisotropy required. There might be situations where hardware does not support the
-  desired behavior of the sampler. In these cases, the Renderscript runtime attempts to provide the
-  closest possible approximation. For example, the user requested 16x anisotropy, but only 8x was
-  set because it's the best available on the hardware.</p>
-
-  <p>The <a href=
-  "{@docRoot}resources/samples/RenderScript/MiscSamples/src/com/example/android/rs/miscsamples/RsRenderStatesRS.html">
-  RsRenderStatesRS</a> sample has many examples on how to create a sampler and bind it to a
-  Fragment program.</p>
-
-
-
-<h2 id="fbo">Rendering to a Framebuffer Object</h2>
-
-<p>Framebuffer objects allow you to render offscreen instead of in the default onscreen
-framebuffer. This approach might be useful for situations where you need to post-process a texture before
-rendering it to the screen, or when you want to composite two scenes in one such as rendering a rear-view
-mirror of a car. There are two buffers associated with a framebuffer object: a color buffer
-and a depth buffer. The color buffer (required) contains the actual pixel data of the scene
-that you are rendering, and the depth buffer (optional) contains the values necessary to figure
-out what vertices are drawn depending on their z-values.</p>
-
-<p>In general, you need to do the following to render to a framebuffer object:</p>
-
-<ul>
-  <li>Create {@link android.renderscript.Allocation} objects for the color buffer and
-  depth buffer (if needed). Specify the {@link
-  android.renderscript.Allocation#USAGE_GRAPHICS_RENDER_TARGET} usage attribute for these
-  allocations to notify the Renderscript runtime to use these allocations for the framebuffer
-  object. For the color buffer allocation, you most likely need to declare the {@link
-  android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE} usage attribute
-  to use the color buffer as a texture, which is the most common use of the framebuffer object.</li>
-
-  <li>Tell the Renderscript runtime to render to the framebuffer object instead of the default
-  framebuffer by calling <code>rsgBindColorTarget()</code> and passing it the color buffer
-  allocation. If applicable, call <code>rsgBindDepthTarget()</code> passing in the depth buffer
-  allocation as well.</li>
-
-  <li>Render your scene normally with the <code>rsgDraw</code> functions. The scene will be
-  rendered into the color buffer instead of the default onscreen framebuffer.</li>
-
-  <li>When done, tell the Renderscript runtime stop rendering to the color buffer and back
-  to the default framebuffer by calling <code>rsgClearAllRenderTargets()</code>.</li>
-
-  <li>Create a fragment shader and bind a the color buffer to it as a texture.</li>
-
-  <li>Render your scene to the default framebuffer. The texture will be used according
-  to the way you setup your fragment shader.</li>
-</ul>
-
-<p>The following example shows you how to render to a framebuffer object by modifying the
-<a href="{@docRoot}guide/resources/renderscript/Fountain/">Fountain</a> Renderscript sample. The end
-result is the <a href="{@docRoot}guide/resources/renderscript/FountainFBO/">FountainFBO</a> sample.
-The modifications render the exact same scene into a framebuffer object as it does the default
-framebuffer. The framebuffer object is then rendered into the default framebuffer in a small
-area at the top left corner of the screen.</p>
-
-<ol>
-  <li>Modify <code>fountain.rs</code> and add the following global variables. This creates setter
-  methods when this file is reflected into a <code>.java</code> file, allowing you to allocate
-  memory in your Android framework code and binding it to the Renderscript runtime.
-<pre>
-//allocation for color buffer
-rs_allocation gColorBuffer;
-//fragment shader for rendering without a texture (used for rendering to framebuffer object)
-rs_program_fragment gProgramFragment;
-//fragment shader for rendering with a texture (used for rendering to default framebuffer)
-rs_program_fragment gTextureProgramFragment;
-</pre>
-  </li>
-
-  <li>Modify the root function of <code>fountain.rs</code> to look like the following code. The
-  modifications are commented:
-<pre>
-int root() {
-    float dt = min(rsGetDt(), 0.1f);
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    const float height = rsgGetHeight();
-    const int size = rsAllocationGetDimX(rsGetAllocation(point));
-    float dy2 = dt * (10.f);
-    Point_t * p = point;
-    for (int ct=0; ct < size; ct++) {
-        p->delta.y += dy2;
-        p->position += p->delta;
-        if ((p->position.y > height) && (p->delta.y > 0)) {
-            p->delta.y *= -0.3f;
-        }
-        p++;
-    }
-    //Tell Renderscript runtime to render to the frame buffer object
-    rsgBindColorTarget(gColorBuffer, 0);
-    //Begin rendering on a white background
-    rsgClearColor(1.f, 1.f, 1.f, 1.f);
-    rsgDrawMesh(partMesh);
-
-    //When done, tell Renderscript runtime to stop rendering to framebuffer object
-    rsgClearAllRenderTargets();
-
-    //Bind a new fragment shader that declares the framebuffer object to be used as a texture
-    rsgBindProgramFragment(gTextureProgramFragment);
-
-    //Bind the framebuffer object to the fragment shader at slot 0 as a texture
-    rsgBindTexture(gTextureProgramFragment, 0, gColorBuffer);
-    //Draw a quad using the framebuffer object as the texture
-    float startX = 10, startY = 10;
-    float s = 256;
-    rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
-                         startX, startY + s, 0, 0, 0,
-                         startX + s, startY + s, 0, 1, 0,
-                         startX + s, startY, 0, 1, 1);
-
-    //Rebind the original fragment shader to render as normal
-    rsgBindProgramFragment(gProgramFragment);
-
-    //Render the main scene
-    rsgDrawMesh(partMesh);
-
-    return 1;
-}
-</pre>
-  </li>
-
-  <li>In the <code>FountainRS.java</code> file, modify the <code>init()</code> method to look
-  like the following code. The modifications are commented:
-
-<pre>
-/* Add necessary members */
-private ScriptC_fountainfbo mScript;
-private Allocation mColorBuffer;
-private ProgramFragment mProgramFragment;
-private ProgramFragment mTextureProgramFragment;
-
-public void init(RenderScriptGL rs, Resources res) {
-    mRS = rs;
-    mRes = res;
-
-    ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);
-
-    Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
-    smb.addVertexAllocation(points.getAllocation());
-    smb.addIndexSetType(Mesh.Primitive.POINT);
-    Mesh sm = smb.create();
-
-    mScript = new ScriptC_fountainfbo(mRS, mRes, R.raw.fountainfbo);
-    mScript.set_partMesh(sm);
-    mScript.bind_point(points);
-
-    ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
-    pfb.setVaryingColor(true);
-    mProgramFragment = pfb.create();
-    mScript.set_gProgramFragment(mProgramFragment);
-
-    /* Second fragment shader to use a texture (framebuffer object) to draw with */
-    pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
-        ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
-
-    /* Set the fragment shader in the Renderscript runtime */
-    mTextureProgramFragment = pfb.create();
-    mScript.set_gTextureProgramFragment(mTextureProgramFragment);
-
-    /* Create the allocation for the color buffer */
-    Type.Builder colorBuilder = new Type.Builder(mRS, Element.RGBA_8888(mRS));
-    colorBuilder.setX(256).setY(256);
-    mColorBuffer = Allocation.createTyped(mRS, colorBuilder.create(),
-    Allocation.USAGE_GRAPHICS_TEXTURE |
-    Allocation.USAGE_GRAPHICS_RENDER_TARGET);
-
-    /* Set the allocation in the Renderscript runtime */
-    mScript.set_gColorBuffer(mColorBuffer);
-
-    mRS.bindRootScript(mScript);
-}
-</pre>
-
-<p class="note"><strong>Note:</strong> This sample doesn't use a depth buffer, but the following code
-shows you how to declare an example depth buffer if you need to use
-one for your application. The depth buffer must have the same dimensions as the color buffer:
-
-<pre>
-Allocation mDepthBuffer;
-
-...
-
-Type.Builder b = new Type.Builder(mRS, Element.createPixel(mRS, DataType.UNSIGNED_16,
-    DataKind.PIXEL_DEPTH));
-b.setX(256).setY(256);
-mDepthBuffer = Allocation.createTyped(mRS, b.create(),
-Allocation.USAGE_GRAPHICS_RENDER_TARGET);
-
-</pre>
-</p>
-</li>
-
-  <li>Run and use the sample. The smaller, white quad on the top-left corner is using the
-  framebuffer object as a texture, which renders the same scene as the main rendering.</li>
-</ol>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 0f18861..2615bee 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -240,7 +240,7 @@
     &lt;string name="app_name">My First App&lt;/string>
     &lt;string name="edit_message">Enter a message&lt;/string>
     &lt;string name="button_send">Send&lt;/string>
-    &lt;string name="menu_settings">Settings&lt;/string>
+    &lt;string name="action_settings">Settings&lt;/string>
     &lt;string name="title_activity_main">MainActivity&lt;/string>
 &lt;/resources>
 </pre>
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index 42b508b..8b0222a 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -28,6 +28,7 @@
 import android.util.TypedValue;
 
 /**
+ * @hide
  * @deprecated in API 16
  * FileA3D allows users to load Renderscript objects from files
  * or resources stored on disk. It could be used to load items
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index 8a49abb..1a8d5bf 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -30,8 +30,9 @@
 import android.util.TypedValue;
 
 /**
+ * @hide
  * @deprecated in API 16
- * <p>This class gives users a simple way to draw hardware accelerated text. 
+ * <p>This class gives users a simple way to draw hardware accelerated text.
  * Internally, the glyphs are rendered using the Freetype library and an internal cache of
  * rendered glyph bitmaps is maintained. Each font object represents a combination of a typeface,
  * and point size. You can create multiple font objects to represent styles such as bold or italic text,
@@ -43,7 +44,7 @@
  * render large batches of text in sequence. It is also more efficient to render multiple
  * characters at once instead of one by one to improve draw call batching.</p>
  * <p>Font color and transparency are not part of the font object and you can freely modify
- * them in the script to suit the user's rendering needs. Font colors work as a state machine. 
+ * them in the script to suit the user's rendering needs. Font colors work as a state machine.
  * Every new call to draw text uses the last color set in the script.</p>
  **/
 public class Font extends BaseObj {
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index 7210513..d0d383d 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -21,6 +21,7 @@
 import android.util.Log;
 
 /**
+ * @hide
  * @deprecated in API 16
  * <p>This class is a container for geometric data displayed with
  * Renderscript. Internally, a mesh is a collection of allocations that
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index d9f64c6..9bd103e 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -26,6 +26,7 @@
 
 
 /**
+ * @hide
  *
  * Program is a base class for all the objects that modify
  * various stages of the graphics pipeline
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index 69968ac..dd0f9f5 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -21,6 +21,7 @@
 
 
 /**
+ * @hide
  * @deprecated in API 16
  * <p>The Renderscript fragment program, also known as fragment shader is responsible
  * for manipulating pixel data in a user defined way. It's constructed from a GLSL
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
index 848c5a3..8ae1777 100644
--- a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -21,6 +21,7 @@
 
 
 /**
+ * @hide
  * @deprecated in API 16
  * <p>ProgramFragmentFixedFunction is a helper class that provides
  * a way to make a simple fragment shader without writing any
diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java
index c44521b..216cb4e 100644
--- a/graphics/java/android/renderscript/ProgramRaster.java
+++ b/graphics/java/android/renderscript/ProgramRaster.java
@@ -21,6 +21,7 @@
 
 
 /**
+ * @hide
  * @deprecated in API 16
  * Program raster is primarily used to specify whether point sprites are enabled and to control
  * the culling mode. By default, back faces are culled.
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java
index d0fd6e5..dac9e76 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/graphics/java/android/renderscript/ProgramStore.java
@@ -21,6 +21,7 @@
 
 
 /**
+ * @hide
  * <p>ProgramStore contains a set of parameters that control how
  * the graphics hardware handles writes to the framebuffer.
  * It could be used to:</p>
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 2bd5124..50e32f6 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
- /**
+/**
+ * @hide
  * <p>The Renderscript vertex program, also known as a vertex shader, describes a stage in
  * the graphics pipeline responsible for manipulating geometric data in a user-defined way.
  * The object is constructed by providing the Renderscript system with the following data:</p>
@@ -43,6 +44,7 @@
 
 
 /**
+ * @hide
  * @deprecated in API 16
  * ProgramVertex, also know as a vertex shader, describes a
  * stage in the graphics pipeline responsible for manipulating
@@ -76,14 +78,15 @@
     }
 
     /**
-    * @deprecated in API 16
-    * Builder class for creating ProgramVertex objects.
-    * The builder starts empty and the user must minimally provide
-    * the GLSL shader code, and the varying inputs. Constant, or
-    * uniform parameters to the shader may optionally be provided as
-    * well.
-    *
-    **/
+     * @hide
+     * @deprecated in API 16
+     * Builder class for creating ProgramVertex objects.
+     * The builder starts empty and the user must minimally provide
+     * the GLSL shader code, and the varying inputs. Constant, or
+     * uniform parameters to the shader may optionally be provided as
+     * well.
+     *
+     **/
     public static class Builder extends BaseProgramBuilder {
         /**
          * @deprecated in API 16
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
index 88cade4..ad486f3 100644
--- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -22,6 +22,7 @@
 
 
 /**
+ * @hide
  * @deprecated in API 16
  * ProgramVertexFixedFunction is a helper class that provides a
  * simple way to create a fixed function emulation vertex shader
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 82ed95c..3c6c720 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -30,6 +30,7 @@
 import android.view.SurfaceView;
 
 /**
+ * @hide
  * @deprecated in API 16
  * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
  *
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java
index ed04000..7eeeeae 100644
--- a/graphics/java/android/renderscript/RSTextureView.java
+++ b/graphics/java/android/renderscript/RSTextureView.java
@@ -29,6 +29,7 @@
 import android.view.TextureView;
 
 /**
+ * @hide
  * @deprecated in API 16
  * The Texture View for a graphics renderscript (RenderScriptGL)
  * to draw on.
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 5269405..52034b1 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -29,6 +29,7 @@
 import android.view.SurfaceView;
 
 /**
+ * @hide
  * @deprecated in API 16
  * The Graphics derivitive of Renderscript.  Extends the basic context to add a
  * root script which is the display window for graphical output.  When the
diff --git a/graphics/java/android/renderscript/package.html b/graphics/java/android/renderscript/package.html
index 5eab23c..eb178c1 100644
--- a/graphics/java/android/renderscript/package.html
+++ b/graphics/java/android/renderscript/package.html
@@ -1,86 +1,10 @@
 <HTML>
 <BODY>
-<p>The Renderscript rendering and computational APIs offer a low-level, high performance means of
-carrying out mathematical calculations and 3D graphics rendering.</p>
+<p>RenderScript provides support for high-performance computation across heterogeneous processors.</p>
 
 <p>For more information, see the
-<a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
 {@more}
 
-<p>An example of Renderscript in applications include the 3D carousel view that is present in
-Android 3.0 applications such as the Books and YouTube applications. This API is intended for
-developers who are comfortable working with native code and want to maximize their performance
-critical applications.</p>
-
-<p>Renderscript adopts a control and slave architecture where the low-level native code is controlled by the
-higher level Android system that runs in the virtual machine (VM). The VM code handles resource
-allocation and lifecycle management of the Renderscript enabled application and calls the Renderscript
-code through high level entry points. The Android build tools generate these entry points through reflection on
-the native Renderscript code, which you write in C (C99 standard). The Renderscript code
-does the intensive computation and returns the result back to the Android VM.</p>
-
-<p>You can find the Renderscript native
-APIs in the <code>&lt;sdk_root&gt;/platforms/android-11/renderscript</code> directory.
-The Android system APIs are broken into a few main groups:</p>
-
-<h4>Core</h4>
-<p>These classes are used internally by the system for memory allocation. They are used by the classes that
-are generated by the build tools:</p>
-<ul>
-  <li>Allocation</li>
-  <li>Element</li>
-  <li>Type</li>
-  <li>Script</li>
-</ul>
-
-
-<h4>Data Types</h4>
-<p>These data types are used by the classes that are generated
-by the build tools. They are the reflected counterparts of the native data types that
-are defined by the native Renderscript APIs and used by your Renderscript code. The
-classes include:</p>
-<ul>
-  <li>Byte2, Byte3, and Byte4</li>
-  <li>Float2, Float3, Float4</li>
-  <li>Int2, Int3, Int4</li>
-  <li>Long2, Long3, Long4</li>
-  <li>Matrix2f, Matrix3f, Matrix4f</li>
-  <li>Short2, Short3, Short4</li>
-</ul>
-
-<p>For example, if you declared the following struct in your .rs Renderscript file:</p>
-
-<pre>struct Hello { float3 position; rs_matrix4x4 transform; }</pre>
-
-<p>The build tools generate a class through reflection that looks like the following:</p>
-<pre>
-class Hello {
-    static public class Item {
-        Float4 position;
-        Matrix4f transform;
-    }
-Element createElement(RenderScript rs) {
-        Element.Builder eb = new Element.Builder(rs);
-        eb.add(Element.F32_3(rs), "position");
-        eb.add(Element.MATRIX_4X4(rs), "transform");
-        return eb.create();
-    }
-}
-</pre>
-
-<h4>Graphics</h4>
-<p>These classes are specific to graphics Renderscripts and support a typical rendering
-pipeline.</p>
-<ul>
-<li>Mesh</li>
-<li>ProgramFragment</li>
-<li>ProgramRaster</li>
-<li>ProgramStore</li>
-<li>ProgramVertex</li>
-<li>RSSurfaceView</li>
-<li>Sampler</li>
-</ul>
-
-</p>
 </BODY>
 </HTML>
diff --git a/include/androidfw/InputDevice.h b/include/androidfw/InputDevice.h
index 1aecf80..45dc2db 100644
--- a/include/androidfw/InputDevice.h
+++ b/include/androidfw/InputDevice.h
@@ -64,6 +64,7 @@
         float max;
         float flat;
         float fuzz;
+        float resolution;
     };
 
     void initialize(int32_t id, int32_t generation, const InputDeviceIdentifier& identifier,
@@ -83,7 +84,7 @@
 
     void addSource(uint32_t source);
     void addMotionRange(int32_t axis, uint32_t source,
-            float min, float max, float flat, float fuzz);
+            float min, float max, float flat, float fuzz, float resolution);
     void addMotionRange(const MotionRange& range);
 
     inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
diff --git a/include/androidfw/InputTransport.h b/include/androidfw/InputTransport.h
index 5706bce..8712995 100644
--- a/include/androidfw/InputTransport.h
+++ b/include/androidfw/InputTransport.h
@@ -168,6 +168,9 @@
      */
     status_t receiveMessage(InputMessage* msg);
 
+    /* Returns a new object that has a duplicate of this channel's fd. */
+    sp<InputChannel> dup() const;
+
 private:
     String8 mName;
     int mFd;
diff --git a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
index 83faf35..18225a5 100644
--- a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
@@ -49,8 +49,6 @@
  * <p>
  * The self-signed certificate may be replaced at a later time by a certificate
  * signed by a real Certificate Authority.
- *
- * @hide
  */
 public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
     private final String mKeystoreAlias;
diff --git a/libs/androidfw/InputDevice.cpp b/libs/androidfw/InputDevice.cpp
index fe891cb..f742052 100644
--- a/libs/androidfw/InputDevice.cpp
+++ b/libs/androidfw/InputDevice.cpp
@@ -172,8 +172,8 @@
 }
 
 void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
-        float flat, float fuzz) {
-    MotionRange range = { axis, source, min, max, flat, fuzz };
+        float flat, float fuzz, float resolution) {
+    MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
     mMotionRanges.add(range);
 }
 
diff --git a/libs/androidfw/InputTransport.cpp b/libs/androidfw/InputTransport.cpp
index 351c666..498389ea 100644
--- a/libs/androidfw/InputTransport.cpp
+++ b/libs/androidfw/InputTransport.cpp
@@ -219,6 +219,11 @@
     return OK;
 }
 
+sp<InputChannel> InputChannel::dup() const {
+    int fd = ::dup(getFd());
+    return fd >= 0 ? new InputChannel(getName(), fd) : NULL;
+}
+
 
 // --- InputPublisher ---
 
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 3e450da..653f315 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -52,8 +52,6 @@
         kOpBatch_Count, // Add other batch ids before this
     };
 
-    void clear();
-
     bool isEmpty() { return mBatches.isEmpty(); }
 
     /**
@@ -80,6 +78,8 @@
      */
     void resetBatchingState();
 
+    void clear();
+
     void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
     void storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
 
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index e80b325..9bc5c14 100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -21,38 +21,46 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Must be a power of two
-#define DITHER_KERNEL_SIZE 4
-
-///////////////////////////////////////////////////////////////////////////////
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
 void Dither::bindDitherTexture() {
     if (!mInitialized) {
-        const uint8_t pattern[] = {
-             0,  8,  2, 10,
-            12,  4, 14,  6,
-             3, 11,  1,  9,
-            15,  7, 13,  5
-        };
+        bool useFloatTexture = Extensions::getInstance().getMajorGlVersion() >= 3;
 
         glGenTextures(1, &mDitherTexture);
         glBindTexture(GL_TEXTURE_2D, mDitherTexture);
 
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
-                GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+        if (useFloatTexture) {
+            float dither = 1.0f / (255.0f * DITHER_KERNEL_SIZE * DITHER_KERNEL_SIZE);
+            const GLfloat pattern[] = {
+                 0 * dither,  8 * dither,  2 * dither, 10 * dither,
+                12 * dither,  4 * dither, 14 * dither,  6 * dither,
+                 3 * dither, 11 * dither,  1 * dither,  9 * dither,
+                15 * dither,  7 * dither, 13 * dither,  5 * dither
+            };
+
+            glPixelStorei(GL_UNPACK_ALIGNMENT, sizeof(GLfloat));
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+                    GL_RED, GL_FLOAT, &pattern);
+        } else {
+            const uint8_t pattern[] = {
+                 0,  8,  2, 10,
+                12,  4, 14,  6,
+                 3, 11,  1,  9,
+                15,  7, 13,  5
+            };
+
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+                    GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+        }
 
         mInitialized = true;
     } else {
@@ -76,10 +84,7 @@
 
     bindDitherTexture();
 
-    float ditherSize = 1.0f / DITHER_KERNEL_SIZE;
     glUniform1i(program->getUniform("ditherSampler"), textureSlot);
-    glUniform1f(program->getUniform("ditherSize"), ditherSize);
-    glUniform1f(program->getUniform("ditherSizeSquared"), ditherSize * ditherSize);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index 34cf9bf..4d1f921 100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
@@ -17,13 +17,23 @@
 #ifndef ANDROID_HWUI_DITHER_H
 #define ANDROID_HWUI_DITHER_H
 
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
 
 #include "Program.h"
 
 namespace android {
 namespace uirenderer {
 
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be a power of two
+#define DITHER_KERNEL_SIZE 4
+// These must not use the .0f notation as they are used from GLSL
+#define DITHER_KERNEL_SIZE_INV (1.0 / 4.0)
+#define DITHER_KERNEL_SIZE_INV_SQUARE (1.0 / 16.0)
+
 /**
  * Handles dithering for programs.
  */
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 26c7e5d..44dc731 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -31,6 +31,7 @@
 
 #include "Caches.h"
 #include "Debug.h"
+#include "Extensions.h"
 #include "FontRenderer.h"
 #include "Rect.h"
 
@@ -375,34 +376,60 @@
 
     Caches& caches = Caches::getInstance();
     GLuint lastTextureId = 0;
+
+    // OpenGL ES 3.0+ lets us specify the row length for unpack operations such
+    // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture.
+    // With OpenGL ES 2.0 we have to upload entire stripes instead.
+    const bool hasUnpackRowLength = Extensions::getInstance().getMajorGlVersion() >= 3;
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
     // Iterate over all the cache textures and see which ones need to be updated
     for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
         CacheTexture* cacheTexture = mCacheTextures[i];
         if (cacheTexture->isDirty() && cacheTexture->getTexture()) {
-            // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer
-            // of data. So expand the dirty rect to the encompassing horizontal stripe.
             const Rect* dirtyRect = cacheTexture->getDirtyRect();
-            uint32_t x = 0;
+            uint32_t x = hasUnpackRowLength ? dirtyRect->left : 0;
             uint32_t y = dirtyRect->top;
             uint32_t width = cacheTexture->getWidth();
             uint32_t height = dirtyRect->getHeight();
-            void* textureData = cacheTexture->getTexture() + y * width;
+            void* textureData = cacheTexture->getTexture() + y * width + x;
 
             if (cacheTexture->getTextureId() != lastTextureId) {
                 lastTextureId = cacheTexture->getTextureId();
                 caches.activeTexture(0);
                 glBindTexture(GL_TEXTURE_2D, lastTextureId);
+
+                // The unpack row length only needs to be specified when a new
+                // texture is bound
+                if (hasUnpackRowLength) {
+                    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+                }
             }
+
+            // If we can upload a sub-rectangle, use the dirty rect width
+            // instead of the width of the entire texture
+            if (hasUnpackRowLength) {
+                width = dirtyRect->getWidth();
+            }
+
 #if DEBUG_FONT_RENDERER
             ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d",
                     i, x, y, width, height);
 #endif
+
             glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
                     GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
+
             cacheTexture->setDirty(false);
         }
     }
 
+    // Reset to default unpack row length to avoid affecting texture
+    // uploads in other parts of the renderer
+    if (hasUnpackRowLength) {
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    }
+
     mUploadTexture = false;
 }
 
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index d681609..eef366c 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -27,13 +27,6 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#define GRADIENT_TEXTURE_HEIGHT 2
-#define GRADIENT_BYTES_PER_PIXEL 4
-
-///////////////////////////////////////////////////////////////////////////////
 // Functions
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -83,6 +76,10 @@
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 
     mCache.setOnEntryRemovedListener(this);
+
+    const Extensions& extensions = Extensions::getInstance();
+    mUseFloatTexture = extensions.getMajorGlVersion() >= 3;
+    mHasNpot = extensions.hasNPot();
 }
 
 GradientCache::GradientCache(uint32_t maxByteSize):
@@ -120,7 +117,7 @@
 
 void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
     if (texture) {
-        const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
+        const uint32_t size = texture->width * texture->height * bytesPerPixel();
         mSize -= size;
 
         glDeleteTextures(1, &texture->id);
@@ -151,7 +148,7 @@
         GradientInfo& info) {
     uint32_t width = 256 * (count - 1);
 
-    if (!Extensions::getInstance().hasNPot()) {
+    if (!mHasNpot) {
         width = 1 << (31 - __builtin_clz(width));
     }
 
@@ -175,12 +172,12 @@
 
     Texture* texture = new Texture;
     texture->width = info.width;
-    texture->height = GRADIENT_TEXTURE_HEIGHT;
+    texture->height = 2;
     texture->blend = info.hasAlpha;
     texture->generation = 1;
 
     // Asume the cache is always big enough
-    const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
+    const uint32_t size = texture->width * texture->height * bytesPerPixel();
     while (getSize() + size > mMaxSize) {
         mCache.removeOldest();
     }
@@ -193,69 +190,110 @@
     return texture;
 }
 
+size_t GradientCache::bytesPerPixel() const {
+    // We use 4 channels (RGBA)
+    return 4 * (mUseFloatTexture ? sizeof(float) : sizeof(uint8_t));
+}
+
+void GradientCache::splitToBytes(uint32_t inColor, GradientColor& outColor) const {
+    outColor.r = (inColor >> 16) & 0xff;
+    outColor.g = (inColor >>  8) & 0xff;
+    outColor.b = (inColor >>  0) & 0xff;
+    outColor.a = (inColor >> 24) & 0xff;
+}
+
+void GradientCache::splitToFloats(uint32_t inColor, GradientColor& outColor) const {
+    outColor.r = ((inColor >> 16) & 0xff) / 255.0f;
+    outColor.g = ((inColor >>  8) & 0xff) / 255.0f;
+    outColor.b = ((inColor >>  0) & 0xff) / 255.0f;
+    outColor.a = ((inColor >> 24) & 0xff) / 255.0f;
+}
+
+void GradientCache::mixBytes(GradientColor& start, GradientColor& end, float amount,
+        uint8_t*& dst) const {
+    float oppAmount = 1.0f - amount;
+    const float alpha = start.a * oppAmount + end.a * amount;
+    const float a = alpha / 255.0f;
+
+    *dst++ = uint8_t(a * (start.r * oppAmount + end.r * amount));
+    *dst++ = uint8_t(a * (start.g * oppAmount + end.g * amount));
+    *dst++ = uint8_t(a * (start.b * oppAmount + end.b * amount));
+    *dst++ = uint8_t(alpha);
+}
+
+void GradientCache::mixFloats(GradientColor& start, GradientColor& end, float amount,
+        uint8_t*& dst) const {
+    float oppAmount = 1.0f - amount;
+    const float a = start.a * oppAmount + end.a * amount;
+
+    float* d = (float*) dst;
+    *d++ = a * (start.r * oppAmount + end.r * amount);
+    *d++ = a * (start.g * oppAmount + end.g * amount);
+    *d++ = a * (start.b * oppAmount + end.b * amount);
+    *d++ = a;
+
+    dst += 4 * sizeof(float);
+}
+
 void GradientCache::generateTexture(uint32_t* colors, float* positions,
         int count, Texture* texture) {
-
     const uint32_t width = texture->width;
-    const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL;
-    uint32_t pixels[width * texture->height];
+    const GLsizei rowBytes = width * bytesPerPixel();
+    uint8_t pixels[rowBytes * texture->height];
+
+    static ChannelSplitter gSplitters[] = {
+            &android::uirenderer::GradientCache::splitToBytes,
+            &android::uirenderer::GradientCache::splitToFloats,
+    };
+    ChannelSplitter split = gSplitters[mUseFloatTexture];
+
+    static ChannelMixer gMixers[] = {
+            &android::uirenderer::GradientCache::mixBytes,
+            &android::uirenderer::GradientCache::mixFloats,
+    };
+    ChannelMixer mix = gMixers[mUseFloatTexture];
+
+    GradientColor start;
+    (this->*split)(colors[0], start);
+
+    GradientColor end;
+    (this->*split)(colors[1], end);
 
     int currentPos = 1;
+    float startPos = positions[0];
+    float distance = positions[1] - startPos;
 
-    float startA = (colors[0] >> 24) & 0xff;
-    float startR = (colors[0] >> 16) & 0xff;
-    float startG = (colors[0] >>  8) & 0xff;
-    float startB = (colors[0] >>  0) & 0xff;
-
-    float endA = (colors[1] >> 24) & 0xff;
-    float endR = (colors[1] >> 16) & 0xff;
-    float endG = (colors[1] >>  8) & 0xff;
-    float endB = (colors[1] >>  0) & 0xff;
-
-    float start = positions[0];
-    float distance = positions[1] - start;
-
-    uint8_t* p = (uint8_t*) pixels;
+    uint8_t* dst = pixels;
     for (uint32_t x = 0; x < width; x++) {
         float pos = x / float(width - 1);
         if (pos > positions[currentPos]) {
-            startA = endA;
-            startR = endR;
-            startG = endG;
-            startB = endB;
-            start = positions[currentPos];
+            start = end;
+            startPos = positions[currentPos];
 
             currentPos++;
 
-            endA = (colors[currentPos] >> 24) & 0xff;
-            endR = (colors[currentPos] >> 16) & 0xff;
-            endG = (colors[currentPos] >>  8) & 0xff;
-            endB = (colors[currentPos] >>  0) & 0xff;
-            distance = positions[currentPos] - start;
+            (this->*split)(colors[currentPos], end);
+            distance = positions[currentPos] - startPos;
         }
 
-        float amount = (pos - start) / distance;
-        float oppAmount = 1.0f - amount;
-
-        const float alpha = startA * oppAmount + endA * amount;
-        const float a = alpha / 255.0f;
-        *p++ = uint8_t(a * (startR * oppAmount + endR * amount));
-        *p++ = uint8_t(a * (startG * oppAmount + endG * amount));
-        *p++ = uint8_t(a * (startB * oppAmount + endB * amount));
-        *p++ = uint8_t(alpha);
+        float amount = (pos - startPos) / distance;
+        (this->*mix)(start, end, amount, dst);
     }
 
-    for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) {
-        memcpy(pixels + width * i, pixels, rowBytes);
-    }
+    memcpy(pixels + rowBytes, pixels, rowBytes);
 
     glGenTextures(1, &texture->id);
-
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
-            GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    if (mUseFloatTexture) {
+        // We have to use GL_RGBA16F because GL_RGBA32F does not support filtering
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, texture->height, 0,
+                GL_RGBA, GL_FLOAT, pixels);
+    } else {
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    }
 
     texture->setFilter(GL_LINEAR);
     texture->setWrap(GL_CLAMP_TO_EDGE);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 7dc5b8a..43934d9 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
 #define ANDROID_HWUI_GRADIENT_CACHE_H
 
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
 
 #include <SkShader.h>
 
@@ -160,12 +160,35 @@
 
     void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
 
+    size_t bytesPerPixel() const;
+
+    struct GradientColor {
+        float r;
+        float g;
+        float b;
+        float a;
+    };
+
+    typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
+            GradientColor& outColor) const;
+
+    void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
+    void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
+
+    typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
+            float amount, uint8_t*& dst) const;
+
+    void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
+    void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
+
     LruCache<GradientCacheEntry, Texture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
 
     GLint mMaxTextureSize;
+    bool mUseFloatTexture;
+    bool mHasNpot;
 
     Vector<SkShader*> mGarbage;
     mutable Mutex mLock;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 63bb73f..a718294 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -90,7 +90,7 @@
     if (fbo) {
         Caches::getInstance().activeTexture(0);
         bindTexture();
-        allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+        allocateTexture();
 
         if (glGetError() != GL_NO_ERROR) {
             setSize(oldWidth, oldHeight);
@@ -167,7 +167,6 @@
     displayList->defer(deferredState, 0);
 
     deferredUpdateScheduled = false;
-    displayList = NULL;
 }
 
 void Layer::flush() {
@@ -182,7 +181,7 @@
         renderer = NULL;
 
         dirtyRect.setEmpty();
-        deferredList->clear();
+        displayList = NULL;
     }
 }
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 27e0cf1..715dfa4 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -255,13 +255,14 @@
         texture.id = 0;
     }
 
-    inline void allocateTexture(GLenum format, GLenum storage) {
+    inline void allocateTexture() {
 #if DEBUG_LAYERS
         ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
 #endif
         if (texture.id) {
-            glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0,
-                    format, storage, NULL);
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+            glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0,
+                    GL_RGBA, GL_UNSIGNED_BYTE, NULL);
         }
     }
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 8451048..3e55fff 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -256,7 +256,7 @@
     // Initialize the texture if needed
     if (layer->isEmpty()) {
         layer->setEmpty(false);
-        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+        layer->allocateTexture();
 
         // This should only happen if we run out of memory
         if (glGetError() != GL_NO_ERROR) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1138998..3730017 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -571,8 +571,8 @@
             startMark("Defer Layer Updates");
         }
 
-        // Note: it is very important to update the layers in reverse order
-        for (int i = count - 1; i >= 0; i--) {
+        // Note: it is very important to update the layers in order
+        for (int i = 0; i < count; i++) {
             Layer* layer = mLayerUpdates.itemAt(i);
             updateLayer(layer, false);
             if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
@@ -594,8 +594,8 @@
         startMark("Apply Layer Updates");
         char layerName[12];
 
-        // Note: it is very important to update the layers in reverse order
-        for (int i = count - 1; i >= 0; i--) {
+        // Note: it is very important to update the layers in order
+        for (int i = 0; i < count; i++) {
             sprintf(layerName, "Layer #%d", i);
             startMark(layerName);
 
@@ -922,7 +922,7 @@
 
     // Initialize the texture if needed
     if (layer->isEmpty()) {
-        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+        layer->allocateTexture();
         layer->setEmpty(false);
     }
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index f78fb2d..2479630 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -19,6 +19,7 @@
 #include <utils/String8.h>
 
 #include "Caches.h"
+#include "Dither.h"
 #include "ProgramCache.h"
 
 namespace android {
@@ -32,6 +33,9 @@
 #define MODULATE_OP_MODULATE 1
 #define MODULATE_OP_MODULATE_A8 2
 
+#define STR(x) STR1(x)
+#define STR1(x) #x
+
 ///////////////////////////////////////////////////////////////////////////////
 // Vertex shaders snippets
 ///////////////////////////////////////////////////////////////////////////////
@@ -51,17 +55,8 @@
         "uniform mat4 transform;\n";
 const char* gVS_Header_Uniforms_IsPoint =
         "uniform mediump float pointSize;\n";
-const char* gVS_Header_Uniforms_HasGradient[3] = {
-        // Linear
-        "uniform mat4 screenSpace;\n"
-        "uniform float ditherSize;\n",
-        // Circular
-        "uniform mat4 screenSpace;\n"
-        "uniform float ditherSize;\n",
-        // Sweep
-        "uniform mat4 screenSpace;\n"
-        "uniform float ditherSize;\n"
-};
+const char* gVS_Header_Uniforms_HasGradient =
+        "uniform mat4 screenSpace;\n";
 const char* gVS_Header_Uniforms_HasBitmap =
         "uniform mat4 textureTransform;\n"
         "uniform mediump vec2 textureDimension;\n";
@@ -105,21 +100,21 @@
 const char* gVS_Main_OutGradient[6] = {
         // Linear
         "    linear = vec2((screenSpace * position).x, 0.5);\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
         "    linear = (screenSpace * position).x;\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
 
         // Circular
         "    circular = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
         "    circular = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
 
         // Sweep
         "    sweep = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
         "    sweep = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
 };
 const char* gVS_Main_OutBitmapTexCoords =
         "    outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
@@ -153,24 +148,14 @@
         "uniform sampler2D baseSampler;\n";
 const char* gFS_Uniforms_ExternalTextureSampler =
         "uniform samplerExternalOES baseSampler;\n";
-#define FS_UNIFORMS_DITHER \
-        "uniform float ditherSizeSquared;\n" \
-        "uniform sampler2D ditherSampler;\n"
-#define FS_UNIFORMS_GRADIENT \
-        "uniform vec4 startColor;\n" \
+const char* gFS_Uniforms_Dither =
+        "uniform sampler2D ditherSampler;";
+const char* gFS_Uniforms_GradientSampler[2] = {
+        "%s\n"
+        "uniform sampler2D gradientSampler;\n",
+        "%s\n"
+        "uniform vec4 startColor;\n"
         "uniform vec4 endColor;\n"
-const char* gFS_Uniforms_GradientSampler[6] = {
-        // Linear
-        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
-        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
-
-        // Circular
-        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
-        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
-
-        // Sweep
-        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
-        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT
 };
 const char* gFS_Uniforms_BitmapSampler =
         "uniform sampler2D bitmapSampler;\n";
@@ -197,10 +182,14 @@
         "    highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
         "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
 
-#define FS_MAIN_DITHER \
-        "texture2D(ditherSampler, ditherTexCoords).a * ditherSizeSquared"
+const char* gFS_Main_Dither[2] = {
+        // ES 2.0
+        "texture2D(ditherSampler, ditherTexCoords).a * " STR(DITHER_KERNEL_SIZE_INV_SQUARE),
+        // ES 3.0
+        "texture2D(ditherSampler, ditherTexCoords).r"
+};
 const char* gFS_Main_AddDitherToGradient =
-        "    gradientColor += " FS_MAIN_DITHER ";\n";
+        "    gradientColor += %s;\n";
 
 // Fast cases
 const char* gFS_Fast_SingleColor =
@@ -233,18 +222,18 @@
         "}\n\n";
 const char* gFS_Fast_SingleGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = " FS_MAIN_DITHER " + texture2D(gradientSampler, linear);\n"
+        "    gl_FragColor = %s + texture2D(gradientSampler, linear);\n"
         "}\n\n",
         "\nvoid main(void) {\n"
-        "    gl_FragColor = " FS_MAIN_DITHER " + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
-        "}\n\n"
+        "    gl_FragColor = %s + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "}\n\n",
 };
 const char* gFS_Fast_SingleModulateGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
+        "    gl_FragColor = %s + color.a * texture2D(gradientSampler, linear);\n"
         "}\n\n",
         "\nvoid main(void) {\n"
-        "    gl_FragColor = " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "    gl_FragColor = %s + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
         "}\n\n"
 };
 
@@ -410,7 +399,7 @@
 // Constructors/destructors
 ///////////////////////////////////////////////////////////////////////////////
 
-ProgramCache::ProgramCache() {
+ProgramCache::ProgramCache(): mHasES3(Extensions::getInstance().getMajorGlVersion() >= 3) {
 }
 
 ProgramCache::~ProgramCache() {
@@ -484,7 +473,7 @@
         shader.append(gVS_Header_Uniforms_TextureTransform);
     }
     if (description.hasGradient) {
-        shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
+        shader.append(gVS_Header_Uniforms_HasGradient);
     }
     if (description.hasBitmap) {
         shader.append(gVS_Header_Uniforms_HasBitmap);
@@ -601,7 +590,8 @@
         shader.append(gFS_Uniforms_ExternalTextureSampler);
     }
     if (description.hasGradient) {
-        shader.append(gFS_Uniforms_GradientSampler[gradientIndex(description)]);
+        shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient],
+                gFS_Uniforms_Dither);
     }
     if (description.hasBitmap && description.isPoint) {
         shader.append(gFS_Header_Uniforms_PointHasBitmap);
@@ -652,9 +642,11 @@
             fast = true;
         } else if (singleGradient) {
             if (!description.modulate) {
-                shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]);
+                shader.appendFormat(gFS_Fast_SingleGradient[description.isSimpleGradient],
+                        gFS_Main_Dither[mHasES3]);
             } else {
-                shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]);
+                shader.appendFormat(gFS_Fast_SingleModulateGradient[description.isSimpleGradient],
+                        gFS_Main_Dither[mHasES3]);
             }
             fast = true;
         }
@@ -708,7 +700,7 @@
         }
         if (description.hasGradient) {
             shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
-            shader.append(gFS_Main_AddDitherToGradient);
+            shader.appendFormat(gFS_Main_AddDitherToGradient, gFS_Main_Dither[mHasES3]);
         }
         if (description.hasBitmap) {
             if (description.isPoint) {
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 1ca148d..38f6f99 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -57,6 +57,8 @@
     void printLongString(const String8& shader) const;
 
     KeyedVector<programid, Program*> mCache;
+
+    const bool mHasES3;
 }; // class ProgramCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 1096642..577f463 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -15,10 +15,9 @@
  */
 
 #include <SkGlyph.h>
-#include <utils/Log.h>
 
-#include "Debug.h"
 #include "CacheTexture.h"
+#include "../Debug.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index 5742941..e7fb474 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_HWUI_CACHE_TEXTURE_H
 #define ANDROID_HWUI_CACHE_TEXTURE_H
 
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
 
 #include <SkScalerContext.h>
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b80a166..917a47d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -50,6 +50,7 @@
     private long mVolumeKeyUpTime;
     private final boolean mUseMasterVolume;
     private final boolean mUseVolumeKeySounds;
+    private final Binder mToken = new Binder();
     private static String TAG = "AudioManager";
 
     /**
@@ -2075,7 +2076,8 @@
         IAudioService service = getService();
         try {
             // pi != null
-            service.registerMediaButtonIntent(pi, eventReceiver);
+            service.registerMediaButtonIntent(pi, eventReceiver,
+                    eventReceiver == null ? mToken : null);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index fd71d79..773d7b6 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -357,7 +357,7 @@
     private static final int SCO_STATE_INACTIVE = 0;
     // SCO audio activation request waiting for headset service to connect
     private static final int SCO_STATE_ACTIVATE_REQ = 1;
-    // SCO audio state is active or starting due to a local request to start a virtual call
+    // SCO audio state is active or starting due to a request from AudioManager API
     private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
     // SCO audio deactivation request waiting for headset service to connect
     private static final int SCO_STATE_DEACTIVATE_REQ = 5;
@@ -530,6 +530,9 @@
         // Register for package removal intent broadcasts for media button receiver persistence
         IntentFilter pkgFilter = new IntentFilter();
         pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
         pkgFilter.addDataScheme("package");
         context.registerReceiver(mReceiver, pkgFilter);
 
@@ -2053,8 +2056,7 @@
                                  mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
                             if (mScoAudioState == SCO_STATE_INACTIVE) {
                                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
-                                    if (mBluetoothHeadset.startScoUsingVirtualVoiceCall(
-                                            mBluetoothHeadsetDevice)) {
+                                    if (mBluetoothHeadset.connectAudio()) {
                                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
                                     } else {
                                         broadcastScoConnectionState(
@@ -2076,8 +2078,7 @@
                                mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
                     if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
                         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
-                            if (!mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
-                                    mBluetoothHeadsetDevice)) {
+                            if (!mBluetoothHeadset.disconnectAudio()) {
                                 mScoAudioState = SCO_STATE_INACTIVE;
                                 broadcastScoConnectionState(
                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
@@ -2250,12 +2251,10 @@
                             switch (mScoAudioState) {
                             case SCO_STATE_ACTIVATE_REQ:
                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
-                                status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
-                                        mBluetoothHeadsetDevice);
+                                status = mBluetoothHeadset.connectAudio();
                                 break;
                             case SCO_STATE_DEACTIVATE_REQ:
-                                status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
-                                        mBluetoothHeadsetDevice);
+                                status = mBluetoothHeadset.disconnectAudio();
                                 break;
                             case SCO_STATE_DEACTIVATE_EXT_REQ:
                                 status = mBluetoothHeadset.stopVoiceRecognition(
@@ -4037,14 +4036,21 @@
                         0,
                         null,
                         SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
-            } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
+            } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+                    || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) {
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     // a package is being removed, not replaced
                     String packageName = intent.getData().getSchemeSpecificPart();
                     if (packageName != null) {
-                        removeMediaButtonReceiverForPackage(packageName);
+                        cleanupMediaButtonReceiverForPackage(packageName, true);
                     }
                 }
+            } else if (action.equals(Intent.ACTION_PACKAGE_ADDED)
+                    || action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
+                String packageName = intent.getData().getSchemeSpecificPart();
+                if (packageName != null) {
+                    cleanupMediaButtonReceiverForPackage(packageName, false);
+                }
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 AudioSystem.setParameters("screen_state=on");
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
@@ -4851,8 +4857,9 @@
         }
     }
 
-    private static class RemoteControlStackEntry {
+    private static class RemoteControlStackEntry implements DeathRecipient {
         public int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
+        final public AudioService mService;
         /**
          * The target for the ACTION_MEDIA_BUTTON events.
          * Always non null.
@@ -4863,6 +4870,7 @@
          * Always non null.
          */
         final public ComponentName mReceiverComponent;
+        public IBinder mToken;
         public String mCallingPackageName;
         public int mCallingUid;
         /**
@@ -4893,9 +4901,12 @@
         }
 
         /** precondition: mediaIntent != null */
-        public RemoteControlStackEntry(PendingIntent mediaIntent, ComponentName eventReceiver) {
+        public RemoteControlStackEntry(AudioService service, PendingIntent mediaIntent,
+                ComponentName eventReceiver, IBinder token) {
+            mService = service;
             mMediaIntent = mediaIntent;
             mReceiverComponent = eventReceiver;
+            mToken = token;
             mCallingUid = -1;
             mRcClient = null;
             mRccId = ++sLastRccId;
@@ -4905,6 +4916,17 @@
                     RemoteControlClient.PLAYBACK_SPEED_1X);
 
             resetPlaybackInfo();
+            if (mToken != null) {
+                try {
+                    mToken.linkToDeath(this, 0);
+                } catch (RemoteException e) {
+                    mService.mAudioHandler.post(new Runnable() {
+                        @Override public void run() {
+                            mService.unregisterMediaButtonIntent(mMediaIntent);
+                        }
+                    });
+                }
+            }
         }
 
         public void unlinkToRcClientDeath() {
@@ -4920,9 +4942,22 @@
             }
         }
 
+        public void destroy() {
+            unlinkToRcClientDeath();
+            if (mToken != null) {
+                mToken.unlinkToDeath(this, 0);
+                mToken = null;
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            mService.unregisterMediaButtonIntent(mMediaIntent);
+        }
+
         @Override
         protected void finalize() throws Throwable {
-            unlinkToRcClientDeath();// unlink exception handled inside method
+            destroy(); // unlink exception handled inside method
             super.finalize();
         }
     }
@@ -5021,11 +5056,12 @@
      * Remove any entry in the remote control stack that has the same package name as packageName
      * Pre-condition: packageName != null
      */
-    private void removeMediaButtonReceiverForPackage(String packageName) {
+    private void cleanupMediaButtonReceiverForPackage(String packageName, boolean removeAll) {
         synchronized(mRCStack) {
             if (mRCStack.empty()) {
                 return;
             } else {
+                final PackageManager pm = mContext.getPackageManager();
                 RemoteControlStackEntry oldTop = mRCStack.peek();
                 Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
                 // iterate over the stack entries
@@ -5033,10 +5069,19 @@
                 //  evaluated it, traversal order doesn't matter here)
                 while(stackIterator.hasNext()) {
                     RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
-                    if (packageName.equals(rcse.mMediaIntent.getCreatorPackage())) {
+                    if (removeAll && packageName.equals(rcse.mMediaIntent.getCreatorPackage())) {
                         // a stack entry is from the package being removed, remove it from the stack
                         stackIterator.remove();
-                        rcse.unlinkToRcClientDeath();
+                        rcse.destroy();
+                    } else if (rcse.mReceiverComponent != null) {
+                        try {
+                            // Check to see if this receiver still exists.
+                            pm.getReceiverInfo(rcse.mReceiverComponent, 0);
+                        } catch (PackageManager.NameNotFoundException e) {
+                            // Not found -- remove it!
+                            stackIterator.remove();
+                            rcse.destroy();
+                        }
                     }
                 }
                 if (mRCStack.empty()) {
@@ -5079,7 +5124,7 @@
             mediaButtonIntent.setComponent(eventReceiver);
             PendingIntent pi = PendingIntent.getBroadcast(mContext,
                     0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
-            registerMediaButtonIntent(pi, eventReceiver);
+            registerMediaButtonIntent(pi, eventReceiver, null);
         }
     }
 
@@ -5089,7 +5134,8 @@
      * Called synchronized on mAudioFocusLock, then mRCStack
      * precondition: mediaIntent != null
      */
-    private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target) {
+    private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target,
+            IBinder token) {
         // already at top of stack?
         if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) {
             return;
@@ -5111,7 +5157,7 @@
             Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e);
         }
         if (!wasInsideStack) {
-            rcse = new RemoteControlStackEntry(mediaIntent, target);
+            rcse = new RemoteControlStackEntry(this, mediaIntent, target, token);
         }
         mRCStack.push(rcse); // rcse is never null
 
@@ -5133,7 +5179,7 @@
             for (int index = mRCStack.size()-1; index >= 0; index--) {
                 final RemoteControlStackEntry rcse = mRCStack.elementAt(index);
                 if (rcse.mMediaIntent.equals(pi)) {
-                    rcse.unlinkToRcClientDeath();
+                    rcse.destroy();
                     // ok to remove element while traversing the stack since we're leaving the loop
                     mRCStack.removeElementAt(index);
                     break;
@@ -5421,12 +5467,13 @@
      * see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
      * precondition: mediaIntent != null
      */
-    public void registerMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver) {
+    public void registerMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver,
+            IBinder token) {
         Log.i(TAG, "  Remote Control   registerMediaButtonIntent() for " + mediaIntent);
 
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
-                pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver);
+                pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token);
                 // new RC client, assume every type of information shall be queried
                 checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
             }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index cd50de4..399eb7b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -791,7 +791,7 @@
      *    {@link #ERROR_INVALID_OPERATION}
      */
     public int setPlaybackRate(int sampleRateInHz) {
-        if (mState == STATE_UNINITIALIZED) {
+        if (mState != STATE_INITIALIZED) {
             return ERROR_INVALID_OPERATION;
         }
         if (sampleRateInHz <= 0) {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 25aae8f..13f6c02 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -120,7 +120,7 @@
     oneway void dispatchMediaKeyEvent(in KeyEvent keyEvent);
     void dispatchMediaKeyEventUnderWakelock(in KeyEvent keyEvent);
 
-           void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c);
+           void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c, IBinder token);
     oneway void unregisterMediaButtonIntent(in PendingIntent pi);
 
     oneway void registerMediaButtonEventReceiverForCalls(in ComponentName c);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index b6b49a2..45a8b99 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -22,6 +22,7 @@
 import android.media.MediaFormat;
 import android.view.Surface;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import java.util.Map;
 
 /**
@@ -395,6 +396,27 @@
          * see {@link #CRYPTO_MODE_UNENCRYPTED} and {@link #CRYPTO_MODE_AES_CTR}.
          */
         public int mode;
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append(numSubSamples + " subsamples, key [");
+            String hexdigits = "0123456789abcdef";
+            for (int i = 0; i < key.length; i++) {
+                builder.append(hexdigits.charAt((key[i] & 0xf0) >> 4));
+                builder.append(hexdigits.charAt(key[i] & 0x0f));
+            }
+            builder.append("], iv [");
+            for (int i = 0; i < key.length; i++) {
+                builder.append(hexdigits.charAt((iv[i] & 0xf0) >> 4));
+                builder.append(hexdigits.charAt(iv[i] & 0x0f));
+            }
+            builder.append("], clear ");
+            builder.append(Arrays.toString(numBytesOfClearData));
+            builder.append(", encrypted ");
+            builder.append(Arrays.toString(numBytesOfEncryptedData));
+            return builder.toString();
+        }
     };
 
     /**
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 3cdf261..4eb0c56 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -25,6 +25,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.util.Log;
 
 /**
@@ -136,10 +137,8 @@
     public static final int MEDIA_DRM_EVENT_KEY_EXPIRED = 3;
     public static final int MEDIA_DRM_EVENT_VENDOR_DEFINED = 4;
 
-    /* Do not change these values without updating their counterparts
-     * in include/media/mediadrm.h!
-     */
     private static final int DRM_EVENT = 200;
+
     private class EventHandler extends Handler
     {
         private MediaDrm mMediaDrm;
@@ -161,10 +160,18 @@
                 Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
 
                 if (mOnEventListener != null) {
-                    Bundle bundle = msg.getData();
-                    byte[] sessionId = bundle.getByteArray("sessionId");
-                    byte[] data = bundle.getByteArray("data");
-                    mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
+                    if (msg.obj != null && msg.obj instanceof Parcel) {
+                        Parcel parcel = (Parcel)msg.obj;
+                        byte[] sessionId = parcel.createByteArray();
+                        if (sessionId.length == 0) {
+                            sessionId = null;
+                        }
+                        byte[] data = parcel.createByteArray();
+                        if (data.length == 0) {
+                            data = null;
+                        }
+                        mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
+                    }
                 }
                 return;
 
@@ -183,14 +190,14 @@
      * the cookie passed to native_setup().)
      */
     private static void postEventFromNative(Object mediadrm_ref,
-                                            int what, int arg1, int arg2, Object obj)
+                                            int eventType, int extra, Object obj)
     {
         MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
         if (md == null) {
             return;
         }
         if (md.mEventHandler != null) {
-            Message m = md.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+            Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj);
             md.mEventHandler.sendMessage(m);
         }
     }
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 749ef12..286e203 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -26,7 +26,10 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.UUID;
 
 /**
  * MediaExtractor facilitates extraction of demuxed, typically encoded,  media data
@@ -195,6 +198,38 @@
     public native final int getTrackCount();
 
     /**
+     * Get the PSSH info if present. This returns a map of uuid-to-bytes, with the uuid specifying
+     * the crypto scheme, and the bytes being the data specific to that scheme.
+     * {@hide}
+     */
+    public Map<UUID, byte[]> getPsshInfo() {
+        Map<UUID, byte[]> psshMap = null;
+        Map<String, Object> formatMap = getFileFormatNative();
+        if (formatMap != null && formatMap.containsKey("pssh")) {
+            ByteBuffer rawpssh = (ByteBuffer) formatMap.get("pssh");
+            rawpssh.order(ByteOrder.nativeOrder());
+            rawpssh.rewind();
+            formatMap.remove("pssh");
+            // parse the flat pssh bytebuffer into something more manageable
+            psshMap = new HashMap<UUID, byte[]>();
+            while (rawpssh.remaining() > 0) {
+                rawpssh.order(ByteOrder.BIG_ENDIAN);
+                long msb = rawpssh.getLong();
+                long lsb = rawpssh.getLong();
+                UUID uuid = new UUID(msb, lsb);
+                rawpssh.order(ByteOrder.nativeOrder());
+                int datalen = rawpssh.getInt();
+                byte [] psshdata = new byte[datalen];
+                rawpssh.get(psshdata);
+                psshMap.put(uuid, psshdata);
+            }
+        }
+        return psshMap;
+    }
+
+    private native Map<String, Object> getFileFormatNative();
+
+    /**
      * Get the track format at the specified index.
      * More detail on the representation can be found at {@link android.media.MediaCodec}
      */
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 1f5ca35..c0fbd2e 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -257,8 +257,10 @@
     }
 
     /**
-     * Writes an encoded sample into the muxer. The application needs to make
-     * sure that the samples are written into the right tracks.
+     * Writes an encoded sample into the muxer.
+     * <p>The application needs to make sure that the samples are written into
+     * the right tracks. Also, it needs to make sure the samples for each track
+     * are written in chronological order.</p>
      * @param byteBuf The encoded sample.
      * @param trackIndex The track index for this sample.
      * @param bufferInfo The buffer information related to this sample.
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 3a42db2..cd1d9ce 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -372,7 +372,7 @@
 
         default:
         {
-            jniThrowException(env, "java/lang/IllegalStateException", NULL);
+            jniThrowException(env, "java/lang/IllegalStateException", msg);
             break;
         }
     }
@@ -455,13 +455,13 @@
     sp<JMediaCodec> codec = getMediaCodec(env, thiz);
 
     if (codec == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        jniThrowException(env, "java/lang/IllegalStateException", "no codec found");
         return;
     }
 
     status_t err = codec->start();
 
-    throwExceptionAsNecessary(env, err);
+    throwExceptionAsNecessary(env, err, "start failed");
 }
 
 static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 1618edf..c32ba9d 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -21,10 +21,12 @@
 #include "android_media_MediaDrm.h"
 
 #include "android_runtime/AndroidRuntime.h"
+#include "android_os_Parcel.h"
 #include "jni.h"
 #include "JNIHelp.h"
 
 #include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
 #include <media/IDrm.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -43,6 +45,15 @@
     var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
     LOG_FATAL_IF(! var, "Unable to find method " fieldName);
 
+#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+    var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
+    LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
+    var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
+    LOG_FATAL_IF(! var, "Unable to find static method " fieldName);
+
+
 struct RequestFields {
     jfieldID data;
     jfieldID defaultUrl;
@@ -74,8 +85,16 @@
     jmethodID getValue;
 };
 
+struct EventTypes {
+    int kEventProvisionRequired;
+    int kEventKeyRequired;
+    int kEventKeyExpired;
+    int kEventVendorDefined;
+} gEventTypes;
+
 struct fields_t {
     jfieldID context;
+    jmethodID post_event;
     RequestFields keyRequest;
     RequestFields provisionRequest;
     ArrayListFields arraylist;
@@ -87,6 +106,88 @@
 
 static fields_t gFields;
 
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class JNIDrmListener: public DrmListener
+{
+public:
+    JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
+    ~JNIDrmListener();
+    virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
+private:
+    JNIDrmListener();
+    jclass      mClass;     // Reference to MediaDrm class
+    jobject     mObject;    // Weak ref to MediaDrm Java object to call on
+};
+
+JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
+{
+    // Hold onto the MediaDrm class for use in calling the static method
+    // that posts events to the application thread.
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        ALOGE("Can't find android/media/MediaDrm");
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return;
+    }
+    mClass = (jclass)env->NewGlobalRef(clazz);
+
+    // We use a weak reference so the MediaDrm object can be garbage collected.
+    // The reference is only used as a proxy for callbacks.
+    mObject  = env->NewGlobalRef(weak_thiz);
+}
+
+JNIDrmListener::~JNIDrmListener()
+{
+    // remove global references
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->DeleteGlobalRef(mObject);
+    env->DeleteGlobalRef(mClass);
+}
+
+void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
+                            const Parcel *obj)
+{
+    jint jeventType;
+
+    // translate DrmPlugin event types into their java equivalents
+    switch(eventType) {
+        case DrmPlugin::kDrmPluginEventProvisionRequired:
+            jeventType = gEventTypes.kEventProvisionRequired;
+            break;
+        case DrmPlugin::kDrmPluginEventKeyNeeded:
+            jeventType = gEventTypes.kEventKeyRequired;
+            break;
+        case DrmPlugin::kDrmPluginEventKeyExpired:
+            jeventType = gEventTypes.kEventKeyExpired;
+            break;
+        case DrmPlugin::kDrmPluginEventVendorDefined:
+            jeventType = gEventTypes.kEventVendorDefined;
+            break;
+        default:
+            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
+            return;
+    }
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (obj && obj->dataSize() > 0) {
+        jobject jParcel = createJavaParcelObject(env);
+        if (jParcel != NULL) {
+            Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
+            nativeParcel->setData(obj->data(), obj->dataSize());
+            env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
+                    jeventType, extra, jParcel);
+        }
+    }
+
+    if (env->ExceptionCheck()) {
+        ALOGW("An exception occurred while notifying an event.");
+        LOGW_EX(env);
+        env->ExceptionClear();
+    }
+}
+
+
 static bool throwExceptionAsNecessary(
         JNIEnv *env, status_t err, const char *msg = NULL) {
 
@@ -109,6 +210,9 @@
         JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
     mObject = env->NewWeakGlobalRef(thiz);
     mDrm = MakeDrm(uuid);
+    if (mDrm != NULL) {
+        mDrm->setListener(this);
+    }
 }
 
 JDrm::~JDrm() {
@@ -160,6 +264,25 @@
     return drm;
 }
 
+status_t JDrm::setListener(const sp<DrmListener>& listener) {
+    Mutex::Autolock lock(mLock);
+    mListener = listener;
+    return OK;
+}
+
+void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
+    sp<DrmListener> listener;
+    mLock.lock();
+    listener = mListener;
+    mLock.unlock();
+
+    if (listener != NULL) {
+        Mutex::Autolock lock(mNotifyLock);
+        listener->notify(eventType, extra, obj);
+    }
+}
+
+
 // static
 bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
     sp<IDrm> drm = MakeDrm();
@@ -194,10 +317,9 @@
 }
 
 static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
-    jboolean isCopy;
     String8 result;
 
-    const char *s = env->GetStringUTFChars(jstr, &isCopy);
+    const char *s = env->GetStringUTFChars(jstr, NULL);
     if (s) {
         result = s;
         env->ReleaseStringUTFChars(jstr, s);
@@ -322,13 +444,28 @@
 }
 
 static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
-    setDrm(env, thiz, NULL);
+    sp<JDrm> drm = setDrm(env, thiz, NULL);
+    if (drm != NULL) {
+        drm->setListener(NULL);
+    }
 }
 
 static void android_media_MediaDrm_native_init(JNIEnv *env) {
     jclass clazz;
     FIND_CLASS(clazz, "android/media/MediaDrm");
     GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I");
+    GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
+                         "(Ljava/lang/Object;IILjava/lang/Object;)V");
+
+    jfieldID field;
+    GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_PROVISION_REQUIRED", "I");
+    gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_REQUIRED", "I");
+    gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_EXPIRED", "I");
+    gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_VENDOR_DEFINED", "I");
+    gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
 
     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
     GET_FIELD_ID(gFields.keyRequest.data, clazz, "data", "[B");
@@ -389,6 +526,8 @@
         return;
     }
 
+    sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
+    drm->setListener(listener);
     setDrm(env, thiz, drm);
 }
 
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 01067c4..9b3917f 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -20,6 +20,8 @@
 #include "jni.h"
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/IDrm.h>
+#include <media/IDrmClient.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
@@ -27,15 +29,24 @@
 
 struct IDrm;
 
-struct JDrm : public RefBase {
+class DrmListener: virtual public RefBase
+{
+public:
+    virtual void notify(DrmPlugin::EventType eventType, int extra,
+                        const Parcel *obj) = 0;
+};
+
+struct JDrm : public BnDrmClient {
     static bool IsCryptoSchemeSupported(const uint8_t uuid[16]);
 
     JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16]);
 
     status_t initCheck() const;
-
     sp<IDrm> getDrm() { return mDrm; }
 
+    void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
+    status_t setListener(const sp<DrmListener>& listener);
+
 protected:
     virtual ~JDrm();
 
@@ -43,6 +54,10 @@
     jweak mObject;
     sp<IDrm> mDrm;
 
+    sp<DrmListener> mListener;
+    Mutex mNotifyLock;
+    Mutex mLock;
+
     static sp<IDrm> MakeDrm();
     static sp<IDrm> MakeDrm(const uint8_t uuid[16]);
 
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 23949fa..1704d5c 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -162,6 +162,18 @@
     return ConvertMessageToMap(env, msg, format);
 }
 
+status_t JMediaExtractor::getFileFormat(jobject *format) const {
+    sp<AMessage> msg;
+    status_t err;
+    if ((err = mImpl->getFileFormat(&msg)) != OK) {
+        return err;
+    }
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    return ConvertMessageToMap(env, msg, format);
+}
+
 status_t JMediaExtractor::selectTrack(size_t index) {
     return mImpl->selectTrack(index);
 }
@@ -339,6 +351,26 @@
     return format;
 }
 
+static jobject android_media_MediaExtractor_getFileFormatNative(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    jobject format;
+    status_t err = extractor->getFileFormat(&format);
+
+    if (err != OK) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return NULL;
+    }
+
+    return format;
+}
+
 static void android_media_MediaExtractor_selectTrack(
         JNIEnv *env, jobject thiz, jint index) {
     sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
@@ -768,6 +800,9 @@
 
     { "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
 
+    { "getFileFormatNative", "()Ljava/util/Map;",
+        (void *)android_media_MediaExtractor_getFileFormatNative },
+
     { "getTrackFormatNative", "(I)Ljava/util/Map;",
         (void *)android_media_MediaExtractor_getTrackFormatNative },
 
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index 03900db..ccbad8c 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -45,6 +45,8 @@
     size_t countTracks() const;
     status_t getTrackFormat(size_t index, jobject *format) const;
 
+    status_t getFileFormat(jobject *format) const;
+
     status_t selectTrack(size_t index);
     status_t unselectTrack(size_t index);
 
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
index 7628754..f859880 100644
--- a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
+++ b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
@@ -97,7 +97,7 @@
     public UniverseBackground(Context context) {
         super(context);
         setBackgroundColor(0xff000000);
-        mSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+        mSession = WindowManagerGlobal.getWindowSession();
         mContent = View.inflate(context, R.layout.universe, null);
         addView(mContent);
         mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/FirstFrameAnimatorHelper.java b/packages/SystemUI/src/com/android/systemui/recent/FirstFrameAnimatorHelper.java
new file mode 100644
index 0000000..2fc7dfc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/FirstFrameAnimatorHelper.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.Animator.AnimatorListener;
+import android.util.Log;
+import android.view.ViewTreeObserver;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+
+/*
+ *  This is a helper class that listens to updates from the corresponding animation.
+ *  For the first two frames, it adjusts the current play time of the animation to
+ *  prevent jank at the beginning of the animation
+ */
+public class FirstFrameAnimatorHelper implements ValueAnimator.AnimatorUpdateListener {
+    private static final boolean DEBUG = false;
+    private static final int MAX_DELAY = 1000;
+    private static final int IDEAL_FRAME_DURATION = 16;
+    private View mTarget;
+    private long mStartFrame;
+    private long mStartTime = -1;
+    private boolean mHandlingOnAnimationUpdate;
+    private boolean mAdjustedSecondFrameTime;
+
+    private static ViewTreeObserver.OnDrawListener sGlobalDrawListener;
+    private static long sGlobalFrameCounter;
+
+    public FirstFrameAnimatorHelper(ValueAnimator animator, View target) {
+        mTarget = target;
+        animator.addUpdateListener(this);
+    }
+
+    public FirstFrameAnimatorHelper(ViewPropertyAnimator vpa, View target) {
+        mTarget = target;
+        vpa.setListener(new AnimatorListenerAdapter() {
+                public void onAnimationStart (Animator animation) {
+                    final ValueAnimator va = (ValueAnimator) animation;
+                    va.addUpdateListener(FirstFrameAnimatorHelper.this);
+                    onAnimationUpdate(va);
+                }
+            });
+    }
+
+    public static void initializeDrawListener(View view) {
+        if (sGlobalDrawListener != null) {
+            view.getViewTreeObserver().removeOnDrawListener(sGlobalDrawListener);
+        }
+        sGlobalDrawListener = new ViewTreeObserver.OnDrawListener() {
+                private long mTime = System.currentTimeMillis();
+                public void onDraw() {
+                    sGlobalFrameCounter++;
+                    if (DEBUG) {
+                        long newTime = System.currentTimeMillis();
+                        Log.d("FirstFrameAnimatorHelper", "TICK " + (newTime - mTime));
+                        mTime = newTime;
+                    }
+                }
+            };
+        view.getViewTreeObserver().addOnDrawListener(sGlobalDrawListener);
+    }
+
+    public void onAnimationUpdate(final ValueAnimator animation) {
+        final long currentTime = System.currentTimeMillis();
+        if (mStartTime == -1) {
+            mStartFrame = sGlobalFrameCounter;
+            mStartTime = currentTime;
+        }
+
+        if (!mHandlingOnAnimationUpdate) {
+            mHandlingOnAnimationUpdate = true;
+            long frameNum = sGlobalFrameCounter - mStartFrame;
+            // If we haven't drawn our first frame, reset the time to t = 0
+            // (give up after MAX_DELAY ms of waiting though - might happen, for example, if we
+            // are no longer in the foreground and no frames are being rendered ever)
+            if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY) {
+                // The first frame on animations doesn't always trigger an invalidate...
+                // force an invalidate here to make sure the animation continues to advance
+                mTarget.getRootView().invalidate();
+                animation.setCurrentPlayTime(0);
+
+            // For the second frame, if the first frame took more than 16ms,
+            // adjust the start time and pretend it took only 16ms anyway. This
+            // prevents a large jump in the animation due to an expensive first frame
+            } else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
+                       !mAdjustedSecondFrameTime &&
+                       currentTime > mStartTime + IDEAL_FRAME_DURATION) {
+                animation.setCurrentPlayTime(IDEAL_FRAME_DURATION);
+                mAdjustedSecondFrameTime = true;
+            } else {
+                if (frameNum > 1) {
+                    mTarget.post(new Runnable() {
+                            public void run() {
+                                animation.removeUpdateListener(FirstFrameAnimatorHelper.this);
+                            }
+                        });
+                }
+                if (DEBUG) print(animation);
+            }
+            mHandlingOnAnimationUpdate = false;
+        } else {
+            if (DEBUG) print(animation);
+        }
+    }
+
+    public void print(ValueAnimator animation) {
+        float flatFraction = animation.getCurrentPlayTime() / (float) animation.getDuration();
+        Log.d("FirstFrameAnimatorHelper", sGlobalFrameCounter +
+              "(" + (sGlobalFrameCounter - mStartFrame) + ") " + mTarget + " dirty? " +
+              mTarget.isDirty() + " " + flatFraction + " " + this + " " + animation);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 9c2bca9..32759de 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -45,8 +45,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.ViewPropertyAnimator;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
@@ -195,50 +194,27 @@
                             oldHolder.calloutLine.setTranslationY(0f);
                         }
                     }
-                    mItemToAnimateInWhenWindowAnimationIsFinished = null;
-
-                    final ViewTreeObserver observer = getViewTreeObserver();
-                    final OnGlobalLayoutListener animateFirstIcon = new OnGlobalLayoutListener() {
-                        public void onGlobalLayout() {
-                            ViewHolder oldHolder = mItemToAnimateInWhenWindowAnimationIsFinished;
-                            if (oldHolder != null) {
-                                oldHolder.iconView.setAlpha(1f);
-                                oldHolder.iconView.setTranslationX(0f);
-                                oldHolder.iconView.setTranslationY(0f);
-                                oldHolder.labelView.setAlpha(1f);
-                                oldHolder.labelView.setTranslationX(0f);
-                                oldHolder.labelView.setTranslationY(0f);
-                                if (oldHolder.calloutLine != null) {
-                                    oldHolder.calloutLine.setAlpha(1f);
-                                    oldHolder.calloutLine.setTranslationX(0f);
-                                    oldHolder.calloutLine.setTranslationY(0f);
-                                }
-                            }
-                            mItemToAnimateInWhenWindowAnimationIsFinished = holder;
-                            int translation = -getResources().getDimensionPixelSize(
-                                    R.dimen.status_bar_recents_app_icon_translate_distance);
-                            final Configuration config = getResources().getConfiguration();
-                            if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
-                                if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
-                                    translation = -translation;
-                                }
-                                holder.iconView.setAlpha(0f);
-                                holder.iconView.setTranslationX(translation);
-                                holder.labelView.setAlpha(0f);
-                                holder.labelView.setTranslationX(translation);
-                                holder.calloutLine.setAlpha(0f);
-                                holder.calloutLine.setTranslationX(translation);
-                            } else {
-                                holder.iconView.setAlpha(0f);
-                                holder.iconView.setTranslationY(translation);
-                            }
-                            if (!mWaitingForWindowAnimation) {
-                                animateInIconOfFirstTask();
-                            }
-                            getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    mItemToAnimateInWhenWindowAnimationIsFinished = holder;
+                    int translation = -getResources().getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_icon_translate_distance);
+                    final Configuration config = getResources().getConfiguration();
+                    if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                        if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+                            translation = -translation;
                         }
-                    };
-                    observer.addOnGlobalLayoutListener(animateFirstIcon);
+                        holder.iconView.setAlpha(0f);
+                        holder.iconView.setTranslationX(translation);
+                        holder.labelView.setAlpha(0f);
+                        holder.labelView.setTranslationX(translation);
+                        holder.calloutLine.setAlpha(0f);
+                        holder.calloutLine.setTranslationX(translation);
+                    } else {
+                        holder.iconView.setAlpha(0f);
+                        holder.iconView.setTranslationY(translation);
+                    }
+                    if (!mWaitingForWindowAnimation) {
+                        animateInIconOfFirstTask();
+                    }
                 }
             }
 
@@ -586,17 +562,20 @@
                 !mRecentTasksLoader.isFirstScreenful()) {
             int timeSinceWindowAnimation =
                     (int) (System.currentTimeMillis() - mWindowAnimationStartTime);
-            final int minStartDelay = 150;
+            final int minStartDelay = 125;
             final int startDelay = Math.max(0, Math.min(
                     minStartDelay - timeSinceWindowAnimation, minStartDelay));
             final int duration = 250;
             final ViewHolder holder = mItemToAnimateInWhenWindowAnimationIsFinished;
             final TimeInterpolator cubic = new DecelerateInterpolator(1.5f);
+            FirstFrameAnimatorHelper.initializeDrawListener(holder.iconView);
             for (View v :
                 new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
                 if (v != null) {
-                    v.animate().translationX(0).translationY(0).alpha(1f).setStartDelay(startDelay)
+                    ViewPropertyAnimator vpa = v.animate().translationX(0).translationY(0)
+                            .alpha(1f).setStartDelay(startDelay)
                             .setDuration(duration).setInterpolator(cubic);
+                    FirstFrameAnimatorHelper h = new FirstFrameAnimatorHelper(vpa, v);
                 }
             }
             mItemToAnimateInWhenWindowAnimationIsFinished = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7bdcf6e..5b911c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -17,11 +17,11 @@
 
 package com.android.systemui.statusbar;
 
+import android.service.notification.StatusBarNotification;
 import android.content.res.Configuration;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.internal.widget.SizeAdaptiveLayout;
 import com.android.systemui.R;
 import com.android.systemui.SearchPanelView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 752bb0c..cbbaab3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -20,10 +20,10 @@
 import android.os.IBinder;
 import android.os.Message;
 
+import android.service.notification.StatusBarNotification;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
 
 /**
  * This class takes the functions from IStatusBar that come in on
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index c82f250..886ed77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,12 +16,11 @@
 
 package com.android.systemui.statusbar;
 
-import android.app.Notification;
+import android.service.notification.StatusBarNotification;
 import android.os.IBinder;
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.R;
 
 import java.util.Comparator;
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 9f54573..c2dc159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -26,6 +26,7 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
+import android.service.notification.StatusBarNotification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -76,7 +77,6 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -708,6 +708,7 @@
 
     private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
         public void onClick(View v) {
+            awakenDreams();
             toggleRecentApps();
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index ecc70d6..976dd01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.service.notification.StatusBarNotification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -23,10 +24,7 @@
 import android.text.StaticLayout;
 import android.text.Layout.Alignment;
 import android.text.TextPaint;
-import android.text.TextUtils;
-import android.util.Slog;
 import android.view.View;
-import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.widget.TextSwitcher;
 import android.widget.TextView;
@@ -35,7 +33,6 @@
 import java.util.ArrayList;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.internal.util.CharSequences;
 
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 0944b40..68d048d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -28,16 +28,11 @@
 import android.location.LocationManager;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.util.Slog;
-import android.view.View;
-import android.widget.ImageView;
 
 // private NM API
 import android.app.INotificationManager;
-import com.android.internal.statusbar.StatusBarNotification;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 
 public class LocationController extends BroadcastReceiver {
     private static final String TAG = "StatusBar.LocationController";
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 3d6bfe7..05bba89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -23,6 +23,7 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
+import android.service.notification.StatusBarNotification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -58,7 +59,6 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 0859874..725d9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -21,9 +21,9 @@
 import android.animation.LayoutTransition;
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.service.notification.StatusBarNotification;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -37,11 +37,9 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBarIconView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 413cc78..dc5de02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.tv;
 
+import android.service.notification.StatusBarNotification;
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.statusbar.BaseStatusBar;
 
 import android.os.IBinder;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 49460de..5f9e921 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -59,6 +59,8 @@
 import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -1801,7 +1803,23 @@
                 ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
                 : com.android.internal.R.anim.lock_screen_behind_enter);
     }
-    
+
+    private static void awakenDreams() {
+        IDreamManager dreamManager = getDreamManager();
+        if (dreamManager != null) {
+            try {
+                dreamManager.awaken();
+            } catch (RemoteException e) {
+                // fine, stay asleep then
+            }
+        }
+    }
+
+    static IDreamManager getDreamManager() {
+        return IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
+    }
+
     static ITelephony getTelephonyService() {
         return ITelephony.Stub.asInterface(
                 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
@@ -4550,6 +4568,7 @@
     }
 
     void startDockOrHome() {
+        awakenDreams();
         // We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
         mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
     }
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 43d76bb..602afd4 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -882,8 +882,9 @@
                 snprintf(name, sizeof(name), "%d", range.axis);
             }
             dump.appendFormat(INDENT3 "%s: source=0x%08x, "
-                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
-                    name, range.source, range.min, range.max, range.flat, range.fuzz);
+                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
+                    name, range.source, range.min, range.max, range.flat, range.fuzz,
+                    range.resolution);
         }
     }
 
@@ -2247,20 +2248,20 @@
     if (mParameters.mode == Parameters::MODE_POINTER) {
         float minX, minY, maxX, maxY;
         if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
-            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
+            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
+            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
         }
     } else {
-        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
-        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
+        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
+        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
     }
-    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
+    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
 
     if (mCursorScrollAccumulator.haveRelativeVWheel()) {
-        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
+        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
     }
     if (mCursorScrollAccumulator.haveRelativeHWheel()) {
-        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
+        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
     }
 }
 
@@ -2611,10 +2612,12 @@
         }
 
         if (mCursorScrollAccumulator.haveRelativeVWheel()) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
+            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+                    0.0f);
         }
         if (mCursorScrollAccumulator.haveRelativeHWheel()) {
-            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
+            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+                    0.0f);
         }
     }
 }
@@ -3063,6 +3066,7 @@
             mOrientedRanges.touchMajor.max = diagonalSize;
             mOrientedRanges.touchMajor.flat = 0;
             mOrientedRanges.touchMajor.fuzz = 0;
+            mOrientedRanges.touchMajor.resolution = 0;
 
             mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
             mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
@@ -3073,6 +3077,7 @@
             mOrientedRanges.toolMajor.max = diagonalSize;
             mOrientedRanges.toolMajor.flat = 0;
             mOrientedRanges.toolMajor.fuzz = 0;
+            mOrientedRanges.toolMajor.resolution = 0;
 
             mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
             mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
@@ -3083,6 +3088,7 @@
             mOrientedRanges.size.max = 1.0;
             mOrientedRanges.size.flat = 0;
             mOrientedRanges.size.fuzz = 0;
+            mOrientedRanges.size.resolution = 0;
         } else {
             mSizeScale = 0.0f;
         }
@@ -3106,6 +3112,7 @@
         mOrientedRanges.pressure.max = 1.0;
         mOrientedRanges.pressure.flat = 0;
         mOrientedRanges.pressure.fuzz = 0;
+        mOrientedRanges.pressure.resolution = 0;
 
         // Tilt
         mTiltXCenter = 0;
@@ -3129,6 +3136,7 @@
             mOrientedRanges.tilt.max = M_PI_2;
             mOrientedRanges.tilt.flat = 0;
             mOrientedRanges.tilt.fuzz = 0;
+            mOrientedRanges.tilt.resolution = 0;
         }
 
         // Orientation
@@ -3142,6 +3150,7 @@
             mOrientedRanges.orientation.max = M_PI;
             mOrientedRanges.orientation.flat = 0;
             mOrientedRanges.orientation.fuzz = 0;
+            mOrientedRanges.orientation.resolution = 0;
         } else if (mCalibration.orientationCalibration !=
                 Calibration::ORIENTATION_CALIBRATION_NONE) {
             if (mCalibration.orientationCalibration
@@ -3165,6 +3174,7 @@
             mOrientedRanges.orientation.max = M_PI_2;
             mOrientedRanges.orientation.flat = 0;
             mOrientedRanges.orientation.fuzz = 0;
+            mOrientedRanges.orientation.resolution = 0;
         }
 
         // Distance
@@ -3190,6 +3200,7 @@
             mOrientedRanges.distance.flat = 0;
             mOrientedRanges.distance.fuzz =
                     mRawPointerAxes.distance.fuzz * mDistanceScale;
+            mOrientedRanges.distance.resolution = 0;
         }
 
         // Compute oriented precision, scales and ranges.
@@ -3204,12 +3215,14 @@
             mOrientedRanges.x.min = mYTranslate;
             mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
             mOrientedRanges.x.flat = 0;
-            mOrientedRanges.x.fuzz = mYScale;
+            mOrientedRanges.x.fuzz = 0;
+            mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
 
             mOrientedRanges.y.min = mXTranslate;
             mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
             mOrientedRanges.y.flat = 0;
-            mOrientedRanges.y.fuzz = mXScale;
+            mOrientedRanges.y.fuzz = 0;
+            mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
             break;
 
         default:
@@ -3219,12 +3232,14 @@
             mOrientedRanges.x.min = mXTranslate;
             mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
             mOrientedRanges.x.flat = 0;
-            mOrientedRanges.x.fuzz = mXScale;
+            mOrientedRanges.x.fuzz = 0;
+            mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
 
             mOrientedRanges.y.min = mYTranslate;
             mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
             mOrientedRanges.y.flat = 0;
-            mOrientedRanges.y.fuzz = mYScale;
+            mOrientedRanges.y.fuzz = 0;
+            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
             break;
         }
 
@@ -6045,10 +6060,10 @@
     for (size_t i = 0; i < mAxes.size(); i++) {
         const Axis& axis = mAxes.valueAt(i);
         info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
-                axis.min, axis.max, axis.flat, axis.fuzz);
+                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
         if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
             info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
-                    axis.min, axis.max, axis.flat, axis.fuzz);
+                    axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
         }
     }
 }
@@ -6078,8 +6093,8 @@
             dump.append(" (invert)");
         }
 
-        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
-                axis.min, axis.max, axis.flat, axis.fuzz);
+        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
+                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
         dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
                 "highScale=%0.5f, highOffset=%0.5f\n",
                 axis.scale, axis.offset, axis.highScale, axis.highOffset);
@@ -6125,18 +6140,21 @@
                     float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
                             scale, 0.0f, highScale, 0.0f,
-                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
+                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
                 } else if (isCenteredAxis(axisInfo.axis)) {
                     float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
                     float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
                             scale, offset, scale, offset,
-                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
+                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
                 } else {
                     float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
                             scale, 0.0f, scale, 0.0f,
-                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
+                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+                            rawAxisInfo.resolution * scale);
                 }
 
                 // To eliminate noise while the joystick is at rest, filter out small variations
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index c596b37..8a52c06 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1730,10 +1730,11 @@
         float highScale;  // scale factor from raw to normalized values of high split
         float highOffset; // offset to add after scaling for normalization of high split
 
-        float min;     // normalized inclusive minimum
-        float max;     // normalized inclusive maximum
-        float flat;    // normalized flat region size
-        float fuzz;    // normalized error tolerance
+        float min;        // normalized inclusive minimum
+        float max;        // normalized inclusive maximum
+        float flat;       // normalized flat region size
+        float fuzz;       // normalized error tolerance
+        float resolution; // normalized resolution in units/mm
 
         float filter;  // filter out small variations of this size
         float currentValue; // current value
@@ -1744,7 +1745,7 @@
         void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
                 bool explicitlyMapped, float scale, float offset,
                 float highScale, float highOffset,
-                float min, float max, float flat, float fuzz) {
+                float min, float max, float flat, float fuzz, float resolution) {
             this->rawAxisInfo = rawAxisInfo;
             this->axisInfo = axisInfo;
             this->explicitlyMapped = explicitlyMapped;
@@ -1756,6 +1757,7 @@
             this->max = max;
             this->flat = flat;
             this->fuzz = fuzz;
+            this->resolution = resolution;
             this->filter = 0;
             resetValue();
         }
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 8bc2da2..59577ad 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -157,3 +157,8 @@
 # ConfigUpdateInstallReceiver.java
 # ---------------------------
 51300 config_install_failed (dir|3)
+
+# ---------------------------
+# IntentFirewall.java
+# ---------------------------
+51400 ifw_intent_matched (Intent Type|1|5),(Component Name|3),(Caller Uid|1|5),(Caller Pkg Count|1|1),(Caller Pkgs|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 3b541ec..a28c387 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1070,7 +1070,8 @@
             if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
             showCurrentInputLocked(getAppShowFlags(), null);
         }
-        return new InputBindResult(session.session, session.channel, mCurId, mCurSeq);
+        return new InputBindResult(session.session,
+                session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq);
     }
 
     InputBindResult startInputLocked(IInputMethodClient client,
@@ -2357,13 +2358,15 @@
                 return true;
             case MSG_CREATE_SESSION: {
                 args = (SomeArgs)msg.obj;
+                IInputMethod method = (IInputMethod)args.arg1;
                 InputChannel channel = (InputChannel)args.arg2;
                 try {
-                    ((IInputMethod)args.arg1).createSession(channel,
-                            (IInputSessionCallback)args.arg3);
+                    method.createSession(channel, (IInputSessionCallback)args.arg3);
                 } catch (RemoteException e) {
                 } finally {
-                    if (channel != null) {
+                    // Dispose the channel if the input method is not local to this process
+                    // because the remote proxy will get its own copy when unparceled.
+                    if (channel != null && Binder.isProxy(method)) {
                         channel.dispose();
                     }
                 }
@@ -2404,16 +2407,24 @@
                     // There is nothing interesting about the last client dying.
                 }
                 return true;
-            case MSG_BIND_METHOD:
+            case MSG_BIND_METHOD: {
                 args = (SomeArgs)msg.obj;
+                IInputMethodClient client = (IInputMethodClient)args.arg1;
+                InputBindResult res = (InputBindResult)args.arg2;
                 try {
-                    ((IInputMethodClient)args.arg1).onBindMethod(
-                            (InputBindResult)args.arg2);
+                    client.onBindMethod(res);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Client died receiving input method " + args.arg2);
+                } finally {
+                    // Dispose the channel if the input method is not local to this process
+                    // because the remote proxy will get its own copy when unparceled.
+                    if (res.channel != null && Binder.isProxy(client)) {
+                        res.channel.dispose();
+                    }
                 }
                 args.recycle();
                 return true;
+            }
             case MSG_SET_ACTIVE:
                 try {
                     ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 44d730c..cfb892f 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -26,16 +26,17 @@
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
-import android.app.INotificationListener;
 import android.app.ITransientNotification;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -57,6 +58,9 @@
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.notification.INotificationListener;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.AtomicFile;
@@ -68,8 +72,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
-import com.android.internal.statusbar.StatusBarNotification;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -121,6 +123,8 @@
     private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
     private static final boolean ENABLE_BLOCKED_TOASTS = true;
 
+    private static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":";
+
     final Context mContext;
     final IActivityManager mAm;
     final UserManager mUserManager;
@@ -163,8 +167,18 @@
 
     private final AppOpsManager mAppOps;
 
-    private ArrayList<NotificationListenerInfo> mListeners = new ArrayList<NotificationListenerInfo>();
-    private ArrayList<String> mEnabledListenersForCurrentUser = new ArrayList<String>();
+    // contains connections to all connected listeners, including app services
+    // and system listeners
+    private ArrayList<NotificationListenerInfo> mListeners
+            = new ArrayList<NotificationListenerInfo>();
+    // things that will be put into mListeners as soon as they're ready
+    private ArrayList<String> mServicesBinding = new ArrayList<String>();
+    // lists the component names of all enabled (and therefore connected) listener
+    // app services for the current user only
+    private HashSet<ComponentName> mEnabledListenersForCurrentUser
+            = new HashSet<ComponentName>();
+    // Just the packages from mEnabledListenersForCurrentUser
+    private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();
 
     // Notification control database. For now just contains disabled packages.
     private AtomicFile mPolicyFile;
@@ -181,27 +195,42 @@
 
     private class NotificationListenerInfo implements DeathRecipient {
         INotificationListener listener;
-        String pkg;
+        ComponentName component;
         int userid;
         boolean isSystem;
+        ServiceConnection connection;
 
-        public NotificationListenerInfo(INotificationListener listener, String pkg, int userid,
-                boolean isSystem) {
+        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
+                int userid, boolean isSystem) {
             this.listener = listener;
-            this.pkg = pkg;
+            this.component = component;
             this.userid = userid;
             this.isSystem = isSystem;
+            this.connection = null;
+        }
+
+        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
+                int userid, ServiceConnection connection) {
+            this.listener = listener;
+            this.component = component;
+            this.userid = userid;
+            this.isSystem = false;
+            this.connection = connection;
         }
 
         boolean enabledAndUserMatches(StatusBarNotification sbn) {
             final int nid = sbn.getUserId();
-            if (!(isSystem || isEnabledForUser(nid))) return false;
+            if (!isEnabledForCurrentUser()) {
+                return false;
+            }
             if (this.userid == UserHandle.USER_ALL) return true;
             return (nid == UserHandle.USER_ALL || nid == this.userid);
         }
 
         public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
-            if (!enabledAndUserMatches(sbn)) return;
+            if (!enabledAndUserMatches(sbn)) {
+                return;
+            }
             try {
                 listener.onNotificationPosted(sbn);
             } catch (RemoteException ex) {
@@ -220,15 +249,17 @@
 
         @Override
         public void binderDied() {
-            unregisterListener(this.listener, this.userid);
+            if (connection == null) {
+                // This is not a service; it won't be recreated. We can give up this connection.
+                unregisterListener(this.listener, this.userid);
+            }
         }
 
         /** convenience method for looking in mEnabledListenersForCurrentUser */
-        public boolean isEnabledForUser(int userid) {
-            for (int i=0; i<mEnabledListenersForCurrentUser.size(); i++) {
-                if (this.pkg.equals(mEnabledListenersForCurrentUser.get(i))) return true;
-            }
-            return false;
+        public boolean isEnabledForCurrentUser() {
+            if (this.isSystem) return true;
+            if (this.connection == null) return false;
+            return mEnabledListenersForCurrentUser.contains(this.component);
         }
     }
 
@@ -434,6 +465,12 @@
         }
     }
 
+    /**
+     * System-only API for getting a list of current (i.e. not cleared) notifications.
+     *
+     * Requires ACCESS_NOTIFICATIONS which is signature|system.
+     */
+    @Override
     public StatusBarNotification[] getActiveNotifications(String callingPkg) {
         // enforce() will ensure the calling uid has the correct permission
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
@@ -456,6 +493,12 @@
         return tmp;
     }
 
+    /**
+     * System-only API for getting a list of recent (cleared, no longer shown) notifications.
+     *
+     * Requires ACCESS_NOTIFICATIONS which is signature|system.
+     */
+    @Override
     public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
         // enforce() will ensure the calling uid has the correct permission
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
@@ -474,27 +517,76 @@
         return tmp;
     }
 
-    boolean packageCanTapNotificationsForUser(final int uid, final String pkg) {
-        // Make sure the package and uid match, and that the package is allowed access
-        return (AppOpsManager.MODE_ALLOWED
-            == mAppOps.checkOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, pkg));
+    /**
+     * Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS
+     * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
+     */
+    void rebindListenerServices() {
+        String flat = Settings.Secure.getString(
+                mContext.getContentResolver(),
+                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+
+        NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
+        final ArrayList<ComponentName> toAdd;
+        final int currentUser = ActivityManager.getCurrentUser();
+
+        synchronized (mNotificationList) {
+            // unbind and remove all existing listeners
+            toRemove = mListeners.toArray(toRemove);
+
+            toAdd = new ArrayList<ComponentName>();
+            final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
+            final HashSet<String> newPackages = new HashSet<String>();
+
+            // decode the list of components
+            if (flat != null) {
+                String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
+                for (int i=0; i<components.length; i++) {
+                    final ComponentName component
+                            = ComponentName.unflattenFromString(components[i]);
+                    if (component != null) {
+                        newEnabled.add(component);
+                        toAdd.add(component);
+                        newPackages.add(component.getPackageName());
+                    }
+                }
+
+                mEnabledListenersForCurrentUser = newEnabled;
+                mEnabledListenerPackageNames = newPackages;
+            }
+        }
+
+        for (NotificationListenerInfo info : toRemove) {
+            final ComponentName component = info.component;
+            final int oldUser = info.userid;
+            Slog.v(TAG, "disabling notification listener for user " + oldUser + ": " + component);
+            unregisterListenerService(component, info.userid);
+        }
+
+        final int N = toAdd.size();
+        for (int i=0; i<N; i++) {
+            final ComponentName component = toAdd.get(i);
+            Slog.v(TAG, "enabling notification listener for user " + currentUser + ": "
+                    + component);
+            registerListenerService(component, currentUser);
+        }
     }
 
+    /**
+     * Register a listener binder directly with the notification manager.
+     *
+     * Only works with system callers. Apps should extend
+     * {@link android.service.notification.NotificationListenerService}.
+     */
     @Override
     public void registerListener(final INotificationListener listener,
-            final String pkg, final int userid) {
-        // ensure system or allowed pkg
-        int uid = Binder.getCallingUid();
-        boolean isSystem = (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0);
-        if (!(isSystem || packageCanTapNotificationsForUser(uid, pkg))) {
-            throw new SecurityException("Package " + pkg
-                    + " may not listen for notifications");
-        }
+            final ComponentName component, final int userid) {
+        checkCallerIsSystem();
 
         synchronized (mNotificationList) {
             try {
                 NotificationListenerInfo info
-                        = new NotificationListenerInfo(listener, pkg, userid, isSystem);
+                        = new NotificationListenerInfo(listener, component, userid, true);
                 listener.asBinder().linkToDeath(info, 0);
                 mListeners.add(info);
             } catch (RemoteException e) {
@@ -503,6 +595,90 @@
         }
     }
 
+    /**
+     * Version of registerListener that takes the name of a
+     * {@link android.service.notification.NotificationListenerService} to bind to.
+     *
+     * This is the mechanism by which third parties may subscribe to notifications.
+     */
+    private void registerListenerService(final ComponentName name, final int userid) {
+        checkCallerIsSystem();
+
+        if (DBG) Slog.v(TAG, "registerListenerService: " + name + " u=" + userid);
+
+        synchronized (mNotificationList) {
+            final String servicesBindingTag = name.toString() + "/" + userid;
+            if (mServicesBinding.contains(servicesBindingTag)) {
+                // stop registering this thing already! we're working on it
+                return;
+            }
+            mServicesBinding.add(servicesBindingTag);
+
+            final int N = mListeners.size();
+            for (int i=N-1; i>=0; i--) {
+                final NotificationListenerInfo info = mListeners.get(i);
+                if (name.equals(info.component)
+                        && info.userid == userid) {
+                    // cut old connections
+                    if (DBG) Slog.v(TAG, "    disconnecting old listener: " + info.listener);
+                    mListeners.remove(i);
+                    if (info.connection != null) {
+                        mContext.unbindService(info.connection);
+                    }
+                }
+            }
+
+            Intent intent = new Intent(NotificationListenerService.SERVICE_INTERFACE);
+            intent.setComponent(name);
+
+            intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                    com.android.internal.R.string.notification_listener_binding_label);
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                    mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0));
+
+            try {
+                if (DBG) Slog.v(TAG, "binding: " + intent);
+                if (!mContext.bindServiceAsUser(intent,
+                        new ServiceConnection() {
+                            INotificationListener mListener;
+                            @Override
+                            public void onServiceConnected(ComponentName name, IBinder service) {
+                                synchronized (mNotificationList) {
+                                    mServicesBinding.remove(servicesBindingTag);
+                                    try {
+                                        mListener = INotificationListener.Stub.asInterface(service);
+                                        NotificationListenerInfo info = new NotificationListenerInfo(
+                                                mListener, name, userid, this);
+                                        service.linkToDeath(info, 0);
+                                        mListeners.add(info);
+                                    } catch (RemoteException e) {
+                                        // already dead
+                                    }
+                                }
+                            }
+
+                            @Override
+                            public void onServiceDisconnected(ComponentName name) {
+                                Slog.v(TAG, "notification listener connection lost: " + name);
+                            }
+                        },
+                        Context.BIND_AUTO_CREATE,
+                        new UserHandle(userid)))
+                {
+                    mServicesBinding.remove(servicesBindingTag);
+                    Slog.w(TAG, "Unable to bind listener service: " + intent);
+                    return;
+                }
+            } catch (SecurityException ex) {
+                Slog.e(TAG, "Unable to bind listener service: " + intent, ex);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Remove a listener binder directly
+     */
     @Override
     public void unregisterListener(INotificationListener listener, int userid) {
         // no need to check permissions; if your listener binder is in the list,
@@ -513,12 +689,39 @@
             for (int i=N-1; i>=0; i--) {
                 final NotificationListenerInfo info = mListeners.get(i);
                 if (info.listener == listener && info.userid == userid) {
-                    mListeners.remove(listener);
+                    mListeners.remove(i);
+                    if (info.connection != null) {
+                        mContext.unbindService(info.connection);
+                    }
                 }
             }
         }
     }
 
+    /**
+     * Remove a listener service for the given user by ComponentName
+     */
+    private void unregisterListenerService(ComponentName name, int userid) {
+        checkCallerIsSystem();
+
+        synchronized (mNotificationList) {
+            final int N = mListeners.size();
+            for (int i=N-1; i>=0; i--) {
+                final NotificationListenerInfo info = mListeners.get(i);
+                if (name.equals(info.component)
+                        && info.userid == userid) {
+                    mListeners.remove(i);
+                    if (info.connection != null) {
+                        mContext.unbindService(info.connection);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * asynchronously notify all listeners about a new notification
+     */
     private void notifyPostedLocked(NotificationRecord n) {
         final StatusBarNotification sbn = n.sbn;
         for (final NotificationListenerInfo info : mListeners) {
@@ -530,6 +733,9 @@
         }
     }
 
+    /**
+     * asynchronously notify all listeners about a removed notification
+     */
     private void notifyRemovedLocked(NotificationRecord n) {
         final StatusBarNotification sbn = n.sbn;
         for (final NotificationListenerInfo info : mListeners) {
@@ -541,6 +747,57 @@
         }
     }
 
+    // -- APIs to support listeners clicking/clearing notifications --
+
+    private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
+        final IBinder token = listener.asBinder();
+        final int N = mListeners.size();
+        for (int i=0; i<N; i++) {
+            final NotificationListenerInfo info = mListeners.get(i);
+            if (info.listener.asBinder() == token) return info;
+        }
+        throw new SecurityException("Disallowed call from unknown listener: " + listener);
+    }
+
+    /**
+     * Allow an INotificationListener to simulate a "clear all" operation.
+     *
+     * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications}
+     *
+     * @param token The binder for the listener, to check that the caller is allowed
+     */
+    public void clearAllNotificationsFromListener(INotificationListener token) {
+        NotificationListenerInfo info = checkListenerToken(token);
+        long identity = Binder.clearCallingIdentity();
+        try {
+            cancelAll(info.userid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
+     *
+     * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
+     *
+     * @param token The binder for the listener, to check that the caller is allowed
+     */
+    public void clearNotificationFromListener(INotificationListener token, String pkg, String tag, int id) {
+        NotificationListenerInfo info = checkListenerToken(token);
+        long identity = Binder.clearCallingIdentity();
+        try {
+            cancelNotification(pkg, tag, id, 0,
+                    Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
+                    true,
+                    info.userid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    // -- end of listener APIs --
+
     public static final class NotificationRecord
     {
         final StatusBarNotification sbn;
@@ -759,12 +1016,23 @@
                     }
                     pkgList = new String[]{pkgName};
                 }
+
+                boolean anyListenersInvolved = false;
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
                         cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
                                 UserHandle.USER_ALL);
+                        if (mEnabledListenerPackageNames.contains(pkgName)) {
+                            anyListenersInvolved = true;
+                        }
                     }
                 }
+
+                if (anyListenersInvolved) {
+                    // make sure we're still bound to any of our
+                    // listeners who may have just upgraded
+                    rebindListenerServices();
+                }
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 // Keep track of screen on/off state, but do not turn off the notification light
                 // until user passes through the lock screen or views the notification.
@@ -795,7 +1063,7 @@
                 = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
 
         private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
-                = Settings.System.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+                = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
 
         SettingsObserver(Handler handler) {
             super(handler);
@@ -804,9 +1072,9 @@
         void observe() {
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
-                    false, this);
+                    false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
-                    false, this);
+                    false, this, UserHandle.USER_ALL);
             update(null);
         }
 
@@ -825,19 +1093,7 @@
                 }
             }
             if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
-                String pkglist = Settings.Secure.getString(
-                        mContext.getContentResolver(),
-                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
-                mEnabledListenersForCurrentUser.clear();
-                if (pkglist != null) {
-                    String[] pkgs = pkglist.split(";");
-                    for (int i=0; i<pkgs.length; i++) {
-                        final String pkg = pkgs[i];
-                        if (pkg != null && ! "".equals(pkg)) {
-                            mEnabledListenersForCurrentUser.add(pkgs[i]);
-                        }
-                    }
-                }
+                rebindListenerServices();
             }
         }
     }
@@ -956,6 +1212,9 @@
 
         // no beeping until we're basically done booting
         mSystemReady = true;
+
+        // make sure our listener services are properly bound
+        rebindListenerServices();
     }
 
     // Toasts
@@ -1781,16 +2040,17 @@
 
         pw.println("Current Notification Manager state:");
 
-        pw.print("  Enabled listeners: [");
-        for (String pkg : mEnabledListenersForCurrentUser) {
-            pw.print(" " + pkg);
+        pw.println("  Listeners (" + mEnabledListenersForCurrentUser.size()
+                + ") enabled for current user:");
+        for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
+            pw.println("    " + cmpt);
         }
-        pw.println(" ]");
 
-        pw.println("  Live listeners:");
+        pw.println("  Live listeners (" + mListeners.size() + "):");
         for (NotificationListenerInfo info : mListeners) {
-            pw.println("    " + info.pkg + " (user " + info.userid + "): " + info.listener
-                + (info.isSystem?" SYSTEM":""));
+            pw.println("    " + info.component
+                    + " (user " + info.userid + "): " + info.listener
+                    + (info.isSystem?" SYSTEM":""));
         }
 
         int N;
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 1fe98af..c21d8c6 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.app.StatusBarManager;
+import android.service.notification.StatusBarNotification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -33,7 +34,6 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7710f13..cc7905c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3858,6 +3858,9 @@
                     if (app.userId != userId) {
                         continue;
                     }
+                    if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
+                        continue;
+                    }
                 // Package has been specified, we want to hit all processes
                 // that match it.  We need to qualify this by the processes
                 // that are running under the specified app and user ID.
@@ -7733,6 +7736,18 @@
     }
 
     @Override
+    public void killUid(int uid, String reason) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("killUid only available to the system");
+        }
+        synchronized (this) {
+            killPackageProcessesLocked(null, UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+                    ProcessList.FOREGROUND_APP_ADJ-1, false, true, true, false,
+                    reason != null ? reason : "kill uid");
+        }
+    }
+
+    @Override
     public boolean killProcessesBelowForeground(String reason) {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
             throw new SecurityException("killProcessesBelowForeground() only available to system");
@@ -8350,13 +8365,13 @@
         final String processName = app == null ? "system_server"
                 : (r == null ? "unknown" : r.processName);
 
-        handleApplicationCrashInner(r, processName, crashInfo);
+        handleApplicationCrashInner("crash", r, processName, crashInfo);
     }
 
     /* Native crash reporting uses this inner version because it needs to be somewhat
      * decoupled from the AM-managed cleanup lifecycle
      */
-    void handleApplicationCrashInner(ProcessRecord r, String processName,
+    void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName,
             ApplicationErrorReport.CrashInfo crashInfo) {
         EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
                 UserHandle.getUserId(Binder.getCallingUid()), processName,
@@ -8366,7 +8381,7 @@
                 crashInfo.throwFileName,
                 crashInfo.throwLineNumber);
 
-        addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
+        addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo);
 
         crashApplication(r, crashInfo);
     }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 3d7da7b..3d2e912 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2594,8 +2594,7 @@
         }
 
         boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
-                callerApp==null?null:callerApp.info, callingPackage, callingUid, callingPid,
-                resolvedType, aInfo);
+                callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
 
         if (mMainStack) {
             if (mService.mController != null) {
diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/java/com/android/server/am/NativeCrashListener.java
index e83433f..0688c50 100644
--- a/services/java/com/android/server/am/NativeCrashListener.java
+++ b/services/java/com/android/server/am/NativeCrashListener.java
@@ -82,7 +82,7 @@
                 ci.stackTrace = mCrashReport;
 
                 if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()");
-                mAm.handleApplicationCrashInner(mApp, mApp.processName, ci);
+                mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci);
                 if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned");
             } catch (Exception e) {
                 Slog.e(TAG, "Unable to report native crash", e);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 8ff1c7d..fccaab5 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -376,37 +376,37 @@
                             // icon, but this used to be able to slip through, so for
                             // those dirty apps give it the app's icon.
                             foregroundNoti.icon = appInfo.icon;
-                            if (foregroundNoti.contentView == null) {
-                                // In this case the app may not have specified a
-                                // content view...  so we'll give them something to show.
-                                CharSequence appName = appInfo.loadLabel(
-                                        ams.mContext.getPackageManager());
-                                if (appName == null) {
-                                    appName = appInfo.packageName;
-                                }
-                                Context ctx = null;
-                                try {
-                                    ctx = ams.mContext.createPackageContext(
-                                            appInfo.packageName, 0);
-                                    Intent runningIntent = new Intent(
-                                            Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-                                    runningIntent.setData(Uri.fromParts("package",
-                                            appInfo.packageName, null));
-                                    PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
-                                            runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-                                    foregroundNoti.setLatestEventInfo(ctx,
-                                            ams.mContext.getString(
-                                                    com.android.internal.R.string
-                                                            .app_running_notification_title,
-                                                    appName),
-                                            ams.mContext.getString(
-                                                    com.android.internal.R.string
-                                                            .app_running_notification_text,
-                                                    appName),
-                                            pi);
-                                } catch (PackageManager.NameNotFoundException e) {
-                                    foregroundNoti.icon = 0;
-                                }
+
+                            // Do not allow apps to present a sneaky invisible content view either.
+                            foregroundNoti.contentView = null;
+                            foregroundNoti.bigContentView = null;
+                            CharSequence appName = appInfo.loadLabel(
+                                    ams.mContext.getPackageManager());
+                            if (appName == null) {
+                                appName = appInfo.packageName;
+                            }
+                            Context ctx = null;
+                            try {
+                                ctx = ams.mContext.createPackageContext(
+                                        appInfo.packageName, 0);
+                                Intent runningIntent = new Intent(
+                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+                                runningIntent.setData(Uri.fromParts("package",
+                                        appInfo.packageName, null));
+                                PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
+                                        runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+                                foregroundNoti.setLatestEventInfo(ctx,
+                                        ams.mContext.getString(
+                                                com.android.internal.R.string
+                                                        .app_running_notification_title,
+                                                appName),
+                                        ams.mContext.getString(
+                                                com.android.internal.R.string
+                                                        .app_running_notification_text,
+                                                appName),
+                                        pi);
+                            } catch (PackageManager.NameNotFoundException e) {
+                                foregroundNoti.icon = 0;
                             }
                         }
                         if (foregroundNoti.icon == 0) {
diff --git a/services/java/com/android/server/firewall/AndFilter.java b/services/java/com/android/server/firewall/AndFilter.java
index cabf00b..e4276d0 100644
--- a/services/java/com/android/server/firewall/AndFilter.java
+++ b/services/java/com/android/server/firewall/AndFilter.java
@@ -26,11 +26,10 @@
 class AndFilter extends FilterList {
     @Override
     public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         for (int i=0; i<children.size(); i++) {
-            if (!children.get(i).matches(ifw, intent, callerApp, callerPackage, callerUid,
-                    callerPid, resolvedType, resolvedApp)) {
+            if (!children.get(i).matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+                    resolvedApp)) {
                 return false;
             }
         }
diff --git a/services/java/com/android/server/firewall/CategoryFilter.java b/services/java/com/android/server/firewall/CategoryFilter.java
index d5e9fe8..4938cb8 100644
--- a/services/java/com/android/server/firewall/CategoryFilter.java
+++ b/services/java/com/android/server/firewall/CategoryFilter.java
@@ -34,7 +34,7 @@
     }
 
     @Override
-    public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp, String callerPackage,
+    public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
             int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         Set<String> categories = intent.getCategories();
         if (categories == null) {
diff --git a/services/java/com/android/server/firewall/Filter.java b/services/java/com/android/server/firewall/Filter.java
index 7639466..0e783e8 100644
--- a/services/java/com/android/server/firewall/Filter.java
+++ b/services/java/com/android/server/firewall/Filter.java
@@ -26,17 +26,14 @@
      * @param ifw The IntentFirewall instance
      * @param intent The intent being started/bound/broadcast
      * @param callerApp An ApplicationInfo of an application in the caller's process. This may not
- *                  be the specific app that is actually sending the intent. This also may be
- *                  null, if the caller is the system process, or an unrecognized process (e.g.
- *                  am start)
-     * @param callerPackage The package name of the component sending the intent. This value is
-*                      provided by the caller and might be forged/faked.
+     *                  be the specific app that is actually sending the intent. This also may be
+     *                  null, if the caller is the system process, or an unrecognized process (e.g.
+     *                  am start)
      * @param callerUid
      * @param callerPid
      * @param resolvedType The resolved mime type of the intent
      * @param resolvedApp The application that contains the resolved component that the intent is
      */
     boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp);
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp);
 }
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index ebbbd86..08e6b45 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -16,18 +16,21 @@
 
 package com.android.server.firewall;
 
+import android.app.AppGlobals;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.os.Environment;
-import android.os.ServiceManager;
+import android.os.RemoteException;
 import android.util.Slog;
 import android.util.Xml;
 import com.android.internal.util.XmlUtils;
+import com.android.server.EventLogTags;
 import com.android.server.IntentResolver;
-import com.android.server.pm.PackageManagerService;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -42,13 +45,22 @@
 public class IntentFirewall {
     private static final String TAG = "IntentFirewall";
 
-    private static final String RULES_FILENAME = "ifw.xml";
+    // e.g. /data/system/ifw/ifw.xml or /data/secure/system/ifw/ifw.xml
+    private static final File RULES_FILE =
+            new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
+
+    private static final int LOG_PACKAGES_MAX_LENGTH = 150;
+    private static final int LOG_PACKAGES_SUFFICIENT_LENGTH = 125;
 
     private static final String TAG_RULES = "rules";
     private static final String TAG_ACTIVITY = "activity";
     private static final String TAG_SERVICE = "service";
     private static final String TAG_BROADCAST = "broadcast";
 
+    private static final int TYPE_ACTIVITY = 0;
+    private static final int TYPE_SERVICE = 1;
+    private static final int TYPE_BROADCAST = 2;
+
     private static final HashMap<String, FilterFactory> factoryMap;
 
     private final AMSInterface mAms;
@@ -74,7 +86,6 @@
                 StringFilter.HOST,
                 StringFilter.MIME_TYPE,
                 StringFilter.PATH,
-                StringFilter.SENDER_PACKAGE,
                 StringFilter.SSP,
 
                 CategoryFilter.FACTORY,
@@ -93,22 +104,19 @@
 
     public IntentFirewall(AMSInterface ams) {
         mAms = ams;
-        File dataSystemDir = new File(Environment.getDataDirectory(), "system");
-        File rulesFile = new File(dataSystemDir, RULES_FILENAME);
-        readRules(rulesFile);
+        readRules(getRulesFile());
     }
 
-    public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ActivityInfo resolvedActivity) {
+    public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp, int callerUid,
+            int callerPid, String resolvedType, ActivityInfo resolvedActivity) {
         List<Rule> matchingRules = mActivityResolver.queryIntent(intent, resolvedType, false, 0);
         boolean log = false;
         boolean block = false;
 
         for (int i=0; i< matchingRules.size(); i++) {
             Rule rule = matchingRules.get(i);
-            if (rule.matches(this, intent, callerApp, callerPackage, callerUid, callerPid,
-                    resolvedType, resolvedActivity.applicationInfo)) {
+            if (rule.matches(this, intent, callerApp, callerUid, callerPid, resolvedType,
+                    resolvedActivity.applicationInfo)) {
                 block |= rule.getBlock();
                 log |= rule.getLog();
 
@@ -121,12 +129,85 @@
         }
 
         if (log) {
-            // TODO: log info about intent to event log
+            logIntent(TYPE_ACTIVITY, intent, callerUid, resolvedType);
         }
 
         return !block;
     }
 
+    private static void logIntent(int intentType, Intent intent, int callerUid,
+            String resolvedType) {
+        // The component shouldn't be null, but let's double check just to be safe
+        ComponentName cn = intent.getComponent();
+        String shortComponent = null;
+        if (cn != null) {
+            shortComponent = cn.flattenToShortString();
+        }
+
+        String callerPackages = null;
+        int callerPackageCount = 0;
+        IPackageManager pm = AppGlobals.getPackageManager();
+        if (pm != null) {
+            try {
+                String[] callerPackagesArray = pm.getPackagesForUid(callerUid);
+                if (callerPackagesArray != null) {
+                    callerPackageCount = callerPackagesArray.length;
+                    callerPackages = joinPackages(callerPackagesArray);
+                }
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Remote exception while retrieving packages", ex);
+            }
+        }
+
+        EventLogTags.writeIfwIntentMatched(intentType, shortComponent, callerUid,
+                callerPackageCount, callerPackages, intent.getAction(), resolvedType,
+                intent.getDataString(), intent.getFlags());
+    }
+
+    /**
+     * Joins a list of package names such that the resulting string is no more than
+     * LOG_PACKAGES_MAX_LENGTH.
+     *
+     * Only full package names will be added to the result, unless every package is longer than the
+     * limit, in which case one of the packages will be truncated and added. In this case, an
+     * additional '-' character will be added to the end of the string, to denote the truncation.
+     *
+     * If it encounters a package that won't fit in the remaining space, it will continue on to the
+     * next package, unless the total length of the built string so far is greater than
+     * LOG_PACKAGES_SUFFICIENT_LENGTH, in which case it will stop and return what it has.
+     */
+    private static String joinPackages(String[] packages) {
+        boolean first = true;
+        StringBuilder sb = new StringBuilder();
+        for (int i=0; i<packages.length; i++) {
+            String pkg = packages[i];
+
+            // + 1 length for the comma. This logic technically isn't correct for the first entry,
+            // but it's not critical.
+            if (sb.length() + pkg.length() + 1 < LOG_PACKAGES_MAX_LENGTH) {
+                if (!first) {
+                    sb.append(',');
+                } else {
+                    first = false;
+                }
+                sb.append(pkg);
+            } else if (sb.length() >= LOG_PACKAGES_SUFFICIENT_LENGTH) {
+                return sb.toString();
+            }
+        }
+        if (sb.length() == 0 && packages.length > 0) {
+            String pkg = packages[0];
+            // truncating from the end - the last part of the package name is more likely to be
+            // interesting/unique
+            return pkg.substring(pkg.length() - LOG_PACKAGES_MAX_LENGTH + 1) + '-';
+        }
+        return null;
+    }
+
+    public static File getRulesFile() {
+        return RULES_FILE;
+    }
+
     private void readRules(File rulesFile) {
         FileInputStream fis;
         try {
@@ -309,7 +390,12 @@
     }
 
     boolean signaturesMatch(int uid1, int uid2) {
-        PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
-        return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "Remote exception while checking signatures", ex);
+            return false;
+        }
     }
 }
diff --git a/services/java/com/android/server/firewall/NotFilter.java b/services/java/com/android/server/firewall/NotFilter.java
index 2ff108a1..f0fc337 100644
--- a/services/java/com/android/server/firewall/NotFilter.java
+++ b/services/java/com/android/server/firewall/NotFilter.java
@@ -33,10 +33,9 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
-        return !mChild.matches(ifw, intent, callerApp, callerPackage, callerUid, callerPid,
-                resolvedType, resolvedApp);
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+        return !mChild.matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+                resolvedApp);
     }
 
     public static final FilterFactory FACTORY = new FilterFactory("not") {
diff --git a/services/java/com/android/server/firewall/OrFilter.java b/services/java/com/android/server/firewall/OrFilter.java
index 1ed1c85..72db31e 100644
--- a/services/java/com/android/server/firewall/OrFilter.java
+++ b/services/java/com/android/server/firewall/OrFilter.java
@@ -26,11 +26,10 @@
 class OrFilter extends FilterList {
     @Override
     public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         for (int i=0; i<children.size(); i++) {
-            if (children.get(i).matches(ifw, intent, callerApp, callerPackage, callerUid, callerPid,
-                    resolvedType, resolvedApp)) {
+            if (children.get(i).matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+                    resolvedApp)) {
                 return true;
             }
         }
diff --git a/services/java/com/android/server/firewall/PortFilter.java b/services/java/com/android/server/firewall/PortFilter.java
index 2b2a198..fe7e085 100644
--- a/services/java/com/android/server/firewall/PortFilter.java
+++ b/services/java/com/android/server/firewall/PortFilter.java
@@ -42,8 +42,7 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         int port = -1;
         Uri uri = intent.getData();
         if (uri != null) {
diff --git a/services/java/com/android/server/firewall/SenderFilter.java b/services/java/com/android/server/firewall/SenderFilter.java
index 0b790bd..58bdd73 100644
--- a/services/java/com/android/server/firewall/SenderFilter.java
+++ b/services/java/com/android/server/firewall/SenderFilter.java
@@ -68,8 +68,7 @@
     private static final Filter SIGNATURE = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-                String callerPackage, int callerUid, int callerPid, String resolvedType,
-                ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
             if (callerApp == null) {
                 return false;
             }
@@ -80,8 +79,7 @@
     private static final Filter SYSTEM = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-                String callerPackage, int callerUid, int callerPid, String resolvedType,
-                ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
             if (callerApp == null) {
                 // if callerApp is null, the caller is the system process
                 return false;
@@ -93,8 +91,7 @@
     private static final Filter SYSTEM_OR_SIGNATURE = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-                String callerPackage, int callerUid, int callerPid, String resolvedType,
-                ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
             return isSystemApp(callerApp, callerUid, callerPid) ||
                     ifw.signaturesMatch(callerUid, resolvedApp.uid);
         }
@@ -103,8 +100,7 @@
     private static final Filter USER_ID = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-                String callerPackage, int callerUid, int callerPid, String resolvedType,
-                ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
             // This checks whether the caller is either the system process, or has the same user id
             // I.e. the same app, or an app that uses the same shared user id.
             // This is the same set of applications that would be able to access the component if
diff --git a/services/java/com/android/server/firewall/SenderPermissionFilter.java b/services/java/com/android/server/firewall/SenderPermissionFilter.java
index 02d8b15..310da20 100644
--- a/services/java/com/android/server/firewall/SenderPermissionFilter.java
+++ b/services/java/com/android/server/firewall/SenderPermissionFilter.java
@@ -34,8 +34,7 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
-            String callerPackage, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         // We assume the component is exported here. If the component is not exported, then
         // ActivityManager would only resolve to this component for callers from the same uid.
         // In this case, it doesn't matter whether the component is exported or not.
diff --git a/services/java/com/android/server/firewall/StringFilter.java b/services/java/com/android/server/firewall/StringFilter.java
index de5a69f..ed5d3f3 100644
--- a/services/java/com/android/server/firewall/StringFilter.java
+++ b/services/java/com/android/server/firewall/StringFilter.java
@@ -119,10 +119,9 @@
     protected abstract boolean matchesValue(String value);
 
     @Override
-    public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp, String callerPackage,
+    public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
             int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
-        String value = mValueProvider.getValue(intent, callerApp, callerPackage, resolvedType,
-                resolvedApp);
+        String value = mValueProvider.getValue(intent, callerApp, resolvedType, resolvedApp);
         return matchesValue(value);
     }
 
@@ -137,7 +136,7 @@
         }
 
         public abstract String getValue(Intent intent, ApplicationInfo callerApp,
-                String callerPackage, String resolvedType, ApplicationInfo resolvedApp);
+                String resolvedType, ApplicationInfo resolvedApp);
     }
 
     private static class EqualsFilter extends StringFilter {
@@ -231,8 +230,8 @@
 
     public static final ValueProvider COMPONENT = new ValueProvider("component") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             ComponentName cn = intent.getComponent();
             if (cn != null) {
                 return cn.flattenToString();
@@ -243,8 +242,8 @@
 
     public static final ValueProvider COMPONENT_NAME = new ValueProvider("component-name") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             ComponentName cn = intent.getComponent();
             if (cn != null) {
                 return cn.getClassName();
@@ -255,8 +254,8 @@
 
     public static final ValueProvider COMPONENT_PACKAGE = new ValueProvider("component-package") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             ComponentName cn = intent.getComponent();
             if (cn != null) {
                 return cn.getPackageName();
@@ -265,28 +264,18 @@
         }
     };
 
-    public static final ValueProvider SENDER_PACKAGE = new ValueProvider("sender-package") {
-        @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
-            // TODO: We can't trust this value, so maybe should check all packages in the caller process?
-            return callerPackage;
-        }
-    };
-
-
     public static final FilterFactory ACTION = new ValueProvider("action") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             return intent.getAction();
         }
     };
 
     public static final ValueProvider DATA = new ValueProvider("data") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.toString();
@@ -297,16 +286,16 @@
 
     public static final ValueProvider MIME_TYPE = new ValueProvider("mime-type") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             return resolvedType;
         }
     };
 
     public static final ValueProvider SCHEME = new ValueProvider("scheme") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getScheme();
@@ -317,8 +306,8 @@
 
     public static final ValueProvider SSP = new ValueProvider("scheme-specific-part") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getSchemeSpecificPart();
@@ -329,8 +318,8 @@
 
     public static final ValueProvider HOST = new ValueProvider("host") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getHost();
@@ -341,8 +330,8 @@
 
     public static final ValueProvider PATH = new ValueProvider("path") {
         @Override
-        public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
-                String resolvedType, ApplicationInfo resolvedApp) {
+        public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+                ApplicationInfo resolvedApp) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getPath();
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index ca7bba2..cc9b785 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -2308,6 +2308,8 @@
     }
 
     public void revokePermission(String packageName, String permissionName) {
+        int changedAppId = -1;
+
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
@@ -2335,6 +2337,30 @@
                     gp.gids = removeInts(gp.gids, bp.gids);
                 }
                 mSettings.writeLPr();
+                changedAppId = ps.appId;
+            }
+        }
+
+        if (changedAppId >= 0) {
+            // We changed the perm on someone, kill its processes.
+            IActivityManager am = ActivityManagerNative.getDefault();
+            if (am != null) {
+                final int callingUserId = UserHandle.getCallingUserId();
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    //XXX we should only revoke for the calling user's app permissions,
+                    // but for now we impact all users.
+                    //am.killUid(UserHandle.getUid(callingUserId, changedAppId),
+                    //        "revoke " + permissionName);
+                    int[] users = sUserManager.getUserIds();
+                    for (int user : users) {
+                        am.killUid(UserHandle.getUid(user, changedAppId),
+                                "revoke " + permissionName);
+                    }
+                } catch (RemoteException e) {
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             }
         }
     }
@@ -8647,14 +8673,16 @@
                 mSettings.writeLPr();
             }
         }
-        // A user ID was deleted here. Go through all users and remove it from
-        // KeyStore.
-        final int appId = outInfo.removedAppId;
-        if (appId != -1) {
-            final KeyStore keyStore = KeyStore.getInstance();
-            if (keyStore != null) {
-                for (final int userId : sUserManager.getUserIds()) {
-                    keyStore.clearUid(UserHandle.getUid(userId, appId));
+        if (outInfo != null) {
+            // A user ID was deleted here. Go through all users and remove it
+            // from KeyStore.
+            final int appId = outInfo.removedAppId;
+            if (appId != -1) {
+                final KeyStore keyStore = KeyStore.getInstance();
+                if (keyStore != null) {
+                    for (final int userId : sUserManager.getUserIds()) {
+                        keyStore.clearUid(UserHandle.getUid(userId, appId));
+                    }
                 }
             }
         }
@@ -10655,19 +10683,18 @@
                         || mSettings.mReadExternalStorageEnforced != enforced) {
                     mSettings.mReadExternalStorageEnforced = enforced;
                     mSettings.writeLPr();
-
-                    // kill any non-foreground processes so we restart them and
-                    // grant/revoke the GID.
-                    final IActivityManager am = ActivityManagerNative.getDefault();
-                    if (am != null) {
-                        final long token = Binder.clearCallingIdentity();
-                        try {
-                            am.killProcessesBelowForeground("setPermissionEnforcement");
-                        } catch (RemoteException e) {
-                        } finally {
-                            Binder.restoreCallingIdentity(token);
-                        }
-                    }
+                }
+            }
+            // kill any non-foreground processes so we restart them and
+            // grant/revoke the GID.
+            final IActivityManager am = ActivityManagerNative.getDefault();
+            if (am != null) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    am.killProcessesBelowForeground("setPermissionEnforcement");
+                } catch (RemoteException e) {
+                } finally {
+                    Binder.restoreCallingIdentity(token);
                 }
             }
         } else {
diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
index d603cfa..c94f7c1 100644
--- a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
+++ b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -226,8 +226,6 @@
         FileOutputStream out = null;
         File tmp = null;
         try {
-            // create the temporary file
-            tmp = File.createTempFile("journal", "", dir);
             // create the parents for the destination file
             File parent = file.getParentFile();
             parent.mkdirs();
@@ -235,6 +233,8 @@
             if (!parent.exists()) {
                 throw new IOException("Failed to create directory " + parent.getCanonicalPath());
             }
+            // create the temporary file
+            tmp = File.createTempFile("journal", "", dir);
             // mark tmp -rw-r--r--
             tmp.setReadable(true, false);
             // write to it
diff --git a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java b/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
new file mode 100644
index 0000000..9185903
--- /dev/null
+++ b/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.updates;
+
+import com.android.server.firewall.IntentFirewall;
+
+public class IntentFirewallInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    public IntentFirewallInstallReceiver() {
+        super(IntentFirewall.getRulesFile().getParent(), IntentFirewall.getRulesFile().getName(),
+                "metadata/", "version");
+    }
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index cbc42eb..af603fd 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5365,6 +5365,9 @@
                     if (maxLayer < winAnim.mSurfaceLayer) {
                         maxLayer = winAnim.mSurfaceLayer;
                     }
+                    if (minLayer > winAnim.mSurfaceLayer) {
+                        minLayer = winAnim.mSurfaceLayer;
+                    }
 
                     // Don't include wallpaper in bounds calculation
                     if (!ws.mIsWallpaper) {
@@ -5377,17 +5380,14 @@
                         frame.union(left, top, right, bottom);
                     }
 
-                    if (ws.mAppToken != null && ws.mAppToken.token == appToken) {
-                        if (minLayer > ws.mWinAnimator.mSurfaceLayer) {
-                            minLayer = ws.mWinAnimator.mSurfaceLayer;
-                        }
-                        if (ws.isDisplayedLw()) {
-                            screenshotReady = true;
-                        }
-                        if (fullscreen) {
-                            // No point in continuing down through windows.
-                            break;
-                        }
+                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
+                            ws.isDisplayedLw()) {
+                        screenshotReady = true;
+                    }
+
+                    if (fullscreen) {
+                        // No point in continuing down through windows.
+                        break;
                     }
                 }
 
@@ -5461,14 +5461,12 @@
                 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
             }
         } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
-        if (DEBUG_SCREENSHOT && retryCount > MAX_SCREENSHOT_RETRIES) {
-            Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + " appWin="
-                    + (appWin == null ? "null" : (appWin + " drawState="
-                            + appWin.mWinAnimator.mDrawState)));
-        }
+        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
+                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
+                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
 
         if (rawss == null) {
-            Slog.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh
+            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
                     + ") to layer " + maxLayer);
             return null;
         }
@@ -5481,7 +5479,7 @@
         canvas.drawBitmap(rawss, matrix, null);
         canvas.setBitmap(null);
 
-        if (DEBUG_SCREENSHOT) {
+        if (true || DEBUG_SCREENSHOT) {
             // TEST IF IT's ALL BLACK
             int[] buffer = new int[bm.getWidth() * bm.getHeight()];
             bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
@@ -5494,7 +5492,8 @@
             }
             if (allBlack) {
                 Slog.i(TAG, "Screenshot " + appWin + " was all black! mSurfaceLayer=" +
-                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null"));
+                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
+                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
             }
         }
 
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 3ed9cef..674955c 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -274,6 +274,33 @@
     }
 
     /**
+     * Make a SignalStrength object from the given parcel as passed up by
+     * the ril which does not have isGsm. isGsm will be changed by ServiceStateTracker
+     * so the default is a don't care.
+     *
+     * @hide
+     */
+    public static SignalStrength makeSignalStrengthFromRilParcel(Parcel in) {
+        if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
+
+        SignalStrength ss = new SignalStrength();
+        ss.mGsmSignalStrength = in.readInt();
+        ss.mGsmBitErrorRate = in.readInt();
+        ss.mCdmaDbm = in.readInt();
+        ss.mCdmaEcio = in.readInt();
+        ss.mEvdoDbm = in.readInt();
+        ss.mEvdoEcio = in.readInt();
+        ss.mEvdoSnr = in.readInt();
+        ss.mLteSignalStrength = in.readInt();
+        ss.mLteRsrp = in.readInt();
+        ss.mLteRsrq = in.readInt();
+        ss.mLteRssnr = in.readInt();
+        ss.mLteCqi = in.readInt();
+
+        return ss;
+    }
+
+    /**
      * {@link Parcelable#writeToParcel}
      */
     public void writeToParcel(Parcel out, int flags) {
diff --git a/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java b/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
index 854a3f4..dbaedf9 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
@@ -47,7 +47,7 @@
         {
             public void onClick (View v)
             {
-                InputMethodManager imm = InputMethodManager.getInstance(instance);
+                InputMethodManager imm = InputMethodManager.getInstance();
                 if (mKeyboardIsActive)
                 {
                     imm.hideSoftInputFromInputMethod(v.getWindowToken(), 0);
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
index bc77e04..32f80a3 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
@@ -66,7 +66,7 @@
         mExpectAutoPop = (keyboardType  == Configuration.KEYBOARD_NOKEYS ||
                 keyboardType == Configuration.KEYBOARD_UNDEFINED);
 
-        mImm = InputMethodManager.getInstance(mTargetActivity);
+        mImm = InputMethodManager.getInstance();
 
         KeyguardManager keyguardManager =
             (KeyguardManager) getInstrumentation().getContext().getSystemService(
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
index 434d592..7a578d9 100644
--- a/tests/RenderScriptTests/FBOTest/Android.mk
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -23,4 +23,6 @@
 
 LOCAL_PACKAGE_NAME := FBOTest
 
+LOCAL_SDK_VERSION := 17
+
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/Fountain/Android.mk b/tests/RenderScriptTests/Fountain/Android.mk
index 4a6560b..0517aef 100644
--- a/tests/RenderScriptTests/Fountain/Android.mk
+++ b/tests/RenderScriptTests/Fountain/Android.mk
@@ -21,8 +21,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
-# TODO: build fails with this set
-# LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 17
 
 LOCAL_PACKAGE_NAME := RsFountain
 
diff --git a/tests/RenderScriptTests/HelloWorld/Android.mk b/tests/RenderScriptTests/HelloWorld/Android.mk
index 54824f4..c1c08ec 100644
--- a/tests/RenderScriptTests/HelloWorld/Android.mk
+++ b/tests/RenderScriptTests/HelloWorld/Android.mk
@@ -23,6 +23,6 @@
 
 LOCAL_PACKAGE_NAME := RsHelloWorld
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 17
 
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/MiscSamples/Android.mk b/tests/RenderScriptTests/MiscSamples/Android.mk
index bdff46a..ee3567b 100644
--- a/tests/RenderScriptTests/MiscSamples/Android.mk
+++ b/tests/RenderScriptTests/MiscSamples/Android.mk
@@ -23,6 +23,6 @@
 
 LOCAL_PACKAGE_NAME := RsMiscSamples
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 17
 
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ModelViewer/Android.mk b/tests/RenderScriptTests/ModelViewer/Android.mk
index 18ceac5..86724cf 100644
--- a/tests/RenderScriptTests/ModelViewer/Android.mk
+++ b/tests/RenderScriptTests/ModelViewer/Android.mk
@@ -22,6 +22,8 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
 
+LOCAL_SDK_VERSION := 17
+
 LOCAL_PACKAGE_NAME := ModelViewer
 
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/PerfTest/Android.mk b/tests/RenderScriptTests/PerfTest/Android.mk
index 0d1e7d2..e9ee771 100644
--- a/tests/RenderScriptTests/PerfTest/Android.mk
+++ b/tests/RenderScriptTests/PerfTest/Android.mk
@@ -24,6 +24,8 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
 
+LOCAL_SDK_VERSION := 17
+
 LOCAL_PACKAGE_NAME := PerfTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/SceneGraph/Android.mk b/tests/RenderScriptTests/SceneGraph/Android.mk
index 163a95d..6047305 100644
--- a/tests/RenderScriptTests/SceneGraph/Android.mk
+++ b/tests/RenderScriptTests/SceneGraph/Android.mk
@@ -21,6 +21,8 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
+LOCAL_SDK_VERSION := 17
+
 LOCAL_PACKAGE_NAME := SceneGraphTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ShadersTest/Android.mk b/tests/RenderScriptTests/ShadersTest/Android.mk
index 0912591..fb6356e 100644
--- a/tests/RenderScriptTests/ShadersTest/Android.mk
+++ b/tests/RenderScriptTests/ShadersTest/Android.mk
@@ -21,6 +21,8 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
+LOCAL_SDK_VERSION := 17
+
 LOCAL_PACKAGE_NAME := ShadersTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index 5d0b155..9862116 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -49,6 +49,8 @@
 {
     private final static String TAG = "NotificationTestList";
 
+    private final static String NOTIFY_TAG = "foo";
+
     NotificationManager mNM;
     Handler mHandler;
     int mStartDelay;
@@ -117,34 +119,34 @@
         public void onClick(View v) {
             switch (v.getId()) {
                 case R.id.clear_1:
-                    mNM.cancel(1);
+                    cancelNotification(1);
                     break;
                 case R.id.clear_2:
-                    mNM.cancel(2);
+                    cancelNotification(2);
                     break;
                 case R.id.clear_3:
-                    mNM.cancel(3);
+                    cancelNotification(3);
                     break;
                 case R.id.clear_4:
-                    mNM.cancel(4);
+                    cancelNotification(4);
                     break;
                 case R.id.clear_5:
-                    mNM.cancel(5);
+                    cancelNotification(5);
                     break;
                 case R.id.clear_6:
-                    mNM.cancel(6);
+                    cancelNotification(6);
                     break;
                 case R.id.clear_7:
-                    mNM.cancel(7);
+                    cancelNotification(7);
                     break;
                 case R.id.clear_8:
-                    mNM.cancel(8);
+                    cancelNotification(8);
                     break;
                 case R.id.clear_9:
-                    mNM.cancel(9);
+                    cancelNotification(9);
                     break;
                 case R.id.clear_10:
-                    mNM.cancel(10);
+                    cancelNotification(10);
                     break;
                 case R.id.notify_1:
                     sendNotification(1);
@@ -196,11 +198,15 @@
         final Notification n = buildNotification(id);
         mHandler.postDelayed(new Runnable() {
             public void run() {
-                mNM.notify(id, n);
+                mNM.notify(NOTIFY_TAG, id, n);
             }
         }, mStartDelay);
     }
 
+    private void cancelNotification(final int id) {
+        mNM.cancel(NOTIFY_TAG, id);
+    }
+
     private static CharSequence subst(CharSequence in, char ch, CharSequence sub) {
         int i=0;
         SpannableStringBuilder edit = new SpannableStringBuilder(in);
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 4345098..ba160b18 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -33,13 +33,10 @@
 import android.net.Uri;
 import android.os.SystemClock;
 import android.widget.RemoteViews;
-import android.widget.TextView;
-import android.widget.ProgressBar;
 import android.os.PowerManager;
 
 // private NM API
 import android.app.INotificationManager;
-import com.android.internal.statusbar.StatusBarNotification;
 
 public class NotificationTestList extends TestActivity
 {
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 84f5a5c..cadac02 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -592,6 +592,10 @@
                         goto bail;
                     }
                     printf("uses-permission: %s\n", name.string());
+                    int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
+                    if (!req) {
+                        printf("optional-permission: %s\n", name.string());
+                    }
                 }
             }
         } else if (strcmp("badging", option) == 0) {
@@ -1033,6 +1037,10 @@
                                 hasWriteCallLogPermission = true;
                             }
                             printf("uses-permission:'%s'\n", name.string());
+                            int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
+                            if (!req) {
+                                printf("optional-permission:'%s'\n", name.string());
+                            }
                         } else {
                             fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
                                     error.string());
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
index 7a6e52e..dc4f9c8 100644
--- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
@@ -22,6 +22,6 @@
 public class InputMethodManager_Accessor {
 
     public static void resetInstance() {
-        InputMethodManager.mInstance = null;
+        InputMethodManager.sInstance = null;
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
index f056040..7c98847 100644
--- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
@@ -35,28 +35,15 @@
     // ---- Overridden methods ----
 
     @LayoutlibDelegate
-    /*package*/ static InputMethodManager getInstance(Looper mainLooper) {
-        synchronized (InputMethodManager.mInstanceSync) {
-            if (InputMethodManager.mInstance != null) {
-                return InputMethodManager.mInstance;
+    /*package*/ static InputMethodManager getInstance() {
+        synchronized (InputMethodManager.class) {
+            InputMethodManager imm = InputMethodManager.peekInstance();
+            if (imm == null) {
+                imm = new InputMethodManager(
+                        new BridgeIInputMethodManager(), Looper.getMainLooper());
+                InputMethodManager.sInstance = imm;
             }
-
-            InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
-                    mainLooper);
+            return imm;
         }
-        return InputMethodManager.mInstance;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static InputMethodManager getInstance(Context context) {
-        synchronized (InputMethodManager.mInstanceSync) {
-            if (InputMethodManager.mInstance != null) {
-                return InputMethodManager.mInstance;
-            }
-
-            InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
-                    Looper.myLooper());
-        }
-        return InputMethodManager.mInstance;
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index f109e39..cbefd3d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -232,7 +232,7 @@
         sCurrentContext = mContext;
 
         // create an InputMethodManager
-        InputMethodManager.getInstance(Looper.myLooper());
+        InputMethodManager.getInstance();
 
         LayoutLog currentLog = mParams.getLog();
         Bridge.setLog(currentLog);